--- /dev/null
+libem_s.a
+aar.s
+lar.s
+sar.s
+csa.s
+csb.s
+shp.s
+set.s
+inn.s
+fat.s
+trp.s
+mon.s
+nop.s
+dia.s
+printf.s
+cii.s
+cuu.s
+cmi.s
+cms.s
+cmu.s
+cvf.s
+exg.s
+los.s
+sts.s
--- /dev/null
+# $Header$
+MACH=m68020
+all: libem_o.a end.o
+
+install: all
+ ../../install libem_o.a tail_em
+ ../../install end.o end_em
+
+cmp: all
+ -../../compare libem_o.a tail_em
+ -../../compare end.o end_em
+
+end.o: end.s
+ $(MACH) -I../../../h -c end.s
+
+libem_o.a: libem_s.a
+ ASAR=aal ; export ASAR ;\
+ march . libem_o.a
+
+clean:
+ rm -f *.o libem_o.a
+
+opr :
+ make pr | opr
+
+pr:
+ @arch pv libem_s.a | pr -h `pwd`/libem_s.a
+ @pr `pwd`/end.s
--- /dev/null
+.define .aar
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+.aar: ! (on entry d0 contains the integer size in the descriptor)
+
+ cmp.l #4, d0
+ beq 9f
+ move.l #EILLINS, -(sp)
+ jmp (.fatal)
+9:
+ ! register usage:
+ ! a0: descriptor address
+ ! a1: return address
+ ! d0: index
+
+ ! The address is calculated by taking the relative index
+ ! (index - lower bound), multiplying that with the element
+ ! size and adding the result to the array base address.
+
+ move.l (sp)+, a1 ! return address
+ move.l (sp)+, a0 ! descriptor address
+ move.l (sp)+, d0 ! index
+ sub.l (a0), d0 ! relative index
+ muls.l (8,a0), d0
+ move.l (sp)+, a0 ! array base address
+ add.l d0, a0 ! address of array element
+ jmp (a1) ! return
+.align 2
--- /dev/null
+.define .cii
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+.cii:
+ move.l (sp)+, a0 ! return address
+ move.l (sp)+, d0 ! destination size
+ sub.l (sp)+, d0 ! destination - source size
+ bgt 1f
+ sub.l d0, sp ! pop extra bytes
+ jmp (a0)
+1:
+ clr.l d1
+ tst.l (sp)
+ bne 4f
+ not.l d1 ! d1 contains sign of source
+4:
+ asr.l #2, d0
+ sub.l #1, d0
+2:
+ move.l d1, -(sp)
+ dbf d0, 2b
+ jmp (a0)
+.align 2
--- /dev/null
+.define .cmi
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! on entry d0: # bytes in 1 block
+ ! on exit d0: result
+.cmi:
+ move.l (sp)+, d2 ! return address
+ move.l sp, a0 ! address of top block
+ lea (sp,d0.l), a1 ! address of lower block
+ move.l d0, d1
+ asr.l #2, d0
+1:
+ cmp.l (a0)+, (a1)+
+ bne 2f
+ sub.l #1, d0
+ bne 1b
+2:
+ bge 3f
+ neg.l d0 ! less
+3:
+ lea (sp,d1.l*2), sp ! new sp; two blocks popped
+ move.l d2,a0
+ jmp (a0) ! return
+.align 2
--- /dev/null
+.define .cms
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! d0 contains set size
+ ! on exit d0 is zero for equal, non-zero for not equal
+.cms:
+ move.l (sp)+, d2 ! return address
+ move.l sp, a0 ! address of top block
+ lea (sp,d0.l), a1 ! address of lower block
+ move.l d0, d1
+ asr.l #2, d0
+1:
+ cmp.l (a0)+, (a1)+
+ bne 2f
+ sub.l #1, d0
+ bne 1b
+2:
+ lea (sp,d1.l*2), sp ! new sp; two blocks popped
+ move.l d2,a0
+ jmp (a0)
+.align 2
--- /dev/null
+.define .cmu
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! on entry d0: # bytes in 1 block
+ ! on exit d0: result
+.cmu:
+ move.l (sp)+, d2 ! return address
+ move.l sp, a0 ! address of top block
+ lea (sp,d0.l), a1 ! address of lower block
+ move.l d0, d1
+ asr.l #2, d0
+1:
+ cmp.l (a0)+, (a1)+
+ bne 2f
+ sub.l #1, d0
+ bne 1b ! note: on equal carry is set
+2:
+ bcc 3f
+ neg.l d0 ! less
+3:
+ lea (sp,d1.l*2), sp ! new sp; two blocks popped
+ move.l d2, a0
+ jmp (a0)
+.align 2
--- /dev/null
+if ${MACH?} -c $1 1>&2
+then echo `basename $1 $2`.o
+else exit 1
+fi
--- /dev/null
+.define .csa
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+.csa:
+ move.l (sp)+, a0 ! jump table address
+ move.l (a0)+, a1 ! default address
+ move.l (sp)+, d0 ! index
+ sub.l (a0)+, d0 ! index - lower bound
+ blt 1f
+ cmp.l (a0)+, d0 ! rel. index, upper - lower bound
+ bgt 1f
+ move.l (a0,d0.l*4), a1 ! jump address
+1:
+ move.l a1, d0
+ beq 2f
+ jmp (a1) ! jump to specified address
+2:
+ move.l #ECASE, -(sp)
+ jmp (.fatal)
+.align 2
--- /dev/null
+.define .csb
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+.csb:
+ move.l (sp)+, a0 ! case descriptor
+ move.l (sp)+, d0 ! index
+ move.l (a0)+, a1 ! default jump address
+ move.l (a0)+, d1 ! # entries
+ beq 3f
+ sub.l #1, d1
+1:
+ cmp.l (a0,d1.w*8), d0
+ dbeq d1, 1b
+ bne 3f
+ move.l (4,a0,d1.w*8), a1 ! jump address
+3:
+ move.l a1, d0
+ beq 4f
+ jmp (a1)
+4:
+ move.l #ECASE, -(sp)
+ jmp (.fatal)
+.align 2
--- /dev/null
+.define .ciu, .cui, .cuu
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! only converts between sizes of multiples of four
+.ciu:
+.cui:
+.cuu:
+ move.l (sp)+, a0 ! return address
+ move.l (sp)+, d0 ! destination size
+ sub.l (sp)+, d0
+ bgt 1f
+ sub.l d0, sp
+ jmp (a0)
+1:
+ asr.l #2, d0
+ sub.l #1, d0
+2:
+ clr.l -(sp)
+ dbf d0, 2b
+ jmp (a0)
+.align 2
--- /dev/null
+.define .cfi, .cif,.cfu,.cuf,.cff
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ .sect .text
+
+ ! this is a dummy float conversion routine
+.cfi:
+.cif:
+.cfu:
+.cuf:
+.cff:
+ move.l (sp)+, a0 ! return address
+ move.l (sp)+, d0 ! destination size
+ sub.l (sp)+, d0 ! diff. in sizes
+ sub.l d0, sp
+ jmp (a0)
+.align 2
--- /dev/null
+.define .diagnos
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+space = 040
+del = 0177
+
+.sect .data
+.range: .data1 space, del-1
+.align 2
+
+.sect .text
+.diagnos:
+ movem.l d0/d1/d2/a0, -(sp)
+ move.l (.lino), -(sp)
+ move.l (.filn), d2
+ beq 1f
+ move.l d2, a0
+ move.l #40, d0
+3:
+ move.b (a0)+, d1
+ beq 2f
+ cmp2.b (.range), d1
+ bcs 1f
+ dbf d0, 3b
+2:
+ move.l d2, -(sp)
+ pea (fmt)
+ jsr (_printf)
+ lea (8, sp), sp
+ move.l (28, sp), (sp)
+ jsr (_printf)
+ lea (4, sp), sp
+ movem.l (sp)+, d0/d1/d2/a0
+ move.l (sp), (4, sp)
+ lea (4, sp), sp
+ rts
+
+1:
+ move.l #unknwn, d2
+ bra 2b
+
+.sect .data
+fmt: .asciz "%s, line %d: "
+unknwn: .asciz "unknown file"
+.align 2
--- /dev/null
+.define endtext,enddata,endbss,_etext,_edata,_end
+.sect .text
+ .align 4
+.sect .rom
+ .align 4
+.sect .data
+ .align 4
+.sect .bss
+ .align 4
+.sect .end ! only for declaration of _end and endbss.
+
+ .sect .text
+endtext:
+_etext:
+ .sect .data
+enddata:
+_edata:
+ .sect .end
+_end:
+endbss:
--- /dev/null
+.define .exg
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! d0 : exchange size in bytes
+.exg:
+ lea (4,sp,d0), a0 ! address of bottom block
+ lea (4,sp), a1 ! address of top block
+ asr.l #2, d0
+ sub.l #1, d0
+1:
+ move.l (a1), d1
+ move.l (a0), (a1)+
+ move.l d1, (a0)+
+ dbf d0, 1b
+ rts
+.align 2
--- /dev/null
+.define .fatal
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ .sect .text
+.fatal:
+ jsr (.trp)
+ jmp (EXIT)
+.align 2
--- /dev/null
+.define .inn
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+.inn: ! d0 bitnumber
+ ! d1 setsize in bytes
+ ! on exit: 0 or 1 in d0
+
+ move.l d2, -(sp)
+ move.l d0, d2
+ asr.l #3, d2 ! offset from sp in bytes
+ eor.l #3, d2 ! longs are stored in high-to-low order
+ cmp.l d1, d2
+ bge 1f ! bitnumber too large
+ btst d0, (8,sp,d2.l)
+ beq 2f
+ move.l #1, d0
+ bra 3f
+1:
+ move.l #ESET, -(sp)
+ jsr (.trp)
+2:
+ clr.l d0
+3:
+ move.l (sp)+, d2
+ move.l (sp)+, a0 ! return address
+ add.l d1, sp ! pop bitset
+ jmp (a0) ! return
+.align 2
--- /dev/null
+.define .lar
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+ ! (on entry d0 contains the integer size in the descriptor)
+.lar:
+ cmp.l #4, d0
+ beq 9f
+ move.l #EILLINS, -(sp)
+ jmp (.fatal)
+9:
+ ! register usage:
+ ! a0: descriptor address
+ ! a1: base address
+ ! d0: index
+ ! d1: # bytes / element
+ ! d2: save return address
+
+ ! For address calculation; see comment in 'aar.s'.
+
+ move.l (sp)+, d2 ! return address
+ move.l (sp)+, a0 ! descriptor address
+ move.l (sp)+, d0 ! index
+ move.l (sp)+, a1 ! array base address
+ sub.l (a0), d0 ! relative index
+ move.l (8,a0), d1 ! # bytes / element
+ cmp.l #1, d1
+ bne 2f
+ clr.l -(sp)
+ move.b (a1,d0.l), (3,sp) ! one byte element
+ bra 5f
+2:
+ cmp.l #2, d1
+ bne 4f
+ clr.l -(sp)
+ move.w (a1,d0.l*2), (2,sp) ! two byte element
+ bra 5f
+4:
+ muls.l d1, d0
+ add.l d0, a1 ! address of 4n byte element
+ add.l d1, a1 ! because of predecrement
+ asr.l #2, d1
+ sub.l #1, d1
+1:
+ move.l -(a1), -(sp)
+ dbf d1, 1b
+5:
+ move.l d2,a0
+ jmp (a0)
+.align 2
--- /dev/null
+.define .los
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ ! d0 : # bytes
+ ! a0 : source address
+ ! a1 : return address
+.sect .text
+.los:
+ move.l (sp)+, a1
+ move.l (sp)+, d0
+ move.l (sp)+, a0
+ cmp.l #1, d0
+ bne 1f
+ clr.l -(sp)
+ move.b (a0), (3,sp) !1 byte
+ bra 3f
+1:
+ cmp.l #2, d0
+ bne 2f
+ clr.l -(sp)
+ move.w (a0), (2,sp) !2 bytes
+ bra 3f
+2:
+ add.l d0, a0 !>=4 bytes
+ asr.l #2, d0
+ sub.l #1, d0
+
+4: move.l -(a0), -(sp)
+ dbf d0, 4b
+3:
+ jmp (a1)
+.align 2
--- /dev/null
+.define .mon
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+.mon:
+ move.l (sp)+,a0
+ pea (fmt)
+ jsr (.diagnos)
+ add.l #8, sp
+ jmp (EXIT)
+
+.sect .data
+fmt: .asciz "system call %d not implemented\n"
+.align 2
--- /dev/null
+.define .nop
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+.nop:
+ move.l (.limhp),-(sp)
+ move.l (.reghp),-(sp)
+ pea (12, sp)
+ move.l (.lino),-(sp)
+ pea (fmt)
+ jsr (.diagnos)
+ lea (20, sp), sp
+ rts
+
+.sect .data
+fmt: .asciz "test %d, sp 0x%x, .reghp 0x%x, .limhp 0x%x.\n"
+.align 2
--- /dev/null
+.define _printf, _putchar, _getal, _char
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .bss
+_getal:
+ .space 12
+_char:
+ .space 1
+ .align 2
+.sect .data
+hexs:
+ .ascii "0123456789abcdef"
+ .align 2
+.sect .text
+_printf:
+ movem.l d0/d1/d2/a0/a1/a2/a3/a4/a5/a6, -(sp)
+ lea (44, sp), a6 ! a6 <- address of arguments
+ move.l (a6)+, a5 ! a5 <- address of format
+next: move.b (a5)+, d0
+ beq out
+ cmp.b #'%', d0
+ beq procnt
+put: move.l d0, -(sp)
+ jsr (_putchar) ! long argument on stack
+ tst.l (sp)+
+ bra next
+
+procnt: move.b (a5)+, d0
+ cmp.b #'d', d0 ! NOTE: %d means unsigned.
+ beq digit
+ cmp.b #'x', d0
+ beq hex
+ cmp.b #'s', d0
+ beq string
+ cmp.b #'%', d0 ! second % has to be printed.
+ beq put
+ tst.b -(a5) ! normal char should be printed
+ bra next
+
+string: move.l (a6)+, a2 ! a2 <- address of string
+sloop: move.b (a2)+, d0
+ beq next
+ move.l d0, -(sp)
+ jsr (_putchar) ! long argument on stack
+ tst.l (sp)+
+ bra sloop
+
+digit: move.l (a6)+, d1 ! d1 <- integer
+ move.l #_getal+12, a2 ! a2 <- ptr to last part of buf
+ clr.b -(a2) ! stringterminator
+1: divul.l #10, d2:d1 ! d1 <- qotient; d2 <- remainder
+ add.l #'0', d2
+ move.b d2, -(a2)
+ tst.l d1 ! if quotient = 0 then ready
+ bne 1b
+ bra sloop ! print digitstring.
+
+hex: move.l (a6)+, d1 ! d1 <- integer
+ move.l #_getal+12, a2 ! a2 <- ptr to last part of buf
+ clr.b -(a2) ! stringterminator
+ move.l #7, d2 ! loop control
+1: move.l d1, d0
+ and.l #15, d0
+ move.b (hexs,d0.w), -(a2) ! hex digit
+ asr.l #4, d1
+ dbf d2, 1b
+ bra sloop
+
+out:
+ movem.l (sp)+, d0/d1/d2/a0/a1/a2/a3/a4/a5/a6
+ rts
+
+
+_putchar:
+ move.l #1, -(sp)
+ pea (11,sp)
+ move.l #1, -(sp)
+ jsr (_write)
+ lea (12, sp), sp
+ rts
+.align 2
--- /dev/null
+.define .sar
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+ ! (on entry d0 contains the integer size in the descriptor)
+.sar:
+ cmp.l #4, d0
+ beq 9f
+ move.l #EILLINS, -(sp)
+ jmp (.fatal)
+9:
+ ! register usage:
+ ! a0: descriptor address
+ ! a1: base address
+ ! d0: index
+ ! d1: # bytes / element
+ ! d2: return address
+
+ ! For address calculation; see comment in 'aar.s'.
+ ! If the element size is a fraction of EM_WSIZE (4)
+ ! the calculation is done by adding.
+
+ move.l (sp)+, d2 ! return address
+ move.l (sp)+, a0
+ move.l (sp)+, d0
+ move.l (sp)+, a1
+ sub.l (a0), d0
+ move.l (8,a0), d1 ! # bytes / element
+ cmp.l #1, d1
+ bne 2f
+ move.l (sp)+, d1
+ move.b d1, (a1,d0.l) ! store one byte element
+ bra 5f
+2:
+ cmp.l #2, d1
+ bne 4f
+ move.l (sp)+, d1
+ move.w d1, (a1,d0.l*2) ! store two byte element
+ bra 5f
+4: ! here: 4n byte element
+ muls.l d1, d0
+ add.l d0, a1 ! address of 4n byte element
+ asr.l #2, d1
+ sub.l #1, d1
+1:
+ move.l (sp)+, (a1)+
+ dbf d1, 1b
+5:
+ move.l d2,a0
+ jmp (a0)
+.align 2
--- /dev/null
+.define .set
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+.sect .text
+
+.set: ! d0 bitnumber
+ ! d1 setsize in bytes
+
+ move.l (sp)+, a0
+ move.l d2, a1
+ move.l d1, d2
+ asr.l #2, d2
+ sub.l #1, d2
+1:
+ clr.l -(sp)
+ dbf d2, 1b
+
+ move.l d0, d2
+ asr.l #3, d2 ! offset from sp in bytes
+ eor.l #3, d2 ! longs are stored in high-to-low order
+ cmp.l d1, d2
+ blt 2f
+ move.l #ESET, -(sp) ! bitnumber too large
+ move.l a1, d2
+ move.l a0, -(sp)
+ jmp (.trp)
+2:
+ bset d0, (sp, d2.l)
+ move.l a1, d2
+ jmp (a0) ! return
+.align 2
--- /dev/null
+.define .strhp
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ .sect .text
+.strhp:
+ move.l (sp)+, a0
+ move.l (sp), d1 ! new heap pointer
+ cmp.l (.limhp), d1 ! compare new heap pointer with limit
+ blt 1f
+ add.l #0x400, d1
+ and.l #~0x3ff, d1
+ move.l d1, (.limhp)
+ move.l d1, -(sp)
+ jsr (_brk) ! allocate 1K bytes of extra storage
+ add.l #4, sp
+ bcs 2f
+1:
+ move.l (sp)+, (.reghp) ! store new value
+ jmp (a0) ! return
+2:
+ move.l #EHEAP, -(sp)
+ jmp (.fatal)
+.align 2
--- /dev/null
+.define .sts
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ ! d0 : # bytes
+ ! a0 : destination address
+ ! a1 : return address
+.sect .text
+.sts:
+ move.l (sp)+, a1
+ move.l (sp)+, d0
+ move.l (sp)+, a0
+ cmp.l #1, d0
+ bne 1f
+ move.l (sp)+, d0
+ move.b d0, (a0)
+ bra 4f
+
+1: cmp.l #2, d0
+ bne 2f
+ move.l (sp)+, d0
+ move.w d0, (a0)
+ bra 4f
+2:
+ asr.l #2, d0
+ sub.l #1, d0
+3:
+ move.l (sp)+, (a0)+
+ dbf d0, 3b
+4:
+ jmp (a1) ! return
+.align 2
--- /dev/null
+.define .trp
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+ .sect .text
+.trp:
+ movem.l d0/d1/a0, -(sp)
+ move.l (16, sp), a0 ! return address
+ move.l (20, sp), d0 ! error number
+ move.l a0, (20, sp)
+ move.l d0, (16, sp)
+ move.l d0,-(sp)
+ cmp.l #16, d0
+ bcc 1f
+ move.l (.trpim), d1
+ btst d0, d1
+ bne 3f
+1:
+ move.l (.trppc), a0
+ move.l a0, d0
+ beq 9f
+ clr.l (.trppc)
+ jsr (a0)
+3:
+ add.l #4, sp
+ movem.l (sp)+, d0/d1/a0
+ add.l #4, sp
+ rts
+9:
+ pea (fmt)
+ jsr (.diagnos)
+ lea (4, sp), sp
+ jsr (__cleanup)
+ jmp (EXIT)
+
+.sect .data
+fmt: .asciz "trap %d called\n"
+.align 2