This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: -mpcrel and -fPIC and -m68000


Alexander Aganichev <AAganichev@hypercom.com> wrote:

> I've made small patch that provides support for PC relative addressing on
> m68000 with -fPIC option set. If someone intrested in testing here it is:
> (See attached file: m68k.pcrel-68000.diff)
>
> How it works:
> ~~~~~~~~~~
>
> On M68020 we already have the following code for calling:
>
>      lea (label:l,%pc),%aX
>      jsr (%aX)
>
> It could be simulated on M68000 with:
>
>      move #label-tmp_label,%aX
> tmp_label:
>      lea tmp_label(%aX,%pc),%aX
>      jsr (%aX)

A few comments. Note that for 68020 and higher, the lea instruction generated
does *not* explicitly specify long displacement. Instead, it lets the relaxer
in the assembler pick the most efficient form. Also for calls, it does not
generate a lea followed by a jsr. Instead, it generates a jbsr, which causes
the relaxer in the assembler to pick the most efficient form of bsr or jsr.

This is very important. The philosophy used by GCC and other UNIX-style
compilers is that the compiler should generate assembly code in text form
without thinking about opcodes, multiple possible forms of an instruction, and
how far apart things are. Instead, the assembler, and ideally the linker too,
should translate this generic text form into opcodes that are the most
efficient. Automatic choice of short vs. long instruction forms is called
relaxation, and has been part of all UNIX assemblers since the original VAX
UNIX 32V one.

I have already been working on supporting PC-relative code on 68000 without the
-32 KB to +32 KB locality of reference limit. I have devised the following
instruction sequences that mimic 32-bit PC-relative JSR, LEA, and PEA on 68000:

32-bit PC-relative JSR:

	movel	#target-L,%d0
	jsr	L(%pc,%d0.l)

32-bit PC-relative LEA:

	lea	L(%pc),%aN
	addal	#target-L,%aN

32-bit PC-relative PEA:

	pea	L(%pc)
	addil	#target-L,(%sp)

L is a label placed at the location where the 32-bit displacement resides. This
makes these instruction sequences look the same to the reloc engine as
equivalent 68020 instructions. Each of these sequences is 5 words long, and I
believe this is the shortest they can be made. Also note that the call sequence
takes advantage of the m68k C calling convention, where it's OK to trash D0 on
entry to the function.

However, I'm not making gcc generate these sequences. Rather, I'm making the
gas relaxer generate them automatically from simple lea and pea like it already
relaxes between 16-bit and 32-bit PC-relative forms on 68020. (With the call
sequence it's a little harder because it is usable only for calls that adhere
to the m68k C calling convention, not for arbitrary assembly JSRs. I'm thinking
about adding a new pseudo-instruction to gas, called callf for "call function",
that is like jbsr but conveys that it's a C function call and enables this
aequence. Then gcc can emit callf instead of jbsr to convey that it's following
the m68k C calling convention.)

I am also implementing the new relaxer, i.e., the mechanism that chooses the
shortest form whenever possible, for nearby references, and uses longer forms
only where necessary because the target is too far, in the linker. This way
relaxation works across module boundaries. However, this makes it object
format-dependent. I'm implementing it for ELF, because it's the format
preferred by the GNU standards, and because in GNU Binutils implementing linker
relaxation is much easier for ELF than for COFF or a.out. (That's because the
ELF BFD backends are much better organised. There is a lot of chaos in the COFF
backends. I haven't looked at a.out, but I think it would be even worse. And of
course a.out is far too limited for what people do with the GNU toolchain these
days.)

I'm not working on this currently, because my previous m68k GNU tools work was
in connection with my work on the PalmOS handheld embedded system, which was in
connection with me working for a company doing PalmOS software development, and
I no longer work there. In fact, I can't do any GNU tools development at all
right now, as I don't have a development machine. My own machines don't have
the disk space or CPU cycles for that, I was doing all my previous GNU tools
development at that company. But I plan to resume my GNU tools development and
implement those m68k enhancements (they are useful for more than just PalmOS)
when I find a new job. I'm even hoping that it will be a little more GNU-
related than my previous. :-)

> Unfortunately I was unable to understand how to allocate temporary register
> (I've tried to use `clobber' but failed) to make same trick with `pea', so
> gcc generates `lea' followed by `move' in this version. I believe someone
> who undertand gcc internals better make a better support for this feature.

You don't need a temporary register to implement a PEA with 32-bit
displacement. See above how I've done it. Note that my PEA sequence clobbers
the flags. I hope it's OK because AFAIK gcc doesn't assume that they are
preserved in this case. (If it does, we'll just need to amend the machine
description for that.) This does not apply to my LEA and JSR sequences.

--
Michael Sokolov		Harhan Engineering Laboratory
Public Service Agent	International Free Computing Task Force
			International Engineering and Science Task Force
			615 N GOOD LATIMER EXPY STE #4
			DALLAS TX 75204-5852 USA

Phone: +1-214-824-7693 (Harhan Eng Lab office)
E-mail: msokolov@ivan.Harhan.ORG (ARPA TCP/SMTP) (UUCP coming soon)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]