#asm ; ;----- call.a: Small-C ver. 2 arithmetic and logical library ; (ASM Version 7-28-83, Bill Randle) ; ; M80 EQU 1 ; Compiler compiled with #define M80 ; to generate short names (unique in 6 chars). ; Set to 0 if compiler NOT compiled with M80 ; switch. ; CCDDGC: DAD D JMP CCGCHAR ; CCDSGC: INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ;SIGN EXTEND INTO HL ; CCGCHAR: MOV A,M ; ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. ; CCARGC: CCSXT: MOV L,A RLC SBB A MOV H,A RET ; CCDDGI: DAD D JMP CCGINT ; CCDSGI: INX H INX H DAD SP ; ;FETCH A FULL 16-BIT INTEGER FROM THE ADDRESS IN HL ;INTO HL ; CCGINT: MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; ; IF M80 ; use short symbol name CCDDPC: ENDIF IF NOT M80 ; use full length name CCDDPDPC: ENDIF ; DAD D CCPDPC: POP B ;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE ; CCPCHAR: PCHAR: MOV A,L STAX D RET ; CCDECI: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; ; IF M80 ; use short symbol name CCDDPI: ENDIF IF NOT M80 ; use full length name CCDDPDPI: ENDIF ; DAD D CCPDPI: POP B ;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE ; CCPINT: PINT: MOV A,L STAX D INX D MOV A,H STAX D RET ; ;INCLUSIVE "OR" HL AND DE INTO HL ; CCOR: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ; ;EXCLUSIVE "OR" HL AND DE INTO HL ; CCXOR: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ; ;"AND" HL AND DE INTO HL ; CCAND: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ; ;IN ALL THE FOLLOWING COMPARE ROUTINES, HL IS SET TO 1 IF THE ;CONDITION IS TRUE, OTHERWISE IT IS SET TO 0 (ZERO). ; ;TEST IF HL = DE ; CCEQ: CALL CCCMP RZ DCX H RET ; ;TEST IF DE <> HL ; CCNE: CALL CCCMP RNZ DCX H RET ; ;TEST IF DE > HL (SIGNED) ; CCGT: XCHG CALL CCCMP RC DCX H RET ; ;TEST IF DE <= HL (SIGNED) ; CCLE: CALL CCCMP RZ RC DCX H RET ; ;TEST IF DE >= HL (SIGNED) ; CCGE: CALL CCCMP RNC DCX H RET ; ;TEST IF DE < HL (SIGNED) ; CCLT: CALL CCCMP RC DCX H RET ; ;COMMON ROUTINE TO PERFORM A SIGNED COMPARE ; OF DE AND HL ;THIS ROUTINE PERFORMS DE - HL AND SETS THE CONDITIONS: ; CARRY REFLECTS SIGN OF DIFFERENCE (SET MEANS DE < HL) ; ZERO/NON-ZERO SET ACCORDING TO EQUALITY. ; CCCMP: MOV A,H ;;INVERT SIGN OF HL XRI 80H MOV H,A MOV A,D ;;INVERT SIGN OF DE XRI 80H CMP H ;;COMPARE MSBS JNZ CCCMP1 ;;DONE IF NEQ MOV A,E ;;COMPARE LSBS CMP L CCCMP1: LXI H,1 ;;PRESET TRUE COND RET ; ;TEST IF DE >= HL (UNSIGNED) ; CCUGE: CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) ; CCULT: CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) ; CCUGT: XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) ; CCULE: CALL CCUCMP RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY ; CCUCMP: MOV A,D CMP H JNZ CCUCP1 MOV A,E CMP L CCUCP1: LXI H,1 RET ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL ; CCASR: XCHG DCR E RM MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A JMP CCASR+1 ; ;SHIFT DE ARITHMETICALLY LEFT BY HL AND RETURN IN HL ; CCASL: XCHG DCR E RM DAD H JMP CCASL+1 ; ;SUBTRACT HL FROM DE AND RETURN IN HL ; CCSUB: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ;FORM THE TWO'S COMPLEMENT OF HL ; CCNEG: CALL CCCOM INX H RET ; ;FORM THE ONE'S COMPLEMENT OF HL ; CCCOM: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET ; ;MULTIPLY DE BY HL AND RETURN IN HL ;(SIGNED MULTIPLY) ; CCMULT: MULT: MOV B,H MOV C,L LXI H,0 CCMLT1: MOV A,C RRC JNC CCMLT2 DAD D CCMLT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP CCMLT1 ; ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) ; CCDIV: DIV: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM CCDENEG MOV A,B ORA A CM CCBCNEG MVI A,16 PUSH PSW XCHG LXI D,0 CCDIV1: DAD H CALL CCRDEL JZ CCDIV2 CALL CCCMPBCDE JM CCDIV2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A CCDIV2: POP PSW DCR A JZ CCDIV3 PUSH PSW JMP CCDIV1 CCDIV3: POP PSW RP CALL CCDENEG XCHG CALL CCDENEG XCHG RET ; ;NEGATE THE INTEGER IN DE ;(INTERNAL ROUTINE) ; CCDENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; ;NEGATE THE INTEGER IN BC ;(INTERNAL ROUTINE) ; CCBCNEG: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ; ;ROTATE DE LEFT ONE BIT ;(INTERNAL ROUTINE) ; CCRDEL: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET ; ;COMPARE BC TO DE ;(INTERNAL ROUTINE) ; CCCMPBCDE: MOV A,E SUB C MOV A,D SBB B RET ; ; LOGICAL NEGATION ; CCLNEG: MOV A,H ORA L JNZ $+6 MVI L,1 RET LXI H,0 RET ; ; EXECUTE "SWITCH" STATEMENT ; ; HL = SWITCH VALUE ; (SP) -> SWITCH TABLE ; DW ADDR1, VALUE1 ; DW ADDR2, VALUE2 ; ... ; DW 0 ; [JMP default] ; continuation ; CCSWITCH: XCHG ;;DE = SWITCH VALUE POP H ;;HL -> SWITCH TABLE SWLOOP: MOV C,M INX H MOV B,M ;;BC -> CASE ADDR, ELSE 0 INX H MOV A,B ORA C JZ SWEND ;;DEFAULT OR CONTINUATION CODE MOV A,M INX H CMP E MOV A,M INX H JNZ SWLOOP CMP D JNZ SWLOOP MOV H,B ;;CASE MATCHED MOV L,C SWEND: PCHL ; #endasm  CMP D