6502.org
http://forum.6502.org/

Stack/PC-relative addressing: signed or unsigned?
http://forum.6502.org/viewtopic.php?f=10&t=2774
Page 1 of 1

Author:  fachat [ Sun Nov 17, 2013 1:16 am ]
Post subject:  Stack/PC-relative addressing: signed or unsigned?

Hi there,

I recently got a comment to my (unfortunately still not getting further) 65k docs.
One part included the question how address memory locations "before" a register pointer.
Like in the 65816 with stack-relative addressing or PC-relative addressing for example.

In my 65k design I initially thought to use unsiged offset, but signed offset looks compelling.
I.e.

Code:
    LDA (S,$ff)  -> reads address at Stack pointer-1
vs
    LDA (S,$ff)  -> reads address at Stack pointer + 255

This gets more interesting when you consider additional operand widths like
Code:
    LDA (S,$ffff)  -> reads address at Stack pointer-1
vs
    LDA (S,$ffff)  -> reads address at Stack pointer + 65535


I am not sure though what is the "least surprise" way of going?
Having 128 instead of 256 bytes in the positive range looks limiting, but you could still be using 16bit offsets then.

What is the 65org32 doing in this respect?

What do you think?

Andre

Author:  Dr Jefyll [ Sun Nov 17, 2013 1:32 am ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

Hi Andre -- good question, fun to contemplate! Did you have a solution in mind for the problem of interrupts sharing the stack? Anything below SP is subject to getting trashed unexpectedly. So is there any need to address what's down there?
Quote:
Having 128 instead of 256 bytes in the positive range looks limiting
Nothing says the positive and negative ranges need to be equal. Your logic could establish a 75-25% split, for instance -- although there'd be a price to pay in clock speed, I suppose.

-- Jeff

Author:  fachat [ Sun Nov 17, 2013 1:42 am ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

Dr Jefyll wrote:
Hi Andre -- good question, fun to contemplate! Did you have a solution in mind for the problem of interrupts sharing the stack? Anything below SP is subject to getting trashed unexpectedly. So is there any need to address what's down there?

In fact that was a comment I got. It mentions some edge cases, but case looks good: if you have PC-relative code, this forces you to put your local variables _behind_ the code. You can't put it in front.
Quote:
Quote:
Having 128 instead of 256 bytes in the positive range looks limiting
Nothing says the positive and negative ranges need to be equal. Your logic could establish a 75-25% split, for instance -- although there'd be a price to pay in clock speed, I suppose.


Yes, the easiest and resource-friendliest way is the one that's already there, for branches for example.

Andre

Author:  enso [ Sun Nov 17, 2013 3:05 am ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

I would say signed for pc-relative, unsigned for sp-relative.

Author:  BigDumbDinosaur [ Sun Nov 17, 2013 6:22 am ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

fachat wrote:
Hi there,

I recently got a comment to my (unfortunately still not getting further) 65k docs.
One part included the question how address memory locations "before" a register pointer.
Like in the 65816 with stack-relative addressing or PC-relative addressing for example.

In my 65k design I initially thought to use unsiged offset, but signed offset looks compelling.
I.e.

Code:
    LDA (S,$ff)  -> reads address at Stack pointer-1
vs
    LDA (S,$ff)  -> reads address at Stack pointer + 255

This gets more interesting when you consider additional operand widths like
Code:
    LDA (S,$ffff)  -> reads address at Stack pointer-1
vs
    LDA (S,$ffff)  -> reads address at Stack pointer + 65535


I am not sure though what is the "least surprise" way of going?
Having 128 instead of 256 bytes in the positive range looks limiting, but you could still be using 16bit offsets then.

What is the 65org32 doing in this respect?

What do you think?

Andre

Well, the '816 only addresses the stack with positive offsets, since as Jeff noted, anything at or below the stack pointer is subject to being stepped on. So for me at least, least surprise would be the '816 behavior.

Author:  fachat [ Sun Nov 17, 2013 11:01 am ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

enso wrote:
I would say signed for pc-relative, unsigned for sp-relative.


As BDD and you point out, positive offsets work best for stack-relative. And it is also basically like extending the existing indexed addressing modes.

Only for PC-relative I found an edge case.

But making just this one diffferent, that would violate the principle of least surprise, wouldn't it?

I had even thought of making byte-wide offsets positive, and larger ones signed, but that is even more a surprise..

Or do you think this different behaviour would useful enough to be acceptable?

Author:  MichaelM [ Sun Nov 17, 2013 2:16 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

I think that we've lost sight of the modular nature of these stack address operations.

Since the results are wrapped at the boundaries, S+255 and S-1 yield the same pointer. For example, suppose S=128, S+255=383. With the stack addresses wrapping in the range 0...255, 383 ($17F) is equivalent to 127. In other words, the resulting effective address pointer is equivalent to S-1.

The similar results apply to the case of where the stack region is expanded to 16 bits.

Author:  fachat [ Sun Nov 17, 2013 2:30 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

Michael, my af65k has (or will have) an extended stack that does not wrap on a page boundary of page one.

In fact I found an interesting use case for signed offsets on the stack:

If you normally think this way: The stack contains local variables, i.e. variables available to this thread only. The code would look about this:

Code:
   .(      ; start of subroutine
   SBS #20      ; make place for local variables
   STA (S,0)   ; use values on stack with stack-relative addressing
   ...
   ADS #20      ; clean up stack
   RTS
   .)

(where SBS and ADS substract and add an immediate value from the stack pointer), this could more efficiently be done using

Code:
   .(      ; start of subroutine
   STA (S,-20)   ; use values on stack with stack-relative addressing
   ...
   RTS
   .)


Works best if you have a local routine without subroutine calls, and no PHx.

Still undecided....

Author:  Rob Finch [ Sun Nov 17, 2013 3:26 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

If you are adding more regs then stack variables would likely be addressed with a base or frame pointer register. Then regular +-offset addressing can be used and stack pointer offset addresses are avoided.

I guess the gist is that, most of the time for smaller routines the offset into the stack is a small number much less than 127 bytes. Whether or not negative displacements are allowed doesn't affect software very much. It just seems a bit wasteful to have negative displacements that are never used. But on the other hand most positive displacements aren't used either.

I was debating whether or not to support a displacement outside the eight bit range for the RTF65002 because it takes extra instructions.

Another issue is whether or not to support separate instructions for adding and subtracting off the stack pointer. I didn't. RTF65002 just uses subtract only.

I'd say flip a coin on it.

Author:  MichaelM [ Sun Nov 17, 2013 3:45 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

Andre:

The point is not that stack wraps in page one, but that it wraps at the boundaries of the address computation. For the 6502, the stack arithmetic is limited to 8 bit operations. For the '816, the stack arithmetic is 16 bits.

A value of $FF may be considered as signed or unsigned at the discretion of the programmer, but the results of any 8-bit addition operation are the same regardless of what he considers the value to represent: +255, or -1.

Similarly, an offset of $FFFF to the '816 stack pointer will result in the same effective address result unless the carry out of the MSB is allowed. In which case, simple protection offered by the paged memory system is bypassed.

If your intent is to have offsets whose widths are less than the arithmetic, i.e. 16 bit offsets in a 32 bit space, then I would recommend treating them as signed offsets so that they are consistent with the program relative offsets you appear to be considering.

I like your example for using a signed bias to allocate local variables on the stack, but I think that there's an issue that you have not considered. In your signed stack offset example, you do not adjust the stack pointer, because as you point out, it requires two operations. However, in the event of a trap (or interrupt), the processor state will overwrite your local variables. You can try to avoid this issue by using a different stack for these situations, but I suspect that it is better to deal with this issue directly, and allocate the space on the stack using the first method you describe in your previous post.

BTW: isn't -20 equivalent to 256-20=236, which is $EC (8 bits), or $FFEC (16 bits)? I suspect that the assembler is doing the signed/unsigned radix 10 to radix 2 (or radix 16) conversions. I sometimes fall into the trap of thinking of unsigned numbers as being distinct from signed numbers as far as the binary arithmetic unit is concerned.

Author:  nyef [ Sun Nov 17, 2013 3:55 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

Another approach that would use signed offsets against the stack pointer is to have a "red zone" immediately below the stack pointer which is skipped over during interrupt processing, providing a safe area for use until the next subroutine call. ISTR that such a "red zone" is used in (some?) x86-64 ABIs, where something like 128 bytes of space below the stack pointer are protected during signal handling.

Author:  barrym95838 [ Sun Nov 17, 2013 4:46 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

fachat wrote:
... What is the 65org32 doing in this respect? ...

Hi, André.

I believe that the 65Org32 (and my 65m32) avoid this problem entirely, because every offset, address and constant is a 32-bit value, so wrap occurs naturally. -1 is always $ffffffff, never $ff or $ffff, or even $ffffffffffffffff.

I was looking through your 65k specs recently to find some ideas on how to implement my status register. I goal is to start out flat, simple, and mode-less, but I want to provide a simple upgrade path to a virtual-capable design without breaking existing code for the simpler one, or complicating the hyper-visor unnecessarily. It appears that the 65GZ032 (linked on your page) was close to completion, but stopped short of providing a complete picture of how the mode-switching mechanism worked.

My design actually looks similar to the GZ, but doesn't try nearly as hard to allow binary compatibility or variable-width addresses and constants. Dieter, Garth, and Jeff have been helping me and encouraging me to complete my specification, but the status register is causing me some grief, because I keep doubting my ability to anticipate future snags. Do you have any links or advice that could get me back on track? If I can't do it myself, I'm going to ask Dieter for some detailed help. He has been very generous with his time so far, and I would prefer not to impose on him further, but that's starting to look more and more like my best chance to get this thing completely documented this year. Simulation should follow rather easily, assuming that I don't have to endlessly revise the specification, and a myopic spec is what I'm really trying to avoid right now.

Thanks,

Mike

Author:  fachat [ Sun Nov 17, 2013 6:42 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

barrym95838 wrote:
fachat wrote:
... What is the 65org32 doing in this respect? ...

Hi, André.

I believe that the 65Org32 (and my 65m32) avoid this problem entirely, because every offset, address and constant is a 32-bit value, so wrap occurs naturally. -1 is always $ffffffff, never $ff or $ffff, or even $ffffffffffffffff.

My core is 6502 compatible and uses prefixes to change absolute or zeropage addresses into offsets. Thus they are smaller than the address width (if chosen to use 32 or more). So I need a decision here. At the moment indeed I tend to use signed offsets, but probably have to check other CPUs as well. What does the x86 do here? Ok, here http://www.bailopan.net/blog/?p=50 it says that AMD64 offsets are 32 bit, so code can only be 2G away from data - which means signed offset.
Quote:
I was looking through your 65k specs recently to find some ideas on how to implement my status register. I goal is to start out flat, simple, and mode-less, but I want to provide a simple upgrade path to a virtual-capable design without breaking existing code for the simpler one, or complicating the hyper-visor unnecessarily. It appears that the 65GZ032 (linked on your page) was close to completion, but stopped short of providing a complete picture of how the mode-switching mechanism worked.

Yes, it's a pity the GZ032 disappeared. I have decided to use the so-far unused bit5 of the standard status register to indicate a "wide" status register. I am not sure how complicated that gets in terms of programming the chip later, but it looks like a feasible idea.
It introduces a small incompatibility though - someone writing a status register to the stack with bit5 set to zero, and expecting PLP to only read back that one byte will fail. But my assumption is that these cases are seldom.
Quote:
My design actually looks similar to the GZ, but doesn't try nearly as hard to allow binary compatibility or variable-width addresses and constants. Dieter, Garth, and Jeff have been helping me and encouraging me to complete my specification, but the status register is causing me some grief, because I keep doubting my ability to anticipate future snags. Do you have any links or advice that could get me back on track?

I'm sorry, but I have my knowledge from what I read on the nets and then thinking about it myself. I don't think I have written up something about the status register like I did for other things here http://www.6502.org/users/andre/65k/features.html
The status register I guess "evolved" as it is now. BTW, the PLP handling the extended status register is there since today, as I decided to add the signed comparison flag (and then had place for the odd/even flag as well :-)

Quote:
Simulation should follow rather easily, assuming that I don't have to endlessly revise the specification, and a myopic spec is what I'm really trying to avoid right now.


A stable specification is very valuable indeed. In addition I use a generational approach. I have a description of the processor's feature in an XML file and generate the docs from it, as well as some VHDL tables. That helps to quickly fix smaller changes.
Quote:
Thanks,

Thank you for your comments!

André

Author:  fachat [ Sun Nov 17, 2013 6:46 pm ]
Post subject:  Re: Stack/PC-relative addressing: signed or unsigned?

MichaelM wrote:
I like your example for using a signed bias to allocate local variables on the stack, but I think that there's an issue that you have not considered. In your signed stack offset example, you do not adjust the stack pointer, because as you point out, it requires two operations. However, in the event of a trap (or interrupt), the processor state will overwrite your local variables. You can try to avoid this issue by using a different stack for these situations, but I suspect that it is better to deal with this issue directly, and allocate the space on the stack using the first method you describe in your previous post.

Yes, thanks, I absolutely forgot that! Thanks for pointing it out!
Quote:
BTW: isn't -20 equivalent to 256-20=236, which is $EC (8 bits), or $FFEC (16 bits)? I suspect that the assembler is doing the signed/unsigned radix 10 to radix 2 (or radix 16) conversions. I sometimes fall into the trap of thinking of unsigned numbers as being distinct from signed numbers as far as the binary arithmetic unit is concerned.

If the assembler is intelligent enough it could optimize the offset width from 16 to 8 bits if there are signed offsets.
I am not sure if it's a good thing, but I sometimes use both negative numbers and positive numbers at the upper unsigned end because I know what they mean. After all, sometimes it _is_ a small negative number, and sometimes it _is_ 255....

André

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/