6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 7:46 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Tue Mar 03, 2015 8:27 pm 
Offline
User avatar

Joined: Sun Dec 29, 2002 8:56 pm
Posts: 460
Location: Canada
Quote:
I dunno how smart that would have to be. I tend to parse expressions into Reverse Polish Notation before trying to evaluate them. Although I've never had occasion to do it, it seems to me that it wouldn't be that hard to scan the RPN form just to see what the maximum number of pushes outstanding during evaluation will be. Of course a compiler would have to also track the maximum number of pushes found in ALL expressions appearing in a function to be able to pre-allocate the appropriate amount of stack space at function entry.


This is not easily doable with a language like 'C' where you can allocate stack space dynamically using alloc() for instance. I suppose it could be a compiler option if one is not using dynamic stack allocations.

_________________
http://www.finitron.ca


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 04, 2015 12:56 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 411
Location: Minnesota
Quote:
This is not easily doable with a language like 'C'


Hmmm...again I dunno. A 'C' compiler could certainly determine the maximum stack space needed for the evaluation of every expression in the function that used 'alloca()' (just like any other function). It is true that it would be difficult to determine how much extra stack space a call to 'alloca()' with a non-constant size argument would require, but is it even ever necessary to do so whatever the argument value?

'alloca()' can't be used until after the function using it has started execution and (assuming my idea works) after the space necessary for the evaluation of all expressions in that function has been allocated. I don't know much about the internals of how 'alloca()' might be implemented, but I imagine what it does is extend the bottom of the stack frame at by the amount of space requested. After that, it's the programmer's responsibility to manage that space. Nothing the compiler does affects it, so the compiler doesn't have to worry about it. It only has to concern itself with what happens above the allocated space.

And to be pedantic, 'alloca()' is a standard library function, not part of the 'C' language itself :wink:


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 06, 2015 6:37 am 
Offline

Joined: Sun Apr 10, 2011 8:29 am
Posts: 597
Location: Norway/Japan
teamtempest wrote:
Quote:
This is not easily doable with a language like 'C'

It is true that it would be difficult to determine how much extra stack space a call to 'alloca()' with a non-constant size argument would require, but is it even ever necessary to do so whatever the argument value?
I'm not sure if you mean '..necessary to [call alloca() with a non-constant size argument]'? If yes, then, absolutely, nearly the only reason for using alloca() in the first place is for when you don't know the size at compile time. Otherwise you would simply declare the array or whatever as a normal local variable and get it allocated on the stack the normal (predictable) way.

With newer C standards (C99, but not C90 or earlier) it's also possible to have dynamic local variables which mostly removes the need for alloca(), e.g.
Code:
void function (int size) {
  char a[size];
..
}
which obviously creates the same unpredictable stack size usage.


Top
 Profile  
Reply with quote  
PostPosted: Fri Mar 06, 2015 3:22 pm 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 411
Location: Minnesota
All good points.

Quote:
With newer C standards (C99, but not C90 or earlier) it's also possible to have dynamic local variables


Yikes!

Still...in my naive way I imagine that this would change the function entry code only in a relatively minor way. Instead of allocating a fixed amount of stack space at entry - ie., altering the stack pointer by a constant value - it would first have to calculate the result of an expression, then use that result to reset the stack pointer.

Mmm, perhaps not quite so simple. Evaluating the expression might require its own temporary storage. That amount would be a constant, though. So perhaps the stack pointer would have to be reset twice - once for the evaulation of what the "real" amount needed would be, then a second time for the execution of the function itself. Still probably faster - and perhaps cleaner - than using 'alloca()'.

Just musing here...


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 13, 2015 2:10 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
I have reimplemented the column 3 instructions to use a base pointer relative addressing mode. The negative and positive offsets are easy to use. The parameters, return address, previous base pointer, static link, etc. are located at positive offsets from the base pointer, which is assigned to X. Local variables and dynamic allocations are located at negative offsets from the base pointer.

An interesting result is that the OSX prefix instruction, which swaps the functionality of S and X, forces stack pointer relative addressing when applied to a base pointer relative instruction. In other words, X temporarily assumes the functionality of S, and S assumes to the functionality of X. For the the base pointer relative addressing mode, S becomes the base pointer, which means that the addressing mode shifts from base pointer relative to stack pointer relative.

Edit:[MichaelM]
The highlighted final sentence in the previous paragraph is incorrect. In a moment of confusion, I incorrectly surmised the effect of the OSX prefix instruction on the base pointer relative addressing mode. What I should have written is that for the auxiliary stack, for which X is the stack pointer, the base pointer and the stack pointer are one and the same: X. Thus, for the auxiliary stack, the base pointer relative addressing mode is actually the stack pointer relative addressing mode. With the OSX prefix, X becomes a stack pointer, the auxiliary stack pointer, and S becomes an index register. The base pointer addressing mode always uses X as the base pointer.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Sun Aug 02, 2015 1:35 pm 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
I have just realized that base pointer relative addressing mode that is included in the M65C02A is independent of the stack. With base pointer addressing, any block of memory can be indexed for the operands of the column 3 instructions. Because the base pointer that I have chosen for the M65C02A is X, which can also implement an auxiliary stack, I have chosen to compensate for the -1 offset of a 6502 stack. That is, the stack pointer points to the first free location rather than the last used location (as is the case for many other processors), i.e. -1 rather than 0.

The base pointer addressing mode that I've implemented automatically adds 1 to the offset calculation. Therefore, the offset in the instruction is 0 based rather than 1 based; I think this is a more natural representation. Thus, an offset of 0 refers to the first byte/word (LSB first) on the stack or memory block being indexed using the base pointer relative addressing mode.

_________________
Michael A.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

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