Path: news1.icaen!news.uiowa.edu!uunet!in3.uu.net!144.212.100.12!news.mathworks.com!news1.chicago.cic.net!iagnet.net!128.223.220.30!logbridge.uoregon.edu!news.uoregon.edu!smalltown.uoregon.edu!cie-2.uoregon.edu!nparker From: nparker@cie-2.uoregon.edu (Neil Parker) Newsgroups: comp.sys.apple2,comp.sys.apple2.programmer Subject: Re: Looking for 32-bit signed integer math routines in 6502 assembly Followup-To: comp.sys.apple2.programmer Date: 27 Aug 1997 21:49:26 GMT Organization: University of Oregon Campus Information Exchange Lines: 143 Message-ID: <5u27d6$2q4@smalltown.uoregon.edu> References: NNTP-Posting-Host: cie-2.uoregon.edu NNTP-Posting-User: nparker Xref: news1.icaen comp.sys.apple2:124593 comp.sys.apple2.programmer:9346 In article Ronald Kneusel writes: > >Subject says it all. Specifically, I'm looking for 32-bit _signed_ >multiplication and division: > >32-bit * 32-bit = 64-bit (or 32-bit ignoring overflow) > >32-bit / 32-bit = 32-bit (plus remainder) > >I've found 16-bit routines but was wondering if anyone had 32-bit routines >in 6502 assembly handy. First, my apologies for posting all this machine language in comp.sys.apple2, but that *is* where the original question is. I've tried to direct followups to comp.sys.apple2.programmer. Attached below is a 32*32=64 multiplication routine. I just banged it out tonight, but it seems to give the correct answers for a few test problems. Alas, it's unsigned, but that's not much of a problem. If a 32-bit result is sufficient, just use MUL4X4 as-is...the low-order 32 bits are the correct low-order bits of the signed product. If you need a 64-bit result, you'll have to do a little pre- and post-processing: LDA A4 ;Compute sign of result EOR B4 PHP ;Save on stack LDY #0 BIT A4 ;A<0? BPL TRYB ;If not, try B LDX #$FC ;Else negate A SEC L1 TYA SBC A4+1,X ;(this only works if A1..A4 are on page 0) STA A4+1,X INX BNE L1 TRYB BIT B4 ;B<0? BPL DOMUL ;If not, multiply LDX #$FC ;Else negate B SEC L2 TYA SBC B4+1,X ;(this only works if B1..B4 are on page 0) STA B4+1,X INX BNE L2 DOMUL JSR MUL4X4 ;Do the (unsigned) multiplication PLP ;Should result be <0? BPL DONE ;If not, then done LDY #0 ;Else negate result LDX #$F8 SEC L3 TYA SBC R8+1,X ;(this only works if R1..R8 are on page 0) STA R8+1,X INX BNE L3 DONE RTS Here's the multiplication routine. It wants the four-byte multiplicand in locations A1 (low byte) through A4 (high byte), and the four-byte multiplier in B1 through B4. The result comes out in R1 through R8. The four low-order bytes of R must be the same memory locations as the four bytes of B--i.e. B1 = R1, B2 = R2, etc. Calling MUL4X4 destroys B. For efficiency, all twelve memory locations should reside on page 0, but this is not required (unlike the signed routine above, which does require everything to be on page 0). This is not the most compact possible routine...some loops have been unrolled for speed, and some code has been added to optimize for zero bytes in B. MUL4X4 LDA #0 ;Init result to 0 STA R5 STA R6 STA R7 STA R8 JSR MUL1 ;Multiply A by 1st byte of B JSR MUL1 ;Multiply A by 2nd byte of B JSR MUL1 ;Multiply A by 3rd byte of B ; Multiply A by 4th byte of B, by falling into... MUL1 LDY B1 ;Get low byte of B LDA B2 ;Shift remaining bytes down, to make room for result STA B1 LDA B3 STA B2 LDA B4 STA B3 TYA ;Get low byte of B back BNE NON0 ;Is it 0? LDA R5 ;If so, shift result down by a whole byte, and return STA R4 LDA R6 STA R5 LDA R7 STA R6 LDA R8 STA R7 STY R8 ;(note Y=0 here) RTS NON0 LDX #8 ;Otherwise prepare to shift 8 bits M1 LSR ;Get low bit of multiplier TAY ;Save remaining multiplier bits BCC M2 ;Low bit 0? CLC ;If not, add multiplicand to result... LDA A1 ADC R5 STA R5 LDA A2 ADC R6 STA R6 LDA A3 ADC R7 STA R7 LDA A4 ADC R8 STA R8 M2 ROR R8 ;...and shift everything down 1 bit ROR R7 ROR R6 ROR R5 ROR R4 TYA ;Get multiplier bits back DEX ;Done 8 bits yet? BNE M1 ;If not, go do more RTS ;Else done The 32/32=32+remainder division routine will have to wait for another day-- I don't have one handy at the moment, and besides, this article is already getting a bit too long. - Neil Parker P.S. Concerning the division routine: Do you care which way the quotient rounds when the result is negative? Should it go to the more negative result, or toward 0, or something else? -- Neil Parker | Unsolicited commercial e-mail to my nparker@cie-2.uoregon.edu | address is not welcome, and will be nparker@cie.uoregon.edu | discarded unread. http://cie-2.uoregon.edu/~nparker |