
#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
 