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

All times are UTC




Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Sun Nov 17, 2013 1:16 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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 of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 1:32 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
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

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 1:42 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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 of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 3:05 am 
Offline
User avatar

Joined: Sat Sep 29, 2012 10:15 pm
Posts: 904
I would say signed for pc-relative, unsigned for sp-relative.

_________________
In theory, there is no difference between theory and practice. In practice, there is. ...Jan van de Snepscheut


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 6:22 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
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.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 11:01 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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 of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 2:16 pm 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
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.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 2:30 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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 of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 3:26 pm 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 460
Location: Canada
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.

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 3:45 pm 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
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.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 3:55 pm 
Offline

Joined: Sun Jul 28, 2013 12:59 am
Posts: 235
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.


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 4:46 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
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


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 6:42 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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 of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 17, 2013 6:46 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
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é

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


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 7 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: