NOLIST ;------------------------------------------------ ; 6502 Standard Macro Library ;------------------------------------------------ ; Copyright (C),1999 Andrew John Jacobs. ; All rights reserved. ;------------------------------------------------ ;------------------------------------------------ ; Revision History: ; ; 16-Aug-99 AJJ Initial version. ; ; 14-Nov-01 AJJ Finally got around to filling in ; some missing comments. ; ;------------------------------------------------ ; Notes: ; ; This file contains a number of useful 6502 ; algorithms for number, string and memory ; operations. The code is written in the form of ; macros rather than subroutines to make them ; more flexible. ; ; The routines in the library assume that 16 and ; 32 bit numbers are represented in little endian ; order, that is the least significant byte in ; the lowest memory location, so that they can ; be applied to addresses as well as pure ; numbers. ; ; The string routines assume that they are ; working with null terminated 'C' style strings. ; ; The main routines sacrifice code size for speed ; and are coded without any iteration. Compact ; versions which use iteration are provided for ; some algorithms and have the same name as the ; original routine with a 'C' suffix (eg. _XFR32 ; => _XFR32C). ; ; Some of the macros use 65SC02 instructions for ; speed or to reduce the amount code generated if ; the assembler will accept them. ; ; Where possible the macros detect optimizable ; cases and generate more efficient code. ; ; Bugs & Enhancments: ; ; If you find a bug I missed or have a new ; routine you would like to submit to the library ; then mail me at: ; ; Andrew@obelisk.demon.co.uk PAGE ;------------------------------------------------ ; Basic Operations ;------------------------------------------------ ; Clear 2 bytes of memory at any location by ; setting it to zero. If 65SC02 instructions are ; available then STZ is used. ; ; On exit: A = ??, X & Y are unchanged. IF __65SC02__ _CLR16 MACRO MEM STZ MEM+0 STZ MEM+1 ENDM ELSE _CLR16 MACRO MEM LDA #0 STA MEM+0 STA MEM+1 ENDM ENDIF ; Clear 4 bytes of memory at any location by ; setting it to zero. If 65SC02 instructions are ; available then STZ is used. ; ; On exit: A = ??, X & Y are unchanged. IF __65SC02__ _CLR32 MACRO MEM STZ MEM+0 STZ MEM+1 STZ MEM+2 STZ MEM+3 ENDM ELSE _CLR32 MACRO MEM LDA #0 STA MEM+0 STA MEM+1 STA MEM+2 STA MEM+3 ENDM ENDIF ; Clear 4 bytes of memory at any location by ; setting it to zero iteratively. If 65SC02 ; instructions are available then STZ is used. ; ; On exit: A = ??, X = $FF, Y is unchanged. IF __65SC02__ _CLR32C MACRO MEM LDX #3 _LOOP\? STZ MEM,X DEX BPL _LOOP\? ENDM ELSE _CLR32C MACRO MEM LDA #0 LDX #3 _LOOP\? STA MEM,X DEX BPL _LOOP\? ENDM ENDIF ; Transfer 2 bytes of memory from one location to ; another using the accumulator. The order in ; which the bytes are moved depends on the ; relative positions of SRC and DST. If SRC and ; DST are the same then no code is generated. ; ; On exit: A = ??, X & Y are unchanged. _XFR16 MACRO SRC,DST IF SRC != DST IF SRC > DST LDA SRC+0 STA DST+0 LDA SRC+1 STA DST+1 ELSE LDA SRC+1 STA DST+1 LDA SRC+0 STA DST+0 ENDIF ENDIF ENDM ; Transfer 4 bytes of memory from one location to ; another using the accumulator. The order in ; which the bytes are moved depends on the ; relative positions of SRC and DST. If SRC and ; DST are the same then no code is generated. ; ; On exit: A = ??, X & Y are unchanged. _XFR32 MACRO SRC,DST IF SRC != DST IF SRC > DST LDA SRC+0 STA DST+0 LDA SRC+1 STA DST+1 LDA SRC+2 STA DST+2 LDA SRC+3 STA DST+3 ELSE LDA SRC+3 STA DST+3 LDA SRC+2 STA DST+2 LDA SRC+1 STA DST+1 LDA SRC+0 STA DST+0 ENDIF ENDIF ENDM ; Transfer 4 bytes of memory from one location to ; another iteratively using the accumulator. The ; transfer may fail if SRC and DST overlap. If ; SRC and DST are the same then no code is ; generated. ; ; On exit: A = ??, X = $FF, Y is unchanged. _XFR32C MACRO SRC,DST IF SRC != DST LDX #3 _LOOP\? LDA SRC,X STA DST,X DEX BPL _LOOP\? ENDIF ENDM ; Set the value of a 16 bit location DST with ; the given constant value. ; ; On exit: A = ??, X & Y unchanged. _SET16I MACRO NUM,DST IF NUM != 0 LDA #LO NUM STA DST+0 LDA #HI NUM STA DST+1 ELSE _CLR16 DST ENDIF PAGE ;------------------------------------------------ ; Logical Operations ;------------------------------------------------ ; Calculate the logical NOT of the 16 bit value ; at location VLA and stores it in location RES. ; ; On exit: A = ??, X & Y are unchanged. _NOT16 MACRO VLA,RES LDA VLA+0 EOR #$FF STA RES+0 LDA VLA+1 EOR #$FF STA RES+1 ENDM ; Calculate the logical NOT of the 32 bit value ; at location VLA and stores it in location RES. ; ; On exit: A = ??, X & Y are unchanged. _NOT32 MACRO VLA,RES LDA VLA+0 EOR #$FF STA RES+0 LDA VLA+1 EOR #$FF STA RES+1 LDA VLA+2 EOR #$FF STA RES+2 LDA VLA+3 EOR #$FF STA RES+3 ENDM ; Calculate the logical NOT of the 32 bit value ; at location VLA iteratively and stores it in ; location RES. ; ; On exit: A = ??, X = $FF, Y are unchanged. _NOT32C MACRO VLA,RES LDX #3 _LOOP\? LDA VLA,X EOR #$FF STA RES,X DEX BPL _LOOP\? ENDM ; Calculate the logical OR of the two 16 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _XFR16. ; ; On exit: A = ??, X & Y are unchanged. _ORA16 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 ORA VLB+0 STA RES+0 LDA VLA+1 ORA VLB+1 STA RES+1 ELSE _XFR16 VLA,RES ENDIF ENDM ; Calculate the logical OR of a 16 value at ; location VLA with a constant value and ; store the result at location RES. ; ; On exit: A = ??, X & Y are unchanged. _ORA16I MACRO VLA,NUM,RES LDA VLA+0 ORA #LO NUM STA RES+0 LDA VLA+1 ORA #HI NUM STA RES+1 ENDM ; Calculate the logical OR of the two 32 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _XFR32. ; ; On exit: A = ??, X & Y are unchanged. _ORA32 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 ORA VLB+0 STA RES+0 LDA VLA+1 ORA VLB+1 STA RES+1 LDA VLA+2 ORA VLB+2 STA RES+2 LDA VLA+3 ORA VLB+3 STA RES+3 ELSE _XFR32 VLA,RES ENDIF ENDM ; Calculate the logical OR of the two 32 bit ; values at locations VLA and VLB iteratively. ; The result is stored in location RES. If VLA ; and VLB are the same the macro expands to a ; _XFR32C. ; ; On exit: A = ??, X = $FF, Y is unchanged. _ORA32C MACRO VLA,VLB,RES IF VLA != VLB LDX #3 _LOOP\? LDA VLA,X ORA VLB,X STA RES,X DEX BPL _LOOP\? ELSE _XFR32C VLA,RES ENDIF ENDM ; Calculate the logical AND of the two 16 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _XFR16. ; ; On exit: A = ??, X & Y are unchanged. _AND16 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 AND VLB+0 STA RES+0 LDA VLA+1 AND VLB+1 STA RES+1 ELSE _XFR16 VLA,RES ENDIF ENDM ; Calculate the logical AND of a 16 value at ; location VLA with a constant value and ; store the result at location RES. ; ; On exit: A = ??, X & Y are unchanged. _AND16I MACRO VLA,NUM,RES LDA VLA+0 AND #LO NUM STA RES+0 LDA VLA+1 AND #HI NUM STA RES+1 ENDM ; Calculate the logical AND of the two 32 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _XFR32. ; ; On exit: A = ??, X & Y are unchanged. _AND32 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 AND VLB+0 STA RES+0 LDA VLA+1 AND VLB+1 STA RES+1 LDA VLA+2 AND VLB+2 STA RES+2 LDA VLA+3 AND VLB+3 STA RES+3 ELSE _XFR32 VLA,RES ENDIF ENDM ; Calculate the logical AND of the two 32 bit ; values at locations VLA and VLB iteratively. ; The result is stored in location RES. If VLA ; and VLB are the same the macro expands to a ; _XFR32C. ; ; On exit: A = ??, X = $FF, Y is unchanged. _AND32C MACRO VLA,VLB,RES IF VLA != VLB LDX #3 _LOOP\? LDA VLA,X AND VLB,X STA RES,X DEX BPL _LOOP\? ELSE _XFR32C VLA,RES ENDIF ENDM ; Calculate the exclusive OR of the two 16 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _CLR16. ; ; On exit: A = ??, X & Y are unchanged. _EOR16 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 EOR VLB+0 STA RES+0 LDA VLA+1 EOR VLB+1 STA RES+1 ELSE _CLR16 RES ENDIF ENDM ; Calculate the exclusive OR of a 16 value at ; location VLA with a constant value and ; store the result at location RES. ; ; On exit: A = ??, X & Y are unchanged. _EOR16I MACRO VLA,NUM,RES LDA VLA+0 EOR #LO NUM STA RES+0 LDA VLA+1 EOR #HI NUM STA RES+1 ENDM ; Calculate the exclusive OR of the two 32 bit ; values at locations VLA and VLB. The result is ; stored in location RES. If VLA and VLB are the ; same the macro expands to a _CLR32. ; ; On exit: A = ??, X & Y are unchanged. _EOR32 MACRO VLA,VLB,RES IF VLA != VLB LDA VLA+0 EOR VLB+0 STA RES+0 LDA VLA+1 EOR VLB+1 STA RES+1 LDA VLA+2 EOR VLB+2 STA RES+2 LDA VLA+3 EOR VLB+3 STA RES+3 ELSE _CLR32 RES ENDIF ENDM ; Calculate the exclusive OR of the two 32 bit ; values at locations VLA and VLB iteratively. ; The result is stored in location RES. If VLA ; and VLB are the same the macro expands to a ; _XFR32C. ; ; On exit: A = ??, X = $FF, Y is unchanged. _EOR32C MACRO VLA,VLB,RES IF VLA != VLB LDX #3 _LOOP\? LDA VLA,X EOR VLB,X STA RES,X DEX BPL _LOOP\? ELSE _CLR32C RES ENDIF ENDM PAGE ;------------------------------------------------ ; Shift Operations ;------------------------------------------------ ; Perform an arithmetic shift left on the 16 bit ; number at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ASL16 MACRO VLA,RES IF VLA != RES LDA VLA+0 ASL A STA RES+0 LDA VLA+1 ROL A STA RES+1 ELSE ASL VLA+0 ROL VLA+1 ENDIF ENDM ; Perform an arithmetic shift left on the 32 bit ; number at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ASL32 MACRO VLA,RES IF VLA != RES LDA VLA+0 ASL A STA RES+0 LDA VLA+1 ROL A STA RES+1 LDA VLA+2 ROL A STA RES+2 LDA VLA+3 ROL A STA RES+3 ELSE ASL VLA+0 ROL VLA+1 ROL VLA+2 ROL VLA+3 ENDIF ENDM ; Perform a left rotation on the 16 bit number at ; location VLA and store the result at location ; RES. If VLA and RES are the same then the ; operation is applied directly to the memory, ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ROL16 MACRO VLA,RES IF VLA != RES LDA VLA+0 ROL A STA RES+0 LDA VLA+1 ROL A STA RES+1 ELSE ROL VLA+0 ROL VLA+1 ENDIF ENDM ; Perform a left rotation on the 32 bit number at ; location VLA and store the result at location ; RES. If VLA and RES are the same then the ; operation is applied directly to the memory, ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ROL32 MACRO VLA,RES IF VLA != RES LDA VLA+0 ROL A STA RES+0 LDA VLA+1 ROL A STA RES+1 LDA VLA+2 ROL A STA RES+2 LDA VLA+3 ROL A STA RES+3 ELSE ROL VLA+0 ROL VLA+1 ROL VLA+2 ROL VLA+3 ENDIF ENDM ; Perform an logical shift right on the 16 bit ; number at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _LSR16 MACRO VLA,RES IF VLA != RES LDA VLA+1 LSR A STA RES+1 LDA VLA+0 ROR A STA RES+0 ELSE LSR VLA+1 ROR VLA+0 ENDIF ENDM ; Perform an logical shift right on the 32 bit ; number at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _LSR32 MACRO VLA,RES IF VLA != RES LDA VLA+3 LSR A STA RES+3 LDA VLA+2 ROR A STA RES+2 LDA VLA+1 ROR A STA RES+1 LDA VLA+0 ROR A STA RES+0 ELSE LSR VLA+3 ROR VLA+2 ROR VLA+1 ROR VLA+0 ENDIF ENDM ; Perform a right rotation on the 16 bit number ; at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ROR16 MACRO VLA,RES IF VLA != RES LDA VLA+1 ROR A STA RES+1 LDA VLA+0 ROR A STA RES+0 ELSE ROR VLA+1 ROR VLA+0 ENDIF ENDM ; Perform a right rotation on the 32 bit number ; at location VLA and store the result at ; location RES. If VLA and RES are the same then ; the operation is applied directly to the memory ; otherwise it is done in the accumulator. ; ; On exit: A = ??, X & Y are unchanged. _ROR32 MACRO VLA,RES IF VLA != RES LDA VLA+3 ROR A STA RES+3 LDA VLA+2 ROR A STA RES+2 LDA VLA+1 ROR A STA RES+1 LDA VLA+0 ROR A STA RES+0 ELSE ROR VLA+3 ROR VLA+2 ROR VLA+1 ROR VLA+0 ENDIF ENDM PAGE ;------------------------------------------------ ; Arithmetic Operations ;------------------------------------------------ ; Increment the 16 bit value at location MEM ; by one. ; ; On exit: A, X & Y are unchanged. _INC16 MACRO MEM INC MEM+0 BNE _DONE\? INC MEM+1 _DONE\? EQU * ENDM ; Increment the 32 bit value at location MEM ; by one. ; ; On exit: A, X & Y are unchanged. _INC32 MACRO MEM INC MEM+0 BNE _DONE\? INC MEM+1 BNE _DONE\? INC MEM+2 BNE _DONE\? INC MEM+3 _DONE\? EQU * ENDM ; Decrement the 16 bit value at location MEM ; by one. ; ; On exit: A = ??, X & Y are unchanged. _DEC16 MACRO MEM LDA MEM+0 BNE _DONE\? DEC MEM+1 _DONE\? DEC MEM+0 ENDM ; Decrement the 32 bit value at location MEM ; by one. ; ; On exit: A = ??, X & Y are unchanged. _DEC32 MACRO MEM LDA MEM+0 BNE _DEC0\? LDA MEM+1 BNE _DEC1\? LDA MEM+2 BNE _DEC2\? DEC MEM+3 _DEC2\? DEC MEM+2 _DEC1\? DEC MEM+1 _DEC0\? DEC MEM+0 ENDM ; Add two 16 bit numbers together and store the ; result in another memory location. RES may be ; the same as either VLA or VLB. ; ; On exit: A = ??, X & Y are unchanged. _ADD16 MACRO VLA,VLB,RES IF VLA != VLB CLC LDA VLA+0 ADC VLB+0 STA RES+0 LDA VLA+1 ADC VLB+1 STA RES+1 ELSE _ASL16 VLA,RES ENDIF ENDM ; Add two 32 bit numbers together and store the ; result in another memory location. RES may be ; the same as either VLA or VLB. ; ; On exit: A = ??, X & Y are unchanged. _ADD32 MACRO VLA,VLB,RES IF VLA != VLB CLC LDA VLA+0 ADC VLB+0 STA RES+0 LDA VLA+1 ADC VLB+1 STA RES+1 LDA VLA+2 ADC VLB+2 STA RES+2 LDA VLA+3 ADC VLB+3 STA RES+3 ELSE _ASL32 VLA,RES ENDIF ENDM ; Subtract two 16 bit numbers and store the ; result in another memory location. RES may be ; the same as VLA or VLB. ; ; On exit: A = ??, X & Y are unchanged. _SUB16 MACRO VLA,VLB,RES SEC LDA VLA+0 SBC VLB+0 STA RES+0 LDA VLA+1 SBC VLB+1 STA RES+1 ENDM ; Subtract two 32 bit numbers and store the ; result in another memory location. RES may be ; the same as VLA or VLB. ; ; On exit: A = ??, X & Y are unchanged. _SUB32 MACRO VLA,VLB,RES SEC LDA VLA+0 SBC VLB+0 STA RES+0 LDA VLA+1 SBC VLB+1 STA RES+1 LDA VLA+2 SBC VLB+2 STA RES+2 LDA VLA+3 SBC VLB+3 STA RES+3 ENDM ; Negate the signed 16 bit number at location VLA ; and stored the result at location RES. RES may ; be the same as VLA. ; ; On exit: A = ??, X & Y are unchanged. _NEG16 MACRO VLA,RES SEC LDA #0 SBC VLA+0 STA RES+0 LDA #0 SBC VLA+1 STA RES+1 ENDM ; Negate the signed 32 bit number at location VLA ; and stored the result at location RES. RES may ; be the same as VLA. ; ; On exit: A = ??, X & Y are unchanged. _NEG32 MACRO VLA,RES SEC LDA #0 SBC VLA+0 STA RES+0 LDA #0 SBC VLA+1 STA RES+1 LDA #0 SBC VLA+2 STA RES+2 LDA #0 SBC VLA+3 STA RES+3 ENDM ; Calculates the absolute value of signed 16 bit ; number at location VLA and stores it in the RES ; location. Less code is generated if VLA and RES ; are the same location. If 65SC02 instructions ; are available a BRA is used to shorten the ; generated code. ; ; On exit: A = ??, X & Y are unchanged. _ABS16 MACRO VLA,RES BIT VLA+0 IF VLA != RES BPL _MOVE\? _NEG16 VLA,RES IF __65SC02__ BRA _DONE\? ELSE JMP _DONE\? ENDIF _MOVE\? EQU * _XFR16 VLA,RES ELSE BPL _DONE\? _NEG16 VLA,RES ENDIF _DONE\? EQU * ENDM ; Calculates the absolute value of signed 32 bit ; number at location VLA and stores it in the RES ; location. Less code is generated if VLA and RES ; are the same location. If 65SC02 instructions ; are available a BRA is used to shorten the ; generated code. ; ; On exit: A = ??, X & Y are unchanged. _ABS32 MACRO VLA,RES BIT VLA+0 IF VLA != RES BPL _MOVE\? _NEG32 VLA,RES IF __65SC02__ BRA _DONE\? ELSE JMP _DONE\? ENDIF _MOVE\? EQU * _XFR32 VLA,RES ELSE BPL _DONE\? _NEG32 VLA,RES ENDIF _DONE\? EQU * ENDM ; Calculate the 16 bit product of two 16 bit ; unsigned numbers. Any overflow during the ; calculation is lost. The number at location ; VLA is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _MUL16 MACRO VLA,VLB,RES _CLR16 RES LDX #16 _LOOP\? EQU * _ASL16 RES,RES _ASL16 VLA,VLA BCC _NEXT\? _ADD16 VLB,RES,RES _NEXT\? DEX BPL _LOOP\? ENDM ; Calculate the 32 bit product of two 16 bit ; unsigned numbers. The number at location VLA ; is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _MUL16X MACRO VLA,VLB,RES _CLR32 RES LDX #16 _LOOP\? EQU * _ASL32 RES,RES _ASL16 VLA,VLA BCC _NEXT\? _ADD16 VLB,RES,RES BCC _NEXT\? _INC16 RES+2 _NEXT\? EQU * DEX BPL _LOOP\? ENDM ; Calculate the 32 bit product of two 32 bit ; unsigned numbers. Any overflow during the ; calculation is lost. The number at location ; VLA is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _MUL32 MACRO VLA,VLB,RES _CLR32 RES LDX #32 _LOOP\? EQU * _ASL32 RES,RES _ASL32 VLA,VLA BCC _NEXT\? _ADD32 VLB,RES,RES _NEXT\? EQU * DEX BPL _LOOP\? ENDM ; These two macros write the code necessary ; to multiply a 16 bit at location VLA by ; a 16 bit constant NUM and store the 16 bit ; result in location RES. ; ; On exit: A = ??, X & Y unchanged. _MUL16I MACRO VLA,NUM,RES IF NUM = 1 _XFR16 VLA,RES ELSE _CLR16 RES __MUL16I VLA,NUM,RES ENDIF ENDM __MUL16I MACRO VLA,NUM,RES IF NUM & $FFFE __MUL16I VLA,(NUM/2),RES _ASL16 RES,RES ENDIF IF NUM & $0001 _ADD16 VLA,RES,RES ENDIF ENDM ; Divide the 16 bit number at location VLA ; by the 16 bit number at location VLB ; leaving the 16 bit quotient at QUO and ; the 16 bit remainder in REM. The value in ; location VLA is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _DIV16 MACRO VLA,VLB,QUO,REM _CLR16 REM LDX #16 _LOOP\? EQU * _ASL16 VLA,VLA _ROL16 REM,REM _SUB16 REM,VLB,REM BCS _NEXT\? _ADD16 REM,VLB,REM _NEXT\? EQU * _ROL16 QUO,QUO DEX BPL _LOOP\? ENDM ; Divide the 32 bit number at location VLA ; by the 16 bit number at location VLB ; leaving the 16 bit quotient at QUO and ; the 16 bit remainder in REM. The value in ; location VLA is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _DIV16X MACRO VLA,VLB,QUO,REM _CLR16 REM LDX #32 _LOOP\? EQU * _ASL32 VLA,VLA _ROL16 REM,REM _SUB16 REM,VLB,REM BCS _NEXT\? _ADD16 REM,VLB,REM _NEXT\? EQU * _ROL16 QUO,QUO DEX BPL _LOOP\? ENDM ; Divide the 32 bit number at location VLA ; by the 32 bit number at location VLB ; leaving the 32 bit quotient at QUO and ; the 32 bit remainder in REM. The value in ; location VLA is destroyed. ; ; On exit: A = ??, X = $FF, Y is unchanged. _DIV32 MACRO VLA,VLB,QUO,REM _CLR32 REM LDX #32 _LOOP\? EQU * _ASL32 VLA,VLA _ROL32 REM,REM _SUB32 REM,VLB,REM BCS _NEXT\? _ADD32 REM,VLB,REM _NEXT\? EQU * _ROL32 QUO,QUO DEX BPL _LOOP\? ENDM PAGE ;------------------------------------------------ ; Comparative Operations ;------------------------------------------------ ; Compares two 16 bit values in memory areas VLA ; and VLB. The comparison starts with the most ; significant bytes and returns as soon as a ; difference is detected. ; ; On exit: A = ??, X & Y are unchanged. _CMP16 MACRO VLA,VLB LDA VLA+1 CMP VLB+1 BNE _DONE\? LDA VLA+0 CMP VLB+0 _DONE\? EQU * ENDM ; Compares two 32 bit values in memory areas VLA ; and VLB. The comparison starts with the most ; significant bytes and returns as soon as a ; difference is detected. ; ; On exit: A = ??, X & Y are unchanged. _CMP32 MACRO VLA,VLB LDA VLA+3 CMP VLB+3 BNE _DONE\? LDA VLA+2 CMP VLB+2 BNE _DONE\? LDA VLA+1 CMP VLB+1 BNE _DONE\? LDA VLA+0 CMP VLB+0 _DONE\? EQU * ENDM PAGE ;------------------------------------------------ ; Memory Operations ;------------------------------------------------ ; Transfers a block of memory from one place to ; another by copying the bytes starting at the ; front of the block and going forward. SRC and ; DST are destroyed during the copy. ; ; On exit: A, X & Y = ??. _MEMFWD MACRO SRC,DST,LEN LDY #0 LDX LEN+1 BEQ _FRAG\? _PAGE\? LDA (SRC),Y STA (DST),Y INY BNE _PAGE\? INC SRC+1 INC DST+1 DEX BNE _PAGE\? _FRAG\? CPY LEN+0 BEQ _DONE\? LDA (SRC),Y STA (DST),Y INY BNE _FRAG\? _DONE\? EQU * ENDM ; Transfers a block of memory from one place to ; another by copying the bytes starting at the ; end of the block and going backwards. _MEMREV MACRO SRC,DST,LEN NOP ENDM ; Tranfers a block of memory from one location to ; another. Depending on the relative positions of ; the blocks an appropriate transfer method is ; used. _MEMCPY MACRO SRC,DST,LEN _CMP16 SRC,DST BCC _SAFE\? _MEMFWD SRC,DST,LEN IF __65SC02__ BRA _DONE\? ELSE JMP _DONE\? ENDIF _SAFE\? _MEMREV SRC,DST,LEN _DONE\? EQU * ENDM PAGE ;------------------------------------------------ ; String Operations ;------------------------------------------------ ; Calculates length of a null terminated string ; by searching for its end. The address of the ; string in STR is destroyed during the search. ; ; On exit: A & Y = ??, X is unchanged. _STRLEN MACRO STR,LEN LDY #0 STY LEN+1 _LOOP\? LDA (STR),Y BEQ _DONE\? INY BNE _LOOP\? INC LEN+1 INC STR+1 IF __65SC02__ BRA _LOOP\? ELSE JMP _LOOP\? ENDIF _DONE\? STY LEN+0 ENDM ; Copies a null terminated string from one memory ; location to another. The source and destination ; addresses are destroyed during the copy process. ; ; On exit: A & Y = ??, X is unchanged. _STRCPY MACRO SRC,DST LDY #0 _LOOP\? LDA (SRC),Y STA (DST),Y BEQ _DONE\? INY BNE _LOOP\? INC SRC+1 INC DST+1 IF __65SC02__ BRA _LOOP\? ELSE JMP _LOOP\? ENDIF _DONE\? EQU * ENDM ; _STRCMP MACRO VLA,VLB LDY #0 _LOOP\? LDA (VLA),Y CMP (VLB),Y BNE _DONE\? LDA (VLA),Y BEQ _DONE\? INY BNE _LOOP\? INC VLA+1 INC VLB+1 IF __65SC02__ BRA _LOOP\? ELSE JMP _LOOP\? ENDIF _DONE\? EQU * ENDM ; _STRNCMP MACRO VLA,VLB,LEN ENDM LIST