[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | DECC |
Notice: | General DEC C discussions |
Moderator: | TLE::D_SMITH N TE |
|
Created: | Fri Nov 13 1992 |
Last Modified: | Fri Jun 06 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 2212 |
Total number of notes: | 11045 |
2180.0. "Using gp reg in assembly routine called from optimised C" by GALVIA::STONES (Tom Stones) Wed May 07 1997 08:05
I have an assembly routine where I use the gp register as a scratch register.
(The assembly routine doesn't create a stack frame, doesn't call any other
routines, and doesn't save any registers.)
I've tried setting the flag in the .prolog assembler directive to 0 and to 1,
and tried it with no flag (default=1).
I'm calling the assembly routine from C code compiled with the -O4 switch.
Depending on the code near the call, the C compiler sometimes generates code
that assumes the gp register has the same value on exit from my assembly routine
as it did on entry.
The calling standard seems to say that I can do this:
"Because a standard-conforming calling procedure must assume that the GP
register value is destroyed across a call but must itself return it with
the correct value, the code following the call must reestablish its value
before further accesses to the GOT ..."
What am I doing wrong??
Extract from the C call:
extern int gcopy(void *src, void *dest, long length, long flags);
...
getclock(TIMEOFDAY,&cstart);
for (i=1; i<=iterations; i++) {
gcopy(ibuf,obuf,imc_size - 8, 0);
}
cend = cstart;
getclock(TIMEOFDAY,&cend);
Shortened assembly routine:
#include <machine/regdef.h>
.align 4
.globl gcopy
.ent gcopy 2
gcopy:
.set noreorder
.frame sp, 0, ra, 0
.prologue 1 <------ Tried 0 as weel as 1.
bis zero, zero, gp
Done:
bis zero, zero, v0
ret zero, (ra), 1
.end gcopy
The compile command:
> cc -O4 -o tgc tgcopy.c ~/try/junk.s -I../src/imc -L../src -limc
Extract from the generated code:
> dis tgc | more
...
0x120001810: a77d8010 ldq t12, -32752(gp)
0x120001814: 239f004f lda at, 79(zero)
0x120001818: 279c0000 ldah at, 0(at)
0x12000181c: 6b7b0000 jmp t12, (t12), 0x120001820(zero)
0x120001820: a77d8010 ldq t12, -32752(gp)
0x12000232c: d3400728 bsr ra, gcopy <--------Call assmbly
0x120002330: a41e0048 ldq v0, 72(sp)
0x120002334: a77d81c8 ldq t12, -32312(gp) <--------Use gp!!
0x120002338: 47e07401 bis zero, 0x3, t0
0x12000233c: 221e0040 lda a0, 64(sp)
0x120002340: b0200000 stl t0, 0(v0)
0x120002344: 6b5b433e jsr ra, (t12), 0x120003040(zero)
0x120002348: 27ba2000 ldah gp, 8192(ra)
0x12000234c: 47ff041f bis zero, zero, zero
0x120002350: 23bd6688 lda gp, 26248(gp)
T.R | Title | User | Personal Name | Date | Lines |
---|
2180.1 | The calling standard could be clearer | QUARRY::neth | Craig Neth | Wed May 07 1997 11:05 | 18 |
| A standard conforming procedure must return with a valid GP value. See the
table on integer registers:
>Global pointer (GP) register. For a standard-conforming procedure, this register
>must contain the calling procedure's global offset table (GOT) segment pointer
>value at the time of a call and must contain the calling procedure's GOT
>segment pointer value or the called procedure's GOT segment pointer value
>upon return. This register must be treated as scratch by the calling procedure. (See Section 2.5
>2.5 and Section 3.2.2 for details.)
Also, you may want to read the section on linker optimizations to
understand the type of optimization that appears to be biting you - the
linker knows that the caller and the callee share the same GP value and
so it can delete the reload after the call.
The .prologue stuff is a red herring here - it is used to indicate whether or
not the routine makes accesses off of GP and thus needs it to be established.
.prologue 0 is what you want
|
2180.2 | Notes collision | GEMEVN::GLOSSOP | Kent Glossop | Wed May 07 1997 11:29 | 23 |
| The calling standard also says:
p 2-3 (at least in my copy):
$29 Global pointer (GP) register. For a standard-conforming procedure,
this register must contain the calling procedure's global offset table
(GOT) segment pointer value at the time of a call and must contain either
the calling procedure's GOT segment pointer value or the called procedure's
GOT segment pointer value upon return. This register must be treated
as a scratch register by the calling procedure. (See Section 2.4 and
Section 3.2.2 for details.)
which you are violating if you are using it as a scratch register, and
not restoring the original value or loading your own.
The calling standard text exists so the linker can perform link-time
optimization. What is presumably going on is the linker is recognizing
that the code can share a got, and is doing the modifications.
If you link -O0 it should probably work OK.
(The text should really be stronger than "standard-conforming procedure" -
any image linked at non-zero opt. level must obey this.)
|
2180.3 | Apparent Contradiction In Text Posted Here... | XDELTA::HOFFMAN | Steve, OpenVMS Engineering | Wed May 07 1997 11:41 | 2 |
|
Looks like it's time to clarify the calling standard text here...
|
2180.4 | | GEMEVN::GLOSSOP | Kent Glossop | Wed May 07 1997 12:15 | 17 |
| > -< Apparent Contradiction In Text Posted Here... >-
What contradiction?
- A *calling* procedure can't know what value will be in $gp on return,
so must reload it by default
- A *called* procedure must return to the caller, either with
the caller's $gp or its own
- The *linker* may use the combined knowledge of the two above facts
to process the relocations provided by the compiler to make a more
efficient image.
I believe the error is the inference that "because the *caller* must meet
certain conditions, then I have the flexibility to treat $gp as a scratch
register in this procedure". That isn't a valid conclusion.
|
2180.5 | | GALVIA::STONES | Tom Stones | Wed May 07 1997 12:27 | 5 |
| The wording in the "Assembly Language Programmer's Guide" should be clarified
too. For example, table 6-1 says:
$29 or $gp Contains the global pointer. Not preserved
across procedure calls.
|
2180.6 | That This Dicussion Is Occuring Points To Problem... | XDELTA::HOFFMAN | Steve, OpenVMS Engineering | Wed May 07 1997 12:36 | 11 |
| :I believe the error is the inference that "because the *caller* must meet
:certain conditions, then I have the flexibility to treat $gp as a scratch
:register in this procedure". That isn't a valid conclusion.
And that's why this needs to be reworded -- the text in .0 clearly
tends to imply "scratch". The text in .1 and .2 say "not scratch,
but see the text in .0".
.0 is one of the best folks to have looking at these documents that
one could hope for -- folks familiar with the mechanism tend to miss
any ambiguity, contradictions, incorrect implications, etc.
|