"small data" in m68k gcc?
Bernardo Innocenti
bernie@develer.com
Mon Oct 13 01:14:00 GMT 2003
On Sunday 12 October 2003 23:49, colin-gcc@horizon.com wrote:
> I asked about this on gcc-help, but nobody had a useful suggestions,
> so I'm searching further afield for useful suggestions.
I've forwarded this to Gunther Nikl who is probably confident
with the small-data model used on the Amiga.
> I'm trying to move some code away from a proprietary compiler, but
> the multitasker depends on having A5-relative global variables, and
> I'm having a hard time figuring out how to generate them.
This has been quite common practice on the Amiga to generate residentable
programs and reduce code and relocs size. Actually, the Amiga uses
A4-relative addressing because A5 is used as a frame pointer and A6 is
reserved for calling shared library functions through a jump table.
> -fpic generates an 15-relative table of pointers to global variables,
> but that's a lot slower. 16-bit offset addressing modes are smaller
> and faster than the 32-bit absolute addresses that GCC usually generates.
Yes, that's the GOT. It allows more than 32KB of data, but it's somewhat
slower.
I've recently committed patches on mainline (will-be GCC 3.4) to
support two new addressing modes used in uClinux:
-msep-data uses the GOT scheme for data, but prevents saving and
restoring A5 and reloading it each time with the GOT pointer.
-mid-shared-library is an exotic scheme with a double indirection to
symbols in text and data segments. It allows scattering a program
and its libraries in memory. Code does not need to be relocated,
therefore a single copy (perhaps in ROM) is shared by different
processes.
The AmigaOS patches Gunther Nikl has probably implement something
closer to your need, but they've not yet been merged into GCC.
> I'd also like to be able to heve "true globals" in the low 32K of memory
> addressed with the 16-bit absolute addressing mode.
This would require adding a new attribute for declarations.
Something like __attribute((zero_page)).
> To round it out, ideally some read-only data could usefully use the
> PC-relative addressing mode.
This is also possible. GCC already places const data in the text
segment and you can use the PLTPC or GOTPC addressing mode to
retrieve it. Assembler support is required, but GAS has it already.
There's currently no distinction between -fpic and -fPIC in the
m68k back-end. If you want to generate optimized code for small
programs (less than 32KB of code), you'll have to hack into m68k.md
to use 16bit displacements instead of 32bit.
> Of course, some data might not fit into the 64K spaces, so a 32-bit
> absolute address would be required for it.
The smartest thing would be having the linker perform this
optimization automatically for relocations <32KB.
It's somewhat perverse to let the linker mess with assembly code,
that's probably why nobody ever did it.
> I was hoping that there was an m68k-specific variable attribute that
> could specify one of the four addressing options to use for references to
> a particular variable, and a command-line option to pick the default one.
There's currently nothing like this in GCC, but it _could_ be added
with some effort.
> It seems like the ort of useful thing that someone has probably
> implemented over the years.
The Amiga people always enjoied A5-relative addressing with SAS/C
(formerly known as Lattice C) and Storm C.
I'm almost sure GCC patches for AmigaOS offer something similar,
and it would be a nice thing to have also for other m68k platforms.
Of course smart A5 addressing requires some support in the startup
code (loading A5 for the first time).
Programmers must be careful when mixing code compiled with small-data
with code using A5 as a general purpose register. On the Amiga,
you'd use the "__loadds" function attribute for callbacks and softints.
> However, I'm having a hard time finding anything like this, even basic
> (a5)-relative globals for the original MacOS.
Hmmm... perhaps there are rougue patches for MacOS that have
never been contributed to GCC. The AmigaOS patches have been
floating around for several years.
> Even the -l option to gas, which is documented as changing the
> default absolute addressing mode to .w (rather than .l), doesn't
> seem to work.
That's not meant to be used to trick the compiler. It's just
a compatibility option for assembly source written for other
assemblers.
> Do you know if something like this exists, or if it could be easily
> hacked in? I'm a bit lost in the code, but it *seems* like it
> shouldn't be too difficult. I just want
>
> attribute((abslong)) -> var.l
> attribute((absshort)) -> var.w
> attribute((based(%a5, base_value))) -> (var-base_value)(%a5)
> attribute((pcrel)) -> var(%pc)
>
> For a simple implementation, the last one can just generate invalid
> assembly code if you try to write to it.
It _can_ be done, I'm sure, but there's currently no support in GCC.
Most of the changes to support this would go into the machine
description file (m68k.md).
If you want to give it a try, I suggest working with a snapshot
of GCC 3.4. After several years of stagnation, the m68k back-end
has undergone a massive cleanup and is _much_ easier to work with
now.
> For *really* small applications, I can define a "struct globals {}"
> and just refer to that everywherem but that really distorts the code
> and makes porting a pain.
Yes, I know what you mean. I wrote embedded C code for small devices
and I had to resort to those tricks myself. Compiler support is
definitely needed to do such things.
> Can you point me to any hints?
I hope I've not confused you more :-)
--
// Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/ http://www.develer.com/
Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html
More information about the Gcc
mailing list