General Information \\ Author: Andrew John Jacobs \\ Published: 1999 \\ 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 fount at [http://www.obelisk.demon.co.uk/6502/algorithms.html] ---- {{{ 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 }}}