1 e’aar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\19\ 3.define .aar2
8 ! Load address of array element, decriptor contains 2-bytes integers
9 ! Expects on stack: pointer to array descriptor
12 ! Yields on stack: address of array element
21 pop h ! hl = pointer to descriptor
23 mov a,e ! bc = index - lower bound
31 push b ! first operand to multiply
37 push b ! second operand to multiply
38 call .mli2 ! de = size * (index - lower bound)
39 pop h ! hl = base address
40 dad d ! hl = address of array[index]
48 \0adi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0l
\ 1.define .adi4
55 ! Add two 32 bits signed or unsigned integers
56 ! Expects on stack: operands
57 ! Yields on stack: result
60 shld .retadr ! get return address out of the way
76 and.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\e\ 2.define .and
83 ! Any size logical-'and'.
84 ! Expects: size in de-registers
86 ! Yields: result on stack
97 mov b,h !now bc points to top of first operand
98 dad d !and hl points to top of second perand
99 push h !this will be the new stackpointer
118 hblm.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0„
\ 1.define .blm
126 ! Expects in de-reg: size of block
127 ! Expects on stack: destination address
136 pop h ! hl = destination address
137 pop b ! bc = source address
154 ocii.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0"
\ 6.define .cii
161 ! Convert integer to integer
162 ! Expects in a-reg: 1 for signed integer to signed integer (cii)
163 ! 0 for unsigned integer to unsigned integer (cuu)
164 ! Expects on stack: destination size
167 ! Yields on stack: result
175 sta .areg ! save a-register
178 pop b ! c = source size
179 mov b,e ! b = destination size
182 jz 3f ! destination size = source size
183 jc shrink ! destination size < source size
185 ! if destination size > source size only:
189 mov d,h ! de = stackpointer
191 sub c ! c = (still) source size
192 mov b,a ! b = destination size - source size
197 dad d ! hl = stackpointer - (dest. size - source size)
198 sphl ! new stackpointer
200 1: ldax d ! move source downwards
207 ral ! a-reg still contains most significant byte of source
208 jnc 1f ! jump if is a positive integer
211 jz 1f ! jump if it is a cuu
212 mvi c,255 ! c-reg contains filler byte
220 !if destination size < source size only:
221 shrink: mov l,c ! load source size in hl
225 mov e,l ! de points just above source
226 mov l,b ! load destination size in hl
228 dad sp ! hl points just above "destination"
230 1: dcx d ! move upwards
243 cmi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\8e\ 4.define .cmi4
250 ! Compare 32 bits integers
251 ! Expects: operands on stack
252 ! a-register = 1 for signed integers
253 ! a-register = 0 for unsigned integers
254 ! Yields in de-registers: -1 if second operand < first operand
255 ! 0 if second operand = first operand
256 ! 1 if second operand > first operand
270 mov e,l !now de points to the first operand
271 dad b !and hl to the second
272 ora a !is it a cmi or cmu?
279 ldax d !second operand is negative
281 jc 1f !jump if both operands are negative
282 lxi d,-1 !second operand is smaller
284 2: ldax d !second operand is positive
286 jnc 1f !jump if both operand are positive
287 lxi d,1 !second operand is larger
290 !cmi and cmu rejoin here
295 lxi d,1 !second operand is larger
297 2: lxi d,-1 !second operand is smaller
303 lxi d,0 !operands are equal
314 cms.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0F
\ 2.define .cms
322 ! Expects: size in de-registers
324 ! Yields in de-registers: 0 if operands are equal
325 ! 1 if operands are not equal
335 cc eoddz !trap is size is odd
336 dad sp !now hl points to second operand
337 !and sp points to the first.
339 pop psw !get next byte in accumulator
343 jnz 2f !jump if bytes are not equal
354 com.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\17\ 1.define .com
361 ! Complement bytes on top of stack.
362 ! Expects in de-registers: number of bytes
379 csa.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ź
\ 3.define .csa
387 ! Expects on stack: address of case descriptor
389 ! This is not a subroutine, but just a piece of code that computes
390 ! the jump address and jumps to it.
391 ! Traps if resulting address is zero.
393 .csa: pop h !hl = address of case descriptor
395 push b !save localbase
400 push b !save default pointer on stack
408 mov b,a !bc = index - lower bound
409 jc 1f !get default pointer
416 jc 1f !upper-lower should be >= index-lower
418 dad b !hl now points to the wanted pointer
422 mov l,a !hl = pointer for index
424 jz 1f !get default pointer if pointer = 0
425 pop b !remove default pointer
429 1: pop h !get default pointer
433 pop b !restore localbase
436 csb.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\ 6\ 4.define .csb
444 ! Expects on stack: address of case descriptor
446 ! This is not a subroutine, but just a piece of code that computes
447 ! the jump address and jumps to it.
448 ! Traps if resulting address is zero.
450 .csb: pop h !hl = pointer to descriptor
451 pop d !de = case index
452 push b !save localbase
453 mov c,m !bc = default pointer
457 push b !save default on stack
458 mov c,m !bc = number of entries
462 !loop: try to find the case index in the descriptor
465 jz 4f !done, index not found
466 mov a,m !do we have the right index?
478 pop psw !remove default pointer
481 2: inx h !skip high byte of index
482 3: inx h !skip jump address
487 4: pop h !take default exit
488 5: pop b !restore localbase
489 mov a,l !jump address is zero?
494 dup.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ż
\ 1.define .dup
501 ! Duplicate top bytes of stack
502 ! Expects in de-registers: number of bytes to duplicate
504 .dup: mov a,e !trap if number is odd
523 dcx d !number of bytes must be a word-multiple i.e. even
533 vdvi2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0{
\a.define .dvi2
541 ! 16 bits signed and unsigned integer divide and remainder routine
542 ! Bit 0 of a-reg is set iff quotient has to be delivered
543 ! Bit 7 of a-reg is set iff the operands are signed, so:
544 ! Expects in a-reg: 0 if called by rmu 2
545 ! 1 if called by dvu 2
546 ! 128 if called by rmi 2
547 ! 129 if called by dvi 2
548 ! Expects on stack: divisor
550 ! Yields in de-reg: quotient or remainder
560 mov a,b ! trap if divisor = 0
563 pop d ! de = dividend
568 jnc 0f ! jump if unsigned
572 jnc 1f ! jump if dividend >= 0
573 mvi h,129 ! indicate dividend is negative
574 xra a ! negate dividend
584 jc 2f ! jump if divisor < 0
585 0: inr h ! indicate negation
586 xra a ! negate divisor
594 2: push h ! save h-reg
595 lxi h,0 ! initial value of remainder
596 mvi a,16 ! initialize loop counter
598 3: push psw ! save loop counter
599 dad h ! shift left: hl <- de <- 0
606 4: push h ! save remainder
607 dad b ! subtract divisor (add negative)
613 pop psw ! restore loop counter
617 pop b ! b-reg becomes what once was h-reg
619 rar ! what has to be delivered: quotient or remainder?
622 ! for dvi 2 and dvu 2 only:
625 jc 8f ! jump if divisor and dividend had same sign
626 xra a ! negate quotient
634 ! for rmi 2 and rmu 2 only:
637 jnc 7f ! negate remainder if dividend was negative
644 7: mov d,h ! return remainder
652 \0exg.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\89\ 2.define .exg
659 ! Exchange top bytes of stack
660 ! Expects in de-registers the number of bytes to be exchanged.
664 cc eoddz !trap if numer of bytes is odd
674 mov c,l !now bc points to first operand
675 dad d !and hl to the second
676 push d !place number of bytes on top of stack
682 xthl !caused by a lack of registers
683 dcx h !decrement top of stack
697 aflp.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0¼
\ 1.define .adf4,.adf8,.sbf4,.sbf8,.mlf4,.mlf8,.dvf4,.dvf8
698 .define .ngf4,.ngf8,.fif4,.fif8,.fef4,.fef8
700 .define .cfi,.cif,.cuf,.cff,.cfu
708 ! Floating point is not implemented
735 inn.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0³
\ 3.define .inn
742 ! Any size bit test on set.
743 ! Expects in de-reg: size of set (in bytes)
744 ! Expects on stack: bit number
746 ! Yields in de-reg.: 0 if bit is reset or bit number out of range
756 xchg !hl = size, de = bit number
757 mov a,d !test if bit number is negative
762 mov b,a !save bits 0-2 of bit number in b-reg
765 mov a,d !shift bit number right 3 times
774 mov a,l !test if bit number is small enough
782 ldax d !a-register = wanted byte
783 2: dcr b !dcr doesn't affect carry bit
788 3: xra a !return 0 if bit number out of range
801 !ior.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\1c\ 2.define .ior
809 ! Any size inclusive-or.
810 ! Expects: size in de-registers
812 ! Yields: result on stack
823 mov b,h !now bc points to top of first operand
824 dad d !and hl points to top of second operand
825 push h !this will be the new stackpointer
844 lar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0c
\ 4.define .lar2
851 ! Load array element, descriptor contains 2-bytes integers
852 ! Expects on stack: pointer to array descriptor
855 ! Yields on stack: array element
856 ! Adapted from .aar2 and .loi
865 pop h ! hl = pointer to descriptor
867 mov a,e ! bc = index - lower bound
875 push b ! first operand to multiply
881 push b ! second operand to multiply
882 call .mli2 ! de = size * (index - lower bound)
883 pop h ! hl = base address
884 dad d ! hl = address of array[index]
885 dad b ! hl= load pointer
886 xra a ! clear carry bit
887 mov a,b ! divide bc by 2
895 ! for 1 byte array element only:
896 mov a,c ! trap if bc odd and <>1
920 omli2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Č
\a.define .mli2
927 ! 16 bits signed integer multiply
928 ! the algorithm multiples A * B, where A = A0*2^8 + A1 and B = B0*2^8 + B1
929 ! product is thus A0*B0*2^16 + 2^8 * (A0 * B1 + B0 * A1) + A0 * B0
930 ! hence either A0 = 0 or B0 = 0 or overflow.
931 ! initial part of code determines which high byte is 0 (also for negative #s)
932 ! then the multiply is reduced to 8 x 16 bits, with the 8 bit number in the
933 ! a register, the 16 bit number in the hl register, and the product in de
934 ! Expects operands on stack
935 ! Yields result in de-registers
938 shld .retadr ! get the return address out of the way
941 mov a,d ! check hi byte for 0
943 jz 1f ! jump if de is a positive 8 bit number
945 jz 5f ! jump if de is a negative 8 bit number
947 shld .tmp1 ! we ran out of scratch registers
951 jz 7f ! jump if second operand is 8 bit negative
952 jmp 6f ! assume second operand is 8 bit positive
954 1: mov a,e ! 8 bit positive number in a
955 pop h ! 16 bit number in hl
957 ! here is the main loop of the multiplication. the a register is shifted
958 ! right 1 bit to load the carry bit for testing.
959 ! as soon as the a register goes to zero, the loop terminates.
960 ! in most cases this requires fewer than 8 iterations.
963 3: rar ! load carry bit from a
964 jnc 4f ! add hl to de if low bit was a 1
969 ora a ! sets zero correct and resets carry bit
970 jnz 3b ! if a has more bits, continue the loop
971 lhld .retadr ! go get return address
974 ! the 8 bit operand is negative. negate both operands
982 inx h ! 16 bit negate is 1s complement + 1
984 sub e ! negate 8 bit operand
987 ! second operand is small and positive
992 ! second operand is small and negative
1005 mli4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ā
\ 3.define .mli4
1012 ! 32 bits signed and unsigned integer multiply routine
1013 ! Expects operands on stack
1014 ! Yields product on stack
1022 pop h ! store multiplier
1026 pop h ! store multiplicand
1031 shld block3 ! product = 0
1036 mov a,m ! get next byte of multiplier
1040 lhld block2 ! add multiplicand to product
1053 2: lhld block2 ! shift multiplicand left
1082 mlu2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0,
\ 3.define .mlu2
1089 ! 16 bits unsigned multiply routine
1090 ! Expects operands on stack
1091 ! Yields result in de-registers
1092 ! This routine could also be used for signed integers, but it won't
1093 ! because there is a more clever one just for signed integers.
1102 pop b ! bc = multiplier
1103 pop d ! de = multiplicand
1104 lxi h,0 ! hl = product
1106 1: mov a,b ! if multiplier = 0 then finished
1111 mov a,b ! shift multiplier right
1118 jnc 2f !if carry set: add multiplicand to product
1121 2: xchg ! shift multiplicand left
1124 jmp 1b ! keep looping
1126 3: xchg ! de becomes product
1133 ngi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0S
\ 1.define .ngi4
1140 ! Exchange 32 bits integer by its two's complement
1141 ! Expects operand on stack
1142 ! Yields result on stack
1164 mnop.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0X
\ 1.define .nop
1194 rol4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\09
\ 2.define .rol4
1201 ! Rotate 4 bytes left
1202 ! Expects in de-reg: number of rotates
1203 ! Expects on stack: operand
1204 ! Yields on stack: result
1212 pop h ! low-order bytes of operand
1213 pop b ! high order bytes of operand
1236 jnz 1b ! keep looping
1246 bror4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0:
\ 2.define .ror4
1253 ! Rotate 4 bytes right
1254 ! Expects in de-reg: number of rotates
1255 ! Expects on stack: operand
1256 ! Yields on stack: result
1264 pop h ! low-order bytes of operand
1265 pop b ! high order bytes of operand
1288 jnz 1b ! keep looping
1298 sar2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\14\ 4.define .sar2
1305 ! Store array element, descriptor contains 2-bytes integers
1306 ! Expects on stack: pointer to array descriptor
1310 ! Adapted from .aar2 and .sti
1319 pop h ! hl = pointer to descriptor
1321 mov a,e ! bc = index - lower bound
1329 push b ! first operand to multiply
1335 push b ! second operand to multiply
1336 call .mli2 ! de = size * (index - lower bound)
1337 pop h ! hl = base address
1338 dad d ! hl = address of array[index]
1345 mov c,a ! bc = word count
1348 ! if 1 byte array element only:
1349 mov a,c ! trap if bc odd and <>1
1371 sbi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ó
\ 1.define .sbi4
1378 ! Subtract two 32 bits signed or unsigned integers.
1379 ! Expects operands on stack
1380 ! Yields result on stack
1390 dad sp !now hl points to the first operand
1396 inx d !and de points to the second.
1413 tset.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0 \ 3.define .set
1420 ! Create set with one bit on
1421 ! Expects in de-reg: size of set to be created
1422 ! Expects on stack: bit number
1423 ! Yields on stack: resulting set
1433 cc eoddz ! trap if size is odd
1434 xchg ! hl = size of set
1435 pop d ! de = bit number
1436 mov a,e ! c = bit number in byte
1438 sta .areg ! save bit number in byte
1440 mvi b,3 ! de = byte number
1451 mov a,l ! trap if bit number is too large
1457 lxi b,0 ! make empty set on stack
1467 dad d ! hl points to byte that will contain a one
1469 mov c,a ! c = bit number in byte
1483 set2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Õ
\ 1.define .set2
1490 ! Create 16 bits set with one bit on
1491 ! Expects in de-reg: bit number
1492 ! Yields in de-reg: resulting set
1494 .set2: mov a,d !trap if bit number >= 16
1514 jnz 3f ! jump if bit 3 is set
1524 esli2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0Ę
\ 1.define .sli2
1531 ! Shift 16 bits integer left
1532 ! Expects on stack: number of shifts
1533 ! number to be shifted
1534 ! Yields in de-reg: result
1539 pop d !de = number of shifts
1540 pop h !hl= number to be shifted
1541 mov a,d !if de>15 return zero
1553 3: xchg !result in de-registers
1557 sli4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0D
\ 2.define .sli4
1564 ! Shift 32 bits integer left
1565 ! Expects on stack: number of shifts
1566 ! number to be shifted
1567 ! Yields on stack: result
1576 pop b !number of shifts
1577 pop d !low-order bytes of number to be shifted
1578 pop h !high-order bytes
1579 mov a,b !if bc>=32 return 0
1607 sri2.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0ī
\ 2.define .sri2
1614 ! Shift 16 bits signed or unsigned integer right
1615 ! Expects in a-reg.: 1 if signed integer
1616 ! 0 if unsigned integer
1617 ! Expects on stack: number of shifts
1618 ! number to be shifted
1619 ! Yields in de-reg.: result
1624 pop h !hl = number of shifts
1625 pop d !de = number to be shifted
1628 jz 1f !jump if unsigned integer
1631 jnc 1f !jump if positive signed integer
1632 mvi h,255 !now h=1 if negative signed number, h=0 otherwise.
1634 1: mov a,l !return 0 or -1 if hl>=16
1641 rar !set carry bit correct
1655 sri4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\08
\ 3.define .sri4
1662 ! Shift 32 bits signed or unsigned integer right
1663 ! Expects in a-reg.: 1 if signed integer
1664 ! 0 if unsigned integer
1665 ! Expects on stack: number of shifts
1666 ! number to be shifted
1667 ! Yields on stack: result
1675 pop b !number of shifts
1676 pop d !low-order bytes of number to be shifted
1677 pop h !high-order bytes
1680 jz 1f !jump if unsigned integer
1683 jnc 1f !jump if positive signed integer
1721 xor.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\1c\ 2.define .xor
1729 ! Any size exclusive-or.
1730 ! Expects: size in de-registers
1732 ! Yields: result on stack
1743 mov b,h !now bc points to top of first operand
1744 dad d !and hl points to top of second operand
1745 push h !this will be the new stackpointer
1764 loi.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0\ 6\ 3.define .loi
1772 ! Expects in de-registers: number of bytes to be loaded
1773 ! (this number should be 1 or even )
1774 ! Expects on stack: base address
1775 ! Yields on stack: result
1779 mov l,c ! free bc for scratch
1783 pop h ! hl = base address
1784 dad d ! hl = load pointer
1785 xra a ! clear carry bit
1786 mov a,d ! divide d by 2
1794 ! if 1 byte has to be loaded only:
1797 cnz eoddz ! trap if number is odd and <> 1
1809 dcx d ! is count exhausted?
1819 sti.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0-
\ 2.define .sti
1827 ! Expects on stack: number of bytes to be stored
1828 ! bytes to be stored
1834 shld .bcreg ! save bc
1843 mov e,a ! de = word count
1846 ! if 1 byte array element only:
1847 mov a,d ! trap if de odd and <>1
1870 fdvi4.s
\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0g
\b.define .dvi4
1877 ! 32 bits integer divide and remainder routine
1878 ! Bit 0 of a-reg is set iff quotient has to be delivered
1879 ! Bit 7 of a-reg is set iff the operands are signed, so:
1880 ! Expects in a-reg: 0 if called by rmu 4
1881 ! 1 if called by dvu 4
1882 ! 128 if called by rmi 4
1883 ! 129 if called by dvi 4
1884 ! Expects on stack: divisor
1886 ! Yields on stack: quotient or remainder
1895 pop h ! store divisor
1904 cz eidivz ! trap if divisor = 0
1906 1: pop h ! store dividend
1910 lxi h,0 ! store initial value of remainder
1917 jnc 2f ! jump if unsigned
1924 call compl ! dividend is positive now
1931 call compl ! divisor is positive now
1933 2: push b ! save b-reg
1936 dv0: lxi h,block1 ! left shift: block2 <- block1 <- 0
1945 lxi h,block2+3 ! which is larger: divisor or remainder?
1958 4: lxi d,block2 ! remainder is larger or equal: subtract divisor
1973 jnz dv0 ! keep looping
1976 lda .areg ! quotient or remainder?
1980 ! for dvi 4 and dvu 4 only:
1983 lxi h,block1 ! complement quotient if divisor
1984 cc compl ! and dividend have different signs
1985 lhld block1+2 ! push quotient
1991 ! for rmi 4 and rmu 4 only:
1995 cc compl ! negate remainder if dividend was negative
2007 ! make 2's complement of 4 bytes pointed to by hl.
2020 \0rck.s
\0\0\0\0\0\0\0\0\0\0\0\0\0\ 2\ 2¤
\ 1\0\0?
\ 3.define .rck
2028 ! Expects on stack: address of range check descriptor
2030 ! Yields index on stack unchanged
2031 ! Causes a trap if index is out of bounds
2039 pop h ! hl = return address
2041 mov c,m ! bc = lower bound
2047 jm 1f ! jump if index and l.b. have different signs
2054 1: xra b ! now a = d again
2055 2: cm erange ! trap if index too small
2062 jm 1f ! jump if index and u.b. have different signs
2069 1: xra d ! now a = b
2070 2: cm erange ! trap if index is too large