6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Sep 06, 2024 5:29 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Thu Apr 02, 2020 2:14 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
I was wandering the 'net and somehow kept noticing that more than a few 65xx programmers were taking more effort than necessary to sign-extend integers. I've been playing with 65xx assembly for at least 39 years, and I really can't remember if I got this little ditty from somewhere else long ago and simply forgot from where, or if it's an original idea of mine. Either way, here it is, all ten bytes and 13 cycles worth:

Code:
; Sign-extend A to 16-bits in ZP
    sta  ZP
    lda  #$7f
    cmp  ZP   ; cc for <0, cs for >=0
    sbc  #$7f
    sta  ZP+1 ; $ff for <0, $00 for >=0

Code:
; Promote int16 in ZP to int32
    lda  #$7f
    cmp  ZP+1 ; cc for <0, cs for >=0
    sbc  #$7f
    sta  ZP+2 ; $ff for <0, $00 for >=0
    sta  ZP+3

[If you're feeling a bit kinky, you can replace the SBC #$7F with ADC #$80 ...]

Comments, critiques, suggestions, corrections, insults?

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 02, 2020 8:53 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
With CMOS instructions, I can cut the 8->16 case down to 9 bytes with the same average cycle count (either 11 or 15 cycles, depending on sign):
Code:
  STA zp
  STZ zp+1
  ASL A ; carry set for negative
  BCC :+
  DEC zp+1
: ; continue
You could avoid the ASL A if the flags already reflect the contents of A, and branch on BPL instead of BCC. This saves 1 more byte and 2 cycles. This even has the virtue of preserving the value in A.

For the 16->32 case:
Code:
  LDA #0
  BIT zp+1 ; N flag reflects value in memory
  BPL :+
  DEC A
: STA zp+2
  STA zp+3
This is 11 bytes, best-case 14 cycles, worst-case 15 cycles. Not quite so good - but if we delete the final STA (thus extending the sign by only one byte), we are back to 9 bytes and 11-12 cycles.


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 02, 2020 1:33 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
The Sign-extend section the Nesdev Wiki's synthetic instructions page offers a similar technique for a constant-time replacement of A with its sign extension, but this one uses no branches. If one bookends it with a STA zp and a STA zp+1, it's almost (but not quite, by 1 byte and 1 cycle) as good as yours. It might be useful if you don't want to store A in the zero page, though, since it doesn't rely on re-using the original value of A as you need to do with your CMP.

Code:
      ; Constant-time version, but destroys the carry
            ASL A           ; sign bit into carry; use CPX etc. if using X reg
            LDA #$00
            ADC #$FF        ; C set:   A = $FF + C = $00
                            ; C clear: A = $FF + C = $FF
            EOR #$FF        ; Flip all bits and they all now match C

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 02, 2020 6:18 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
As always, there's more than one way…


Top
 Profile  
Reply with quote  
PostPosted: Mon May 11, 2020 10:24 pm 
Offline

Joined: Mon May 01, 2017 7:13 am
Posts: 83
Cute tricks, I like them. Will come in handy for me fairly soon.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


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: