6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 11:42 pm

All times are UTC




Post new topic Reply to topic  [ 7 posts ] 
Author Message
PostPosted: Wed Mar 13, 2013 5:36 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
I successfully converted one of Lee Davidson's contributions. I'll add more as time goes on.
It uses 3 zeropage variables: Number is the input $0000-$00FF only. Sqr is the output. Tempsq is temp storage.
This is the Square Routine:
Code:
; How to calculate the 16-bit unsigned integer square of a signed 16-bit integer.
; By Lee Davison (leeedavison@googlemail.com), 19 October 2000.
; Modified for the 65Org16 By Sam Gaskill, 13 March 2013.
; Calculates the 16 bit unsigned integer square of the signed 16 bit integer in
; Number.  The result is always in the range 0 to 65025 and is held in
; Sqr
;
; The maximum input range is only +/-255 and no checking is done to ensure that
; this is so.
;
; This routine is useful if you are trying to draw circles as for any circle
;
; x^2+y^2=r^2 where x and y are the co-ordinates of any point on the circle and
; r is the circle radius
;
; Destroys all registers


Square      LDA #$00            ; clear A
            STA Sqr             ; clear square
            LDA   Number     
NoNneg      STA   Tempsq          ; save ABS(number)
             LDX   #$10            ; set bit count

Nextr2bit     ASL   Sqr             ; low byte *2
             ASL   A               ; shift number byte
             BCC   NoSqadd         ; don't do add if C = 0
             TAY                 ; save A
             CLC                 ; clear carry for add
             LDA   Tempsq          ; get number
             ADC   Sqr             ; add number^2
             STA   Sqr             ; save number^2
             TYA                 ; get A back

NoSqadd     DEX                 ; decrement bit count
             BNE   Nextr2bit       ; go do next bit
            RTS

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 13, 2013 8:09 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Needs some refinements which I'll make soon, but I didn't want to break it. So this appears to be working for Square Root:
Code:
; How to calculate the 8-bit unsigned integer square root of an unsigned 16-bit integer.
; By Lee Davison (leeedavison@googlemail.com), 23 July 2001.
; Modified for the 65Org16 by Sam Gaskill, 13 March 2013.
; Calculates the 8 bit root and 9 bit remainder of a 16 bit unsigned integer in
; Numberl. Numberh=0. The result is always in the range 0 to 255 and is held in
; Root, the remainder is in the range 0 to 511 and is held in Reml/Remh
;
; partial results are held in templ/temph
;
; This routine is the complement to the integer square program.
;
; Destroys A, X registers.
                     
SqRoot      LDA   #$00      ; clear A
             STA   Reml      ; clear remainder low byte
             STA   Remh      ; clear remainder high byte
             STA   Root      ; clear Root
             LDX   #$10      ; 16 pairs of bits to do
Loop
             ASL   Root      ; Root = Root * 2

             ASL   Numberl   ; shift highest bit of number ..
             ROL   Numberh   ;
             ROL   Reml      ; .. into remainder
             ROL   Remh      ;

             ASL   Numberl   ; shift highest bit of number ..
             ROL   Numberh   ;
             ROL   Reml      ; .. into remainder
             ROL   Remh      ;

             LDA   Root      ; copy Root ..
             STA   templ      ; .. to templ
             LDA   #$00      ; clear byte
             STA   temph      ; clear temp high byte

             SEC             ; +1
             ROL   templ      ; temp = temp * 2 + 1
             ROL   temph      ;

             LDA   Remh      ; get remainder high byte
             CMP   temph      ; comapre with partial high byte
             BCC   Next      ; skip sub if remainder high byte smaller

            BNE   Subtr      ; do sub if <> (must be remainder>partial !)

             LDA   Reml      ; get remainder low byte
             CMP   templ      ; comapre with partial low byte
             BCC   Next      ; skip sub if remainder low byte smaller

                            ; else remainder>=partial so subtract then
                            ; and add 1 to root. carry is always set here
Subtr
             LDA   Reml      ; get remainder low byte
             SBC   templ      ; subtract partial low byte
             STA   Reml      ; save remainder low byte
             LDA   Remh      ; get remainder high byte
             SBC   temph      ; subtract partial high byte
             STA   Remh      ; save remainder high byte

             INC   Root      ; increment Root
Next
             DEX             ; decrement bit pair count
             BNE   Loop      ; loop if not all done

             RTS

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 13, 2013 9:21 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Did you only have to change the loop counters? If this works it's a nice demonstration of how easy it is to port code from 6502 to 65Org16!
I notice that the comments still describe a 16 bit function - it should in fact now be a 32bit function. Reducing it back to 16bits should show the advantage of the 16bit nature of the machine.
Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 13, 2013 9:45 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
BigEd wrote:
Did you only have to change the loop counters?...
Cheers
Ed

That was one change, I had to change it from $0008 to $0010. Note that Bitwise's AS65 assembler right justifies 8bit values, ie a value you might see of $ee, is actually $00ee. One is allowed to present it either way to the assembler, but just realize the rules.

The other detail, was putting the entire 16 bit value into the Numberl variable. I forced Numberh to zero.

I will double check this routine now in ISim, as my circle plotting routine is still not functional.

EDIT: This is correct. After storing a value of $E100 in Numberl, and $0000 in Numberh, with the loop counter @ $0010, the returned result was $00F0 for Root variable with no other changes to the original 6502 software in this case.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 14, 2013 12:00 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
My plotting routine is now functional due to some other errors that were present in my 65Org16 code. Lee's code was functional as presented above, but I'm sure some variables can be eliminated. I'll look into optimizing it next week...

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 14, 2013 1:26 am 
Offline
User avatar

Joined: Thu Mar 11, 2004 7:42 am
Posts: 362
There is an optimized (6502) version here:

http://6502org.wikidot.com/software-math-sqrt


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 14, 2013 10:46 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Awesome, thanks Bruce. I have a few routines to compare speeds now and to convert over to 65Org16. I should probably .zip each one up and add to the header.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: