6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Sep 20, 2024 3:26 pm

All times are UTC




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: 16bit inc/dec indirectly
PostPosted: Mon Feb 18, 2008 10:22 pm 
Offline

Joined: Wed Oct 04, 2006 11:19 pm
Posts: 8
Location: Munich | Germany
Hey *,

how would you solve this problem.

i like to 16bit-INC/DEC a value stored under address ptr1 (zp).

Code:
        clc
        lda #1
        adc (ptr1),y
        sta (ptr1),y
        bne *+9
        ldy #1
        sec
        adc (ptr1),y
        sta (ptr1),y


While INC looks kind of ok (but still I'm sure there would a better way) I have so my doubts about the DEC routine I wrote:

Code:
        lda (ptr1),y
        bne skip
        ldy #1
        lda (ptr1),y
        sta ptr2
        dec ptr2
        lda ptr2
        sta (ptr1),y
skip    ldy #0
        lda (ptr1),y
        sta ptr2
        dec ptr2
        lda ptr2
        sta (ptr1),y


Any suggestions to realize this more effectively?

grtx and thx,
\twh


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 12:48 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Off the top of my head, this is what I could come up with.

Code:
.proc inc_indirect
  ldy #0
  lda (ptr1),y
  tax
  inx
  txa
  sta (ptr1),y
  bne done
  iny
  ldy #0
  lda (ptr1),y
  tax
  inx
  txa
  sta (ptr1),y
done:
  rts
.endproc

.proc dec_indirect
  ldy #0
  lda (ptr1),y
  tax
  beq underflow
  dex
  txa
  sta (ptr1),y
  rts

underflow:
  dex
  txa
  sta (ptr1),y
  iny
  lda (ptr1),y
  tax
  dex
  txa
  sta (ptr1),y
  rts
.endproc


If there is any way you can cache values you use frequently in direct-page, though, do so. There's a huge performance improvement if you do. :)


Top
 Profile  
Reply with quote  
PostPosted: Tue Feb 19, 2008 1:27 am 
Offline

Joined: Tue Nov 18, 2003 8:41 pm
Posts: 250
All you're really doing is a hard coded 16 bit addition
or subtraction of 1

twh1st wrote:
Code:
        clc
        lda #1
        adc (ptr1),y
        sta (ptr1),y
        bne *+9
        ldy #1
        sec
        adc (ptr1),y
        sta (ptr1),y



You don't explicitly set y to begin, but presumably y is 0
so you can iny instead of ldy #1 and save a byte

If you start with 1 in the accumulator, the only way to end up
with 0 in the accumulator after an adc is to add FF and that will
also result in the carry being set, so the sec is redundant.

Your code becomes:

Code:
        clc
        lda #1
        adc (ptr1),y
        sta (ptr1),y
        bne *+7
        iny
        adc (ptr1),y
        sta (ptr1),y


personally, I'd code it like this:

Code:
        clc
        lda (ptr1),y
        adc #1
        sta (ptr1),y
        bcc *+7
        iny
        adc (ptr1),y
        sta (ptr1),y


Just because it's a little easier (for me, any way)
to see what's going on.

Dec can be roughly the same.
0 is the only thing you can start with in the accumulator
and subtract 1 from and end up with a barrow, ie
with the carry clear, and that will leave FF in the
accumulator. Adding FF to something is the same
as subtracting 1 (as far as the resulting byte and
ignoring flags)

Code:
        sec
        lda (ptr1),y
        sbc #1
        sta (ptr1),y
        bcs *+7
        iny
        adc (ptr1),y
        sta (ptr1),y


The last three instructions are the same so they
can probably be shared if that seems desriable,
but I'll leave that as an 'exercise for the reader' ;)


Last edited by bogax on Sun Dec 07, 2008 6:50 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 1:37 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
twh1st, your increment needs an LDY #0 near the beginning. Then your LDY #1 can be shortened to INY (which requires re-adjusting your branch distance-- a good reason to use labels). Otherwise it looks ok.

Then you can modify the increment routine to make the decrement routine this way:
Code:
        LDY #0
        LDA  (PTR1),Y
        DEA
        STA  (PTR1),Y
        CMP  #$FF
        BNE  done
        INY
        LDA  (PTR1),Y
        DEA
        STA  (PTR1),Y
done:

kc5tja's TAX INX/DEX TXA is necessary if you're using the old NMOS 6502. If you're not using a Commodore 64 or something where you're stuck with NMOS, I always recommend using the CMOS 6502 instead, partly for the added instructions.

If you're on a 65816 and have both the accumulator and index registers in 16-bit mode, I think you can do:
Code:
        LDX  #PTR1     ; Edit: omit the # per discussion below.
        INC  0,X

although I have been away from this stuff for awhile and might need some refresher time.

Edit: I see bogax posted while I was writing. Good post.


Last edited by GARTHWILSON on Tue Feb 19, 2008 3:58 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 3:05 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Your INC 0,X isn't going to work, because PTR1 points to the variable to be in/decremented. You have to use (dp),Y for this, unless INC/DEC take (0,X) as an addressing mode (I can't recall off-hand if it does).

If using the 65816 in 16-bit mode, though, I'd use this:

Code:
lda (ptr1) ; Yes, no ,Y suffix -- the 65816 assumes a zero-offset.
ina ; or dea
sta (ptr1)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 3:25 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
Ah yes, just take the # out of the LDX #. Now you'll get the final address in X, having loaded it from the pointer variable. So if PTR1 at address 0061-0062 for example contained 3FE6, now you'll increment the 16-bit number contained at 3FE6-3FE7.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 7:37 pm 
Offline

Joined: Wed Oct 04, 2006 11:19 pm
Posts: 8
Location: Munich | Germany
excellent!!! thank you guys!

btw, I forgot to copy'n'paste the "ldy #0" .. it was not meant to be set implicitly. :-)

grtx,
\twh


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 19, 2008 7:42 pm 
Offline

Joined: Wed Oct 04, 2006 11:19 pm
Posts: 8
Location: Munich | Germany
GARTHWILSON wrote:
kc5tja's TAX INX/DEX TXA is necessary if you're using the old NMOS 6502. If you're not using a Commodore 64 or something where you're stuck with NMOS, I always recommend using the CMOS 6502 instead, partly for the added instructions.


I'm coding with an Atari 8bit. I never heard of different 6502 implementations like CMOS or NMOS. So I guess I have a NMOS 6502 because I never saw opcodes like "DEA" or "INA".

thanks anyway!!

grtx,
\twh


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Apr 29, 2008 7:09 am 
Offline

Joined: Wed May 21, 2003 1:08 pm
Posts: 27
Location: Germany
twh1st wrote:
GARTHWILSON wrote:
kc5tja's TAX INX/DEX TXA is necessary if you're using the old NMOS 6502. If you're not using a Commodore 64 or something where you're stuck with NMOS, I always recommend using the CMOS 6502 instead, partly for the added instructions.


I'm coding with an Atari 8bit. I never heard of different 6502 implementations like CMOS or NMOS. So I guess I have a NMOS 6502 because I never saw opcodes like "DEA" or "INA".

thanks anyway!!

grtx,
\twh


Hi twh,

the Atari 8bit has a NMOS CPU, you might have a CMOS Type in your floppy when you have a Speed Enhancement in there (The Compyshop Speedy is using a 65C02). Unfortunately, in the Atari XL/XE line, there is now easy way to replace the NMOS 6502 for a CMOS one, because the Atari 6502 has this special "halt" signal for sharing the bus with Antic. I've read that it is possible to exchange the CPU in old Atari 800 machines, as they use a stock 6502 NMOS (and not the special Atari one).

Carsten


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Apr 30, 2008 11:08 pm 
Offline

Joined: Sat Sep 22, 2007 1:31 am
Posts: 24
Quote:
Unfortunately, in the Atari XL/XE line, there is now easy way to replace the NMOS 6502 for a CMOS one, because the Atari 6502 has this special "halt" signal for sharing the bus with Antic.


Shouldn't /RDY be a replacement to halt? You can pause the CPU as long as you need with /RDY if I recall correctly.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu May 01, 2008 6:38 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
RDY is active-high -- no overbar for the signal name. So, if RDY goes low it will halt the processor. However, it will not release the bus. For this, a separate signal (BE for the 65816 at least; not sure if BE also exists on 65C02 as well) is used. If BE doesn't exist on the 65C02, external, three-statable bus buffering is required.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu May 01, 2008 2:14 pm 
Offline

Joined: Sat Sep 22, 2007 1:31 am
Posts: 24
And I take it the 65c02 or 65cs02 do not have buffers on the processor side to protect from another device trying to drive the same address bus? (not necessarily tri-state)

Like if the processor is halted via /RDY and the address bus has a random (but static while paused) value asserted by the CPU - you could have a logic device that would sort of invert the state of the address lines for another device to drive the address bus. Lines that are driven high by the original processor could be pulled to low and vice versa when needed by the another processor. I'm not sure if this would damage the original CPU or not.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu May 01, 2008 8:53 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
WDC's 65c02 does have BE (active-high bus enable) on pin 36 of the DIP, 40 of the PLCC, and 34 of the PQFP. (It's the same pin on the PLCC and PQFP, but they're numbered differently, the PLCC starting with pin 1 in the middle of the top and the PQFP starting on the corner.) They also have a ML\ (active-low memory lock) output (pin 5 of the DIP) and an VP\ (active-low vector pull) output (pin 1 of the DIP where other manufacturers had ground). Pin 21 of the DIP is still ground. WDC's 65c02 also lets you stop the clock indefinitely in either phase.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri May 02, 2008 4:59 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
In fact, internally to the CPU chip itself, that's all RDY does -- it simply gates the clock in phase-1!!


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 15 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: