1 eÿaaru.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ö
\0.define .aaru
25 aar.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ò
\ 2.define .aar
33 ! 2-byte descriptor elements
34 ! any size array elements
37 ! stack: pointer to descriptor
39 ! base address of array
42 ! side-effect: size of array elements in bc
47 pop hl ! return address
48 pop ix ! pointer to descr.
49 ex (sp),hl ! save ret. addr.
51 ld c,(ix+0) ! bc := lower bound
54 sbc hl,bc ! hl := index-lwb
55 ld c,(ix+4) ! bc := size
57 ex de,hl ! de := index-lwb
58 call .mli2 ! hl := bc*de =
60 pop ix ! return address
62 add hl,de ! addr. of element
65 aar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ã
\ 1.define .aar2
72 ! special case aar: element size = 2 (statically known)
75 ! execution time: 124 states
80 pop ix ! save return address
81 pop hl ! pointer to descriptor
82 ld c,(hl) ! bc := lower bound
87 sbc hl,bc ! index - lwb
88 add hl,hl ! size*(index-lwb)
89 pop de ! base address of array
93 eand.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0î
\ 1.define .and
100 ! auxiliary size 'and'
104 ! stack: result (out)
109 pop ix ! save return address
114 add hl,de ! now hl is the base of second
115 ld b,d ! operand. bc and de are base
116 ld c,e ! of the first operand
133 cii.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0e
\f.define .cii
141 ! cii: convert integer to integer
143 ! stack: destination size
146 ! stack: result (out)
147 ! This code is also used by cuu.
148 ! The contents of the a-register determines
149 ! if we're doing a cii (a=0) or a cuu (a=1),
150 ! so be very careful with this register!
155 pop ix ! return address
156 pop hl ! destination size
158 ld b,h ! bc := destination size
160 xor a ! watch it, this is dirty!
161 ! Besides clearing the carry
162 ! this instruction sets a-reg.
163 ! to 0, to indicate this is
164 ! a cii and not a cuu.
165 sbc hl,de ! hl := destination size
167 jr z,1f ! equal, return
168 jp p,2f ! larger, expand
170 ! The most significant part of the source
171 ! is removed. As the least sign. part is
172 ! on top of the stack, we have to move an
175 add hl,sp ! note that hl < 0
176 ! (also come here via cuu)
178 dec hl ! now hl points to most
179 ! significant byte of what
180 ! will be left over of source
184 dec de ! now de points to highest
186 lddr ! move 'destination size'
187 ! bytes upwards (i.e. away
191 ld sp,hl ! adjust stackpointer
197 ! A number of bytes (containing the signbits
198 ! of the source) is inserted before the most
199 ! significant byte of the source.
200 ! As this byte is somewhere in the middle of
201 ! the stack, the entire source must first be
202 ! moved downwards (in the direction of the
205 ld b,d ! bc := source size
206 ! (also come here via cuu)
208 ex de,hl ! de := difference (> 0)
211 dec de ! if difference = 1, don't adjust stack pointer
220 ex de,hl ! de := sp - difference
225 ldir ! move source upwards,
228 ! now we will fill the hole with bytes
229 ! containing either 0 or -1, depending
230 ! on the signbit of the source.
233 ex de,hl ! de := difference
234 dec hl ! now hl points to
235 ! most significant byte
238 or a ! see if we're doing
240 jr nz,3f ! cuu, expand with zeroes
241 bit 7,(hl) ! test signbit
243 dec b ! b := -1 (was 0 after ldir)
246 ld (hl),b ! either 0 or -1
256 ! cuu: convert unsigned to unsigned
258 ! stack: destination size
261 ! stack: result (out)
262 ! The only difference between a cuu and a cii is:
263 ! if the destination is larger than the source,
264 ! the former extends with zeroes and the latter
265 ! extends with sign bits
266 ! cuu uses the code of cii. In this case it puts
267 ! a '1' in the accumulator to indicate this is
280 jr z,1b ! equal, return
281 jp m,9b ! smaller, shrink
283 jr 8b ! larger, expand
284 \0cms.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0d
\ 1.define .cms
294 ! stack: second operand
296 ! stack: result (out)
322 cmu.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ý
\ 5.define .cmu
331 ! stack: second operand
333 ! stack: result (out)
338 ! The two operands are compared byte by byte,
339 ! starting at the highest byte, until
341 pop ix ! return address
346 dec hl ! pointer to highest byte
350 add hl,bc ! pointer to highest byte
352 ld sp,hl ! points to where the
353 ! result will be stored
355 ! now, de points to highest byte of 1st operand
361 ! loop, compare the two operands
364 xor (hl) ! Avoid overflow during
365 ! subtraction. If the
366 ! signbits differ, then
367 ! the operands differ.
368 jp m,2f ! signbits differ
369 ld a,(de) ! signbits are equal,
373 jr nz,1f ! operands are different
374 dec de ! the two bytes are the
375 ! same, try next bytes,
377 dec hl ! bump pointers
381 jr nz,0b ! no, try next bytes
382 ! yes, then the two operands are equal.
385 ld h,a ! hl := result
389 ! the signbits differ
390 ld h,(hl) ! hl := positive if
392 ! byte of 2nd operand
393 ! is "0", else negative
394 ld l,1 ! just in case (hl)=0
396 ex (sp),hl ! sp was set above
398 cmu4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0}
\ 2.define .cmu4
405 ! 4 byte cmu and cmi routine
407 ! a: 0 for cmu, 1 for cmi
425 ld (savesp),hl ! save new sp-1
463 acsa.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\03
\ 2.define .csa
470 ! this is not a subroutine, but just a
471 ! piece of code that computes the jump-
472 ! address and jumps to it.
473 ! traps if resulting address is zero
512 :csb.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0¦
\ 3.define .csb
519 ! this is not a subroutine, but just a
520 ! piece of code that computes the jump-
521 ! address and jumps to it.
522 ! traps if resulting address is zero
527 pop hl ! pointer to descriptor
529 ld c,(hl) ! bc := default offset
533 push bc ! save default on stack
534 ld c,(hl) ! bc := #entries
539 ! loop, try to find the case index
543 jr z,noteq ! done, index not found
544 ld a,(hl) ! is de=(hl) ?
552 ld a,(hl) ! yes, get jump address
556 pop af ! remove default
559 inc hl ! skip high byte of index
561 inc hl ! skip jump address
566 pop hl ! take default exit
568 ld a,l ! jump address is zero?
570 jr z,.trp.z ! yes, trap
572 dvi2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0"
\ 2.define .dvi2
579 ! 16-bit signed division
584 ! no check on overflow
633 dvi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0%
\ 4.define .dvi4
640 ! 4-byte divide routine for z80
644 ! stack: quotient (out)
645 ! bc de: remainder (out) (high part in bc)
657 ld b,(ix+7) ! dividend
723 edvu2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ø
\ 1.define .dvu2
735 ! hl: remainder (out)
736 ! no overflow detection
771 dvu4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ø
\f.define .dvu4
778 ! 4-byte divide routine for z80
782 ! stack: quotient (out)
783 ! bc de: remainder (out) (high part in bc)
787 ! a n-byte divide may be implemented
788 ! using 2 (virtual) registers:
789 ! - a n-byte register containing
791 ! - a 2n-byte shiftregister (VSR)
793 ! Initially, the VSR contains the dividend
794 ! in its low (right) n bytes and zeroes in its
795 ! high n bytes. The dividend is shifted
796 ! left into a "window" bit by bit. After
797 ! each shift, the contents of the window
798 ! is compared with the divisor. If it is
799 ! higher or equal, the divisor is subtracted from
800 ! it and a "1" bit is inserted in the
801 ! VSR from the right side! else a "0" bit
802 ! is inserted. These bits are shifted left
803 ! too during subsequent iterations.
804 ! At the end, the rightmost part of VSR
805 ! contains the quotient.
806 ! For n=4, we need 2*4+4 = 12 bytes of
807 ! registers. Unfortunately we only have
808 ! 5 2-byte registers on the z80
809 ! (bc,de,hl,ix and iy). Therefore we use
810 ! an overlay technique for the rightmost
811 ! 4 bytes of the VSR. The 32 iterations
812 ! are split up into two groups: during
813 ! the first 16 iterations we use the high
814 ! order 16 bits of the dividend! during
815 ! the last 16 iterations we use the
817 ! register allocation:
822 pop hl ! save return address
824 pop bc ! low part (2 bytes)
826 xor a ! clear carry, a := 0
829 ld (.flag),a ! first pass main loop
830 pop de ! high part divisor
831 sbc hl,de ! inverse of high part
832 ex de,hl ! of divisor in de
833 pop hl ! save low part of
835 ld (.low),hl ! used during second
836 ! iteration over main loop
837 pop ix ! high part of dividend
841 ld iy,0 ! now the VSR is initialized
843 ! main loop, done twice
846 ! sub-loop, done 16 times
848 add iy,iy ! shift VSR left
854 or a ! subtract divisor from
858 jr nc,4f ! decrement iy if there
862 add iy,de ! there is no "sbc iy,ss"
863 ! on the z80, so de was
864 ! inverted during init.
866 ! see if the result is non-negative,
867 ! otherwise undo the subtract.
868 ! note that this uncooperating machine
869 ! does not set its S -or Z flag after
871 ex (sp),iy ! does anyone see a better
872 ex (sp),hl ! solution ???
884 ld a,(.flag) ! see if this was first or
885 ! second iteration of main loop
886 or a ! 0=first, 1=second
889 ld (.flag),a ! flag := 1
890 ld (.result),ix ! save high part of result
891 ld ix,(.low) ! initialize second
892 ! iteration, ix := low
897 push iy ! transfer remainder
898 pop bc ! from iy-hl to bc-de
901 ld hl,(.result) ! high part of result
903 push ix ! low part of result
913 exg.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\r\ 1.define .exg
943 gto.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\1d\ 1.define .gto
970 lhulp.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Æ
\ 2.sect .text
982 ld b,(ix+7) ! dividend
1037 ior.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0}
\ 1.define .ior
1044 ! auxiliary size 'ior'
1048 ! stack: result (out)
1075 .laru.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ö
\0.define .laru
1099 lar.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0µ
\ 2.define .lar
1107 ! 2-byte descriptor elements
1108 ! any size array elements
1113 ! adapted from .aar and .los
1131 add hl,de ! address of array element
1133 dec hl ! pointer to highest byte of element
1137 ld a,c ! skip check to save runtime
1139 jr nz,.trp.z ! size was odd but <> 1
1153 .lar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\8a\ 1.define .lar2
1160 ! special case lar: element size = 2 (statically known)
1163 ! adapted from .aar2
1164 ! execution time: 144 states
1177 add hl,hl ! size*(index-lwb)
1185 los.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0_
\ 2.define .los
1195 pop ix ! save return address
1196 pop de ! number of bytes to transfer
1197 pop hl ! address of lowest byte
1199 dec hl ! address of highest byte
1200 srl d ! divide de by 2
1202 jr nc,1f ! see if de was odd
1203 ld a,e ! yes, then it must be 1
1205 jr nz,.trp.z ! no, error
1206 ld e,(hl) ! pack 1 byte into integer
1210 ld b,(hl) ! get 2 bytes
1214 push bc ! put them on stack, most
1215 ! significant byte first
1220 jp (ix) ! yes, return
1221 dmli2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0m
\ 1.define .mli2
1233 ! multiplier (bc) is left unchanged
1234 ! no detection of overflow
1255 lmli4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0¿
\ 6.define .mli4
1262 ! 32-bit multiply routine for z80
1268 ! register utilization:
1269 ! ix: least significant 2 bytes of result
1270 ! hl: most significant 2 bytes of result
1271 ! bc: least significant 2 bytes of multiplicand
1272 ! de: most significant 2 bytes of multiplicand
1273 ! iy: 2 bytes of multiplier (first most significant,
1274 ! later least significant)
1278 pop hl ! return address
1280 ld (.mplier+2),de! least significant bytes of
1283 ld (.mplier),de ! most sign. bytes
1284 pop de ! least significant bytes of
1286 pop bc ! most sign. bytes
1287 push hl ! return address
1291 ld h,a ! clear result
1293 ld (.flag),a ! indicate that this is
1294 ! first pass of main loop
1296 ! main loop, done twice, once for each part (2 bytes)
1300 ! sub-loop, done 16 times
1302 add iy,iy ! shift left multiplier
1303 jr nc,3f ! skip if most sign. bit is 0
1304 add ix,de ! 32-bit add
1308 jr z,4f ! done with this part of multiplier
1309 add ix,ix ! 32-bit shift left
1313 ! see if we have just processed the first part
1314 ! of the multiplier (flag = 0) or the second
1320 ld (.flag),a ! set flag
1321 ld iy,(.mplier+2)! least significant 2 bytes now in iy
1322 add ix,ix ! 32-bit shift left
1328 ex (sp),hl ! put most sign. 2 bytes of result
1329 ! on stack! put return address in hl
1330 push ix ! least sign. 2 bytes of result
1335 rrck.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ÿ
\ 1.define .rck
1349 xor d ! check sign bit to catch overflow with subtract
1353 1: xor d ! now a equals (original) h again
1360 xor d ! check sign bit to catch overflow with subtract
1364 1: xor d ! now a equals (original) h again
1371 (rmi2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0(
\ 2.define .rmi2
1378 ! 16-bit signed remainder
1383 ! no check on overflow
1432 saru.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ö
\0.define .saru
1456 sar.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0O
\ 2.define .sar
1465 ! 2-byte descriptors
1466 ! any size array elements
1470 ! adapted from .aar and .sts
1489 srl b ! bc contains #bytes to transfer
1490 rr c ! divide bc by 2
1509 ,sar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0m
\ 1.define .sar2
1516 ! special case sar: element size = 2 (statically known)
1519 ! adapted from .aar2
1520 ! execution time: 143 states
1541 lsdf.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\1f\ 1.define .sdf
1548 ! store double offsetted
1553 pop ix ! return address
1567 sdl.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0´
\ 1.define .sdl
1574 ! store double local at any offset
1577 ! stack: operand (4 bytes)
1582 pop ix ! return address
1585 add hl,bc ! pointer to lowest byte
1587 pop bc ! low 2 bytes of source
1592 pop bc ! high 2 bytes of source
1598 set.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0û
\ 1.define .set
1610 ! stack: result (out)
1615 pop ix ! return address
1648 pstr.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0û
\0.define .strhp
1675 sts.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0V
\ 2.define .sts
1683 ! object size given by 2-byte integer on
1687 ! checks if #bytes is even or 1,
1693 pop ix ! save return address
1694 pop de ! # bytes to transfer
1695 pop hl ! destination address
1696 srl d ! divide de by 2
1698 jr nc,1f ! see if it was odd
1699 ld a,e ! yes, must be 1
1701 jr nz,.trp.z ! no, error
1702 pop de ! transfer 1 byte,
1703 ! padded with zeroes
1717 unim.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0b
\ 1.define unimpld, e.mon, e.rck, .trp.z, .unimpld
1725 unimpld: ! used in dispatch table to
1726 ! catch unimplemented instructions
1747 trp.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0¼
\ 2.define .trp.z
1754 ! changed into output routine to print errornumber
1759 pop hl !error number
1763 jp p,1f ! error no >= 16?
1765 push hl ! save error no on stack
1768 push hl ! test bit "error no" of ignmask
1779 jr z,2f ! if bit <> 0 error
1805 1: .asciz 'error xxxxx\r\n'
1807 inn.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\ 3\ 2.define .inn
1819 ! stack: result (out)
1862 lxor.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0~
\ 1.define .xor
1869 ! auxiliary size 'xor'
1873 ! stack: result (out)
1900 nop.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\0\ 2.define .nop
1910 ! changed into output routine to print linenumber
1911 ! in octal (6 digits)
1934 1: .asciz 'test xxxxx 0xxxxxx\r\n'
1953 outdec.s
\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Å
\ 2.define outdec
1959 ! output contents of HL as a sequence
1981 ! convert returns in a a count
1982 ! hl is decremented count times by (de)
1983 ! as a usefull side effect de is incremented
1994 push hl ! save pointer to new value
2011 ret.s
\0.s
\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0®
\ 2.define .ret
2019 ! 'ret' and 'lfr' for sizes > 4 (and <= 8)
2028 ! stack: return value
2030 pop ix ! save return address
2033 rr e ! divide size by 2
2044 jp (ix) ! yes, return
2049 ! result on stack: return value
2051 pop ix ! save return address
2055 rr e ! divide size by 2
2066 jp (ix) ! yes, return