[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
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.RTitleUserPersonal
Name
DateLines
2180.1The calling standard could be clearerQUARRY::nethCraig NethWed May 07 1997 11:0518
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.2Notes collisionGEMEVN::GLOSSOPKent GlossopWed May 07 1997 11:2923
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.3Apparent Contradiction In Text Posted Here...XDELTA::HOFFMANSteve, OpenVMS EngineeringWed May 07 1997 11:412
   Looks like it's time to clarify the calling standard text here...
2180.4GEMEVN::GLOSSOPKent GlossopWed May 07 1997 12:1517
>  -< 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.5GALVIA::STONESTom StonesWed May 07 1997 12:275
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.6That This Dicussion Is Occuring Points To Problem...XDELTA::HOFFMANSteve, OpenVMS EngineeringWed May 07 1997 12:3611
: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.