32bitmath[.SEQ formatted GEOS file V1.0 Comm. Compat.ևևȘe`H/U PS.Patch 2.0Y BLASTER'S CONVERTER V2.5Park AvenueATHENSAWrite Image V2.1geoWrite V2.1  ...݅ ( >1 59 ..  9 < <` " . r " `(@1ʎsAڢ9 V& yh[A#0@000000(  Thirty-two bit math routines By Nate Fiedler (NateF, on Q-Link) These are 11 pages of 11 routines for handling numbers up to 32 bits in length. These routines are not commented, but they are easy to follow. Some of them require that you substitute in hexadecimal values for the opcodes and operands where the opcodes are using an address mode that is not supported by the 6502 and 6510 microprocessor. The routines include: ZeroRegs clear all GEOS registers MoveLW moves a longword MultLW multiplies two longwords DivLW divides two longwords AddLW adds two longwords IncLW increments a longword CmpLW compares two longwords SubLW subtracts two longwords DecLW decrements two longwords Cmp1LW compares a longword to one Cmp0LW compares a longword to zero I will use the term "longword" when I am speaking of a register that is four bytes long. A one byte register is called a byte. A two byte register is called a word. I forget what a three byte register is called. And a four byte register is called a longword. If you really want to know what a three byte register is called, you can find the machine langauge book for the 68030 Motorola processor. The routines are fully documented with instructions, and all routines necessary are included. If you have any problems, please notify me, and I will try to rectify whatever ails you, that is as long as the problem has something to do with these routines. :) (retarded smiley face) You may notice that the divide and multiply routines are a little slow, especially when you are using very large values. The best solution to this problem is to multiply a large number by a small one, rather then a small value by a large value, since it will add the small value to itself very-large-value times. The divide routine will check for division by 0, and check if operand1 is smaller than operand2, and will return somewhat correct values if either of these errors occur. I worked on these for two days, so you better like them! Enjoy! :) (another retarded smiley face) Nate Fiedler Rd 3 Box 140 Bernville, PA 19506-9313 NateF on Q-Link rHx0 ;DivLW - divide a 32 bit number by another 32 bit number ;Pass: x operand1 - zero page address of lHx0 ;DivLW - divide a 32 bit number by another 32 bit number ;Pass: x operand1 - zero page address of longword ; dividend ; y operand2 - zero page address of longword ; divisor ;Returns: x,y, word pointed to by x contains result of division ; r12 contains the remainder (longword value) ;Destroys: a, r11, r14-r15 ;Note: DivLW will check for division by zero, and will ; exit with operand1 in remainder and operand1 will ; equal zero. ; If operand1 is less than operand2, it will exit with ; operand1 in remainder and operand1 will equal zero. DivLW: sty r11L stx r11H LoadB r14L,0 sta r14H sta r15L sta r15H ldx r11L jsr Cmp0LW beq 99$ ldx r11H jsr CmpLW bcc 99$ 10$: jsr SubLW ldx #r14 jsr IncLW ldx r11H jsr CmpLW bcs 10$ 99$: ldy #r12 ldx r11H jsr MoveLW ldy r11H ldx #r14 jsr MoveLW ldy r11L ldx r11H rts tHx0 ;IncLW - increment a longword value by one ;Pass: x operand1 - zero page address of longword ; to increment ;ReturnHx0 ;IncLW - increment a longword value by one ;Pass: x operand1 - zero page address of longword ; to increment ;Returns: x, value in register pointed to by x will be one ; greater than before call to IncLW. ; zero flag will be set or clear, to show if the value ; rolled from $FFFFFFFF to $00000000 ;Destroys: nothing IncLW: inc 0,x bne 10$ inc 1,x bne 10$ inc 2,x bne 10$ inc 3,x 10$: rts xHx0 ;CmpLW - compare two long words to each other Hx0 ;CmpLW - compare two long words to each other ;Pass: x operand1 - zero page address of longword ; y operand2 - zero page address of other ; longword to compare operand1 to ;Destroys: a ;Returns: zero flag be set or clear ;Note: The "cmp zp,y" opcode will not work with ; geoAssembler version 1.0. Substitute in the hex value ; of this opcode with the absolute address of the ; operand and it will work. ; Example: ; .byte $d9,0,r1 ; Will compare r1,y to value in "a" register ; This will make it use the absolute address mode. ; Note that the address is two bytes long. ;See  Commodore 64 Programmer's Reference Guide for opcodes ;of this and all other machine language commands. CmpLW: lda 3,x cmp 3,y ; or .byte $d9,0,3 bne 10$ lda 2,x cmp 2,y ; or .byte $d9,0,2 bne 10$ lda 1,x cmp 1,y ; or .byte $d9,0,1 bne 10$ lda 0,x cmp 0,y ; or .byte $d9,0,0 10$: rts n|Hx0 ;SubLW - subtract two longword values ;Pass: x operand1 - zero pageHx0 ;SubLW - subtract two longword values ;Pass: x operand1 - zero page address of longword ; destination register ; y  operand2 - zero page address of longword Hx0; value to subtract from operand1 ;Returns: x,y, longword pointed to by x will contain result ; of subtraction.  operand1 =  operand1 -  operand2 Hx0;Destroys: a ;Note: The "sbc zp,y" opcode will not work with ; geoAssembler version 1.0. Substitute in the hex value ; of this opcode with the absolute address of the ; operand and it will work. ; Example: ; .byte $f9,0,r1 ; Will subtract r1,y from value in "a" register ; This will make it use the absolute address mode. ; Note that the address is two bytes long. ;See  Commodore 64 Programmer's Reference Guide for opcodes ;of this and all other machine language commands. SubLW: sec lda 0,x sbc 0,y ; or .byte $f9,0,0 sta 0,x lda 1,x sbc 1,y ; or .byte $f9,0,1 sta 1,x lda 2,x sbc 2,y ; or .byte $f9,0,2 sta 2,x lda 3,x sbc 3,y ; or .byte $f9,0,3 sta 3,x rts UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU# # #"#Hx0 ;DecLW - decrement a longword register by one ;Pass: x operand - zero page address of longword ; register to decrement ;Returns: x, word pointed to by x will be one less than before. ; Zero flag will be set or clear, to show if the value ; reached zero, but can be unreliable ;Destroys: a DecLW: lda 0,x bne 10$ lda 1,x bne 20$ lda 2,x bne 30$ lda 3,x bne 40$ rts 40$: dec 3,x 30$: dec 2,x 20$: dec 1,x 10$: dec 0,x rts iHx0 ;Cmp1LW: -Hx0 ;Cmp1LW: - compare a longword register to one ;Pass: x operand - zero page address of longword ; to compare to one ;Returns: zero flag set or clear ; After a call to Cmp1LW, ; a "beq" can be used to branch if value equaled one ; a "bne" can be used to branch if value did not ; equal one ;Destroys: a  Cmp1LW: lda 3,x bne 10$ lda 2,x bne 10$ lda 1,x bne 10$ lda 0,x cmp #1 10$: rts 0lHx0 ;MultLW - multiply two 32 bit registers ;Pass: Hx0 ;MultLW - multiply two 32 bit registers ;Pass: x operand1 - zero page address of longword ; multiplicand ; y operand2 - zero page address of longword ; multiplier ;Returns: x,y, register pointed to by x contains result, ; register pointed to by y will equal one ;Destroys: a, r12, r14-r15 ;Note: operand1 maximum value can be $FFFF ; operand2 maximum value can be $7FFF ; Largest possible result will equal $7FFE8001 MultLW: sty r12L stx r12H ldx r12L ldy r12H jsr Cmp1LW beq 99$ jsr Cmp0LW bne 5$ jmp MoveLW 5$: ldy #r14 ldx r12H jsr MoveLW 10$: ldx r12H jsr AddLW ldx r12L jsr DecLW jsr Cmp1LW bne 10$ 99$: ldy r12L ldx r12H rts oHx0 ;MoveLW - moves a 32 bit register to anotherHx0 ;MoveLW - moves a 32 bit register to another 32 bit register ;Pass: x operand1 - zero page address of source ; longword register ; y operand2 - zero page address of ; destination longword register ;Returns: x,y, register pointed to by y contains value in ; register pointed to by x ;Destroys: a ;Note: The "sta zp,y" opcode will not work with ; geoAssembler version 1.0. Substitute in the hex value ; of this opcode with the absolute address of the ; operand and it will work. ; Example: ; .byte $99,0,r1 ; Will store accumulator to r1,y ; This will make it use the absolute address mode. ; Note that the address is two bytes long. ;See  Commodore 64 Programmer's Reference Guide for opcodes ;of this and all other machine language commands. MoveLW: lda 0,x sta 0,y ; or .byte $99,0,0 lda 1,x sta 1,y ; or .byte $99,0,1 lda 2,x sta 2,y ; or .byte $99,0,2 lda 3,x sta 3,y ; or .byte $99,0,3 rts pHx0 ;ZeroRegs - clears all GEOS registHx0 ;ZeroRegs - clears all GEOS registers to zero ;Pass: nothing ;Returns: GEOS registers all equal zero ;Destroys: a,x, r0-r15 ZeroRegs: ldx #$1f lda #0 10$: sta r0L,x dex bpl 10$ rts uHx0 ;Hx0 ;AddLW - add two 32 bit registers ;Pass: x operand1 - zero page address of longword ; destination ; y  operand2 - zero page address of longword Hx0; register to add to operand1 ;Returns: x,y, word pointed to by x contains result of addition ;  operand1 =  operand1 +  operand2 Hx0;Destroys: a ;Note: The "adc zp,y" opcode will not work with ; geoAssembler version 1.0. Substitute in the hex value ; of this opcode with the absolute address of the ; operand and it will work. ; Example: ; .byte $79,0,r1 ; Will adc r1,y with the value in the "a" register. ; This will make it use the absolute address mode. ; Note that the address is two bytes long. ;See  Commodore 64 Programmer's Reference Guide for opcodes ;of this and all other machine language commands. AddLW: clc lda 0,x adc 0,y ; or .byte $79,0,0 sta 0,x lda 1,x adc 1,y ; or .byte $79,0,1 sta 1,x lda 2,x adc 2,y ; or .byte $79,0,2 sta 2,x lda 3,x adc 3,y ; or .byte $79,0,3 sta 3,x rts vHx0 ;Cmp0LW - compare 32 bit register to zero ;Pass: x operand - zero page address of longword ; to test ;Returns: zero flag either set or clear, depending onHx0 ;Cmp0LW - compare 32 bit register to zero ;Pass: x operand - zero page address of longword ; to test ;Returns: zero flag either set or clear, depending on result ;Destroys: a ;Description: Tests to see if a 32 bit register is equal ; to zero ; After calling Cmp0LW, ; a "beq" can be used to branch if it is equal to zero ; a "bne" can be used to branch if it is not equal ; to zero Cmp0LW: lda 3,x bne 10$ lda 2,x bne 10$ lda 1,x bne 10$ lda 0,x 10$: rts wHxHx0