[Coco] GCC: DFLOAT / DIRECT_PAGE

David dbree at duo-county.com
Sat Nov 15 23:22:00 EST 2003


On Sat, Nov 15, 2003 at 01:06:41AM -0500, John E. Malmberg wrote:
> David wrote:
> >On Fri, Nov 14, 2003 at 11:31:41AM -0600, John E. Malmberg wrote:

> >>If I can do it, this is what I will do for direct_page:
> >>
> >>1. The compiler will treat it like a hint, just as register is a hint.
> >>  This means that the compiler will prefer to use direct page addressing
> >>  mode for the designated variable, but since it also has the absolute
> >>  address for the variable, or a stack/register relative address for
> >>  the variable, it can decide to use that instead.
> >>
> >>2. The compiler will default to treating the direct page pointer as
> >>  what other platforms refer to as a frame pointer for stack variables
> >>  that are in range.
> 
> When I wrote #2, I forgot about the 256 byte alignment issue.  That 
> almost completely eliminates using it for stack variables.  But it is 
> still fair game for static varaibles anywhere in the program.
> 
> >
> >Yes, but how to get the directive "direct" installed.  Won't this need
> >to be installed as a reserved word?
> 
> No.  It would be installed as a GNU extention of either 
> __mode__(direct_page, params...) or __attribute__(direct_page, params...)
> 
> Then for the cross compiler, there is a predefine of
> 
> #define direct_page(params...) __attribute__(direct_page, params...)
> 
> I do not have the syntax exactly right, but that is how GCC is 
> implementing this feature for other targets.
> 
> >Check out the files c-parse* and
> >also c-common.h, all in the gcc directory.  I really believe that this
> >word will need to be added to all(?) these places.
> 
> I will look at them later, but from looking at the 68HC11 and the other
> targets, it still looks like if the right stuff is put in the *6809* 
> files, the compiler will be able to do it with out changing the common code.
> 
> >Also, as for using hints.  I believe that the usage of "direct" will
> >need to be absolute.
> 
> A "direct" psect could be absolutely based, but since the compiler and 
> linker already know how to deal with ones that are not, there is no 
> reason to restrict them.
> 
> The compiler should already know how to put a psect at a fixed location.
> 
> >If it's defined, use direct referencing else use
> >16-bit.  At least, if we're dealing with linkable modules.  Let's look
> >at the process of compiling a program.  If the compiler decides which
> >mode to use in the assembler output, although it realizes the relative
> >addresses for the variables in _this_ module, it cannot know the
> >ultimate address in the final program.
> 
> The compiler knows the relative address, the linker knows the absolute 
> address.  The mechanism is already there to figure it out.
> 
> If the compiler generates "direct" addresses, it will need to make sure 
> that the direct register has the correct value, and that value will 
> either be known at compile time, or supplied by the linker, or even the 
> loader.
> 
> As far as the compiler needs to be concerned, a direct page reference is 
> just a variant of index addressing.  And the compiler knows how to do that.
> 
> Generally a compiler, GCC included, groups code and data in to program 
> sections, commonly called psects.
> 
> The direct page attribute applied to a psect that would have the 
> requirement that it is aligned on a 256 byte boundary.
> 
> > However, this is where the
> >program code is generated.  Suppose we're doing "cc p1.c p2.c p3.c".
> >Now, after the assembler source files are generated and the object
> >modules are created, the linker will go through and first allocate all
> >the direct-page variables (beginning with whatever might be in the
> >lead-in module, then place the d-p variables of p1 above those.. dp of
> >p2 above those.. then p3. Now, it goes back and, beginning at the next
> >address above p3's last dp variables, it begins the same process with
> >the non-dp variables.
> 
> No, the linker will collect all of the psects that have the direct page 
> attribute and are compatable into one cluster, and fixup the symbol that 
> the compiler initialized the direct page register.  Multiple clusters 
> will be generated as needed.  An OS-9 compatable linker could know to 
> put the static variables in one loadable modules, and the executable 
> code in a set of other modules.

In OS-9, the variables don't go into a "module", per se.  Actually, in
the program module that would be compiled, the data area doesn't exist
(except for the data that goes into initialized variables.  But even
this is not at its final location, but will be relocated upon program
execution.

I don't exactly catch what you mean when you refer to modules.  After
linking, there will be only one module - the program module.  The data
area doesn't exist until the program is loaded into memory.

> But here I am losing precision, because there are words that have 
> different meanings.
> 
> >For this reason, it would be impossible for the compiler to
> >automatically determine what would be DP at compile time.
> 
> The compiler knows that each direct page psect has an alignment of 256 
> bytes.  Having it take advantage of this for stack variables may be a 
> challenge, but is doable.
> 
> The compiler only needs to know the alignment of the direct page 
> register.  The linker or the program loader.
> 
> >If we do provide our own assembler/linker, one thing would be needed.  I
> >believe it was Mike Knudsen who mentioned that the MW linker did not
> >warn you if you had more than 256 DP bytes.  The linker should
> >check and warn you if more than this max was reached.  It shouldn't be a
> >problem to implement, and would be a very good addition.
> 
> I have not used the MW linker, so I am not aware of it's limitations.
> 
> But there is no reason for their to only be one direct page section. 
> There can be up to 256 of them, only one active at any given time.
> 
> If the compiler is working with direct page variables that are not in 
> the same psect, it would know that it would need to use a different 
> address mode for at least one.
> 
> This is something that the GCC compiler already should know how to do, 
> and so should any linker that goes with it.
> 
> >>  A direct page reference, depending on the internals of the CPU may take
> >>  one less clock cycle than an 8 bit stack or register offset.  I would 
> >>  need
> >>  to look at the 6809 specs to see if this is the case.  The difference
> >>  is that a register offset has to do an 8 bit fetch and 16 bit add, and
> >>  a direct page reference just has to do an 8 bit fetch.
> >>
> >>3. The direct_page attribute for a variable name will be able to take
> >>  a value indicating the program section that the variable will be in.
> >>  The attributes of the program section will determine the real address
> >>  of the program section.  GCC already knows how to do the program section
> >>  part.
> >
> >I'm not sure I understand what you're saying here.  And another thought
> >just occurred to me.  I've been thinking in terms of all variables from
> >all modules to be stored consecutively in one area.
> 
> That is a model for all static variables, for languages like BASIC.  For 
> languages like C, that is not the case.  For reentrant code, variables 
> go in and out of scope, and typically live only on the stack or in 
> registers.

PS to the below:
After rereading this, I wish to make a note.  I suppose there are two
definitions to a static variable.  The one you are using above is for
variables define within a function or block.  The static variable I
refer to below is one defined as static but outside any function.  This
will live in the scope of any function occurring in that file.  Well,
actually they are still the same thing, except for the scope..  But, in
OS9 - I don't know about other systems, this _will_ be defined with the
global variables.  It will occupy a space in the data area everywhere,
but won't be known to any function external to that file.

--- end PS ---

This is true for static variables, but global variables live throughout
the entire program.  One other note in OS9, the linker - at least the
one we have for the coco - does not make any difference between global
and static variables as far as allocation is concerned.  It allocates
them in the order it finds them.  If proga.c has, in sequence, int a,
static int b int c, then they will be allocated in that order, a, then
b, then c.

> >This would be the case for OS9,
> 
> No, the case for OS9, unless OS9 reserves the direct page register for 
> it's own use, would be for a program to have as many direct page 
> sections as it needs.  These sections can be put at fixed memory 
> locations by the linker, or at dynamic locations, where the compiler 
> knows where they are.

In OS9, on entry into the program, the DP points to the base of the data
area.  Very rarely, AFAIK, is this altered.  The strategy being that you
define small (char, int, etc) variables that are accessed most often, to
be direct so that they will be placed first in the data area and that
the compiler will then know to use DP mode to access them.  Suppose
proga.c defines three variables like this:  int a1, direct int dpa, int
a2, then the next prog, progb.c, defines int b1, direct int dpb, char b2.
The linker will allocate these in this order, dpa, dpb, a1, a2, b1, b2 -
assuming no other programs ( and not considering the cstart data).

> >but for RS-BASIC programs, this would not be necessary.
> >The only reason for this would be to utilize the DP function.
> >Otherwise, it would not hurt for the variables to simply be stored at
> >the end of the code for the module.
> 
> The static variables are are put in program sections with the same name, 
> and the linker puts them in the data segment of the image.

IOW, all data is placed in a single block?  That's what I was origially
thinking, but, for RS-BASIC, it would not _have_ to be, as far as I can
see.  I'd think it might be simpler to put them all in one block, but it
doesn't seem mandatory.  In a RS-BASIC program, the data and code are
all in one block (except for multiple load files, of course).  (I think
that's the correct name).

> The linker uses a process known as a fixup, to make sure that the 
> compiler loads the direct page register before referencing the variables.
> 
> On some operating systems, the final fixups are done by the operating 
> system when it loads an executable module into memory.
 
> I see that it would be vary useful.  And if you treat the direct page as 
> a psect that is aligned on a 256 byte foundary, the compiler already 
> knows how to transparently manage any number of these psects, fixed or 
> relocatable.  As the register has only 256 possible values, it puts a 
> bound that only 256 psects could possibly have the direct attribute.

I don't understand what you will be referencing.  It seems that it would
be difficult to reference the variables.  Also, if you are going to
alter the DP depending on where you are, I think you'd need to store the
entry value of the DP on entry into each function - maybe a stack push -
and then restore this value on exit.  Otherwise, the DP would not be
valid after returning to the calling function.  It seems to me that,
except for functions that have very intensive loops, that it would
involve as much or more overhead in program bytes and cpu cycles than it
would save.

> > I'm still struggling with how to determine
> >if an operator is data in the program.  This needs to be done in order
> >to determine whether the operand should be referenced by pc or y
> >(assuming we keep y as the data pointer)..
> 
> That is something that I need to look at.  What really matters in that 
> decision is the calling conventions for the run time library.

It doesn't matter if dealing with RSDOS, but for OS9, addresses within
the program area must be indexed off the pc, and data variables need to
be indexed off some other register - if we stick with MW's convention,
this will be the y register.

> GCC has some expectations of that some registers will be used for some 
> things.

These are specified in the *.h file, aren't they?

> > I had hoped that SYMBOL_REF
> >would be a data pointer, but apparently not.  Can someone tell me what
> >gcc interprets SYMBOL_REF, LABEL_REF and PROG_REF (or maybe PROGRAM_REF)
> >to be?
> 
> Try the command "info gccint" at the command prompt, it claims to be up 
> to date for GCC 3.3.1 on my installation.

I've looked at it quite a bit - actually the one for 3.1.1 mostly.

> I have not had time to study it that closely.

It's kinda vague.  I think I need something a bit more elementary.  I
believe that it states that it is more of a reference than a tutorial.

> I do not know if I can achieve my goals, but from what I can see so far, 
> something like this has been implemented with other targets.
> 
> What is bothering me right now, is I can see how it is done by examining 
> the files emitted by configure and make, but I have not found out yet 
> how to specify it on the input files.

Same here.  It may be quite simple if and when we find it.  As you
mentioned, perhaps the later versions of gcc may have new tools
included, but after perusing the diff files for the ports of gcc to OSK,
I see that they did quite a bit of patching to the base files.  Many of
the patches deal with making it a native OSK compiler, whereas we
already have the host characteristics built in, but there are many,
many places where they add conditions dealing with it being a data area.
Again, I'm more interested in OS9 than BASIC.



More information about the Coco mailing list