DSPRelated.com
Forums

FW: SHARC 21065 (C compiler call code)

Started by Burgwedel Friedrich March 1, 2005
-----Original Message-----
From: Burgwedel Friedrich
Sent: Tuesday, March 01, 2005 10:56 AM
To: 'Mike Rosing'; wadsworth_bob
Cc:
Subject: RE: [adsp] SHARC 21065 (C compiler call code) Hi Mike, hi Bob,

> So it looks like you do a look up into a table, then jump to
> some offset from that address, and fix the registers i6 and
> i7 along the way. It's from a C compiler, so you may want to
> find the original source code to figure out what is really going on.

not completely... ;)

The cjump opcode is, as mike said, intended for the compiler's use. It
is normally hidden in the ccall() macro, which normally expands to

cjump function (DB);
dm(i7,m7)=r2;
dm(i7,m7)=PC;

Since cjump itself is a macro somehow, the whole sequence expands to

r2 = i6;
i6 = i7;
jump function (db)
dm(i7,m7) = r2;
dm(i7,m7) = PC;

This is the compiler's function call code. Knowing that the C compiler
uses i7 as stack pointer and i6 as frame base pointer (remember the
stack to grow downwards!), we see that the code simply sets a new stack
frame base at the position of the current stack pointer (that is, i6 now
addresses free memory on the stack), then pushes the old frame base
pointer and the current program counter to the stack; this way they will
occupy the first two locations of a new stack frame. If the called
function needs some additional memory on the stack (for local variables
and temporary register backup, for example), it uses

modify (i7,-x);

with x being the number of words that will be usable in the stack frame.
The real stack frame is always 2 words larger, due to the two push
operations inside the call code:

dm(0,i6) addresses the old frame base pointer (pushed first),
and
dm(-1,i6) addresses the address from where the function was
called (not exactly the return address, see down).

This is why all later local variables or register backups will have to
address dm(-2,i6) to dm(-x-1,i6). Even the function parameters that
where pushed to the stack (if any) are easily addressed by offsets to
the frame base pointer:

dm(1,i6) addresses the last pushed parameter -- normally the
first parameter in the parameter list.
dm(2,i6) addresses the 2nd parameter, ...

The C call code is complemented by the c runtime function exit macro,
which is

i12 = dm(m7,i6);
jump (m14,i12) (db);
rframe;
nop;

which in turn expands to

i12 = dm(-1,i6);
jump (1,i12) (db);
i7 = i6;
i6 = dm(0,i6)

This expanded version misses the nop opcode which is normally "recycled"
by the optimizer, but I show the expanded (less optimal) code for better
understanding. As you can see, this code reverses the changes made by
the call code: it retrieves the "to be" return address and jumps back to
caller by incrementing the address by one since it was pushed by the
last opcode of the call code; so execution resumes just after the call
code. The next two operations just restore the stack pointer and the
frame base pointer -- we even to not need to manually reverse the modify
operation that generated the stack frame.

Quite simple, right?!

For those who code assembly language I should mention that fetching the
return address causes a DAG2 stall; you should try to insert another
opcode -- maybe restoring a DAG1 register that would otherwise stall,
too -- to hide this stall.

So long,
Friedrich

> -----Original Message-----
> From: Mike Rosing [mailto:]
> Sent: Tuesday, March 01, 2005 5:03 AM
> To: wadsworth_bob
> Cc:
> Subject: Re: [adsp] SHARC 21065 >
> On Mon, 28 Feb 2005, wadsworth_bob wrote:
>
> > I am using the SHARC 21065 processor. At the end of some
> of the code
> > I have inherited, the following code exists:
> >
> > _exit:
> > i12=dm(m7,i6);
> > jump (m14,i12) (db);
> > rframe;
> > nop;
> > .ENDSEG;
> >
> > Can anyone tell me what this is for?
>
> The manual says the following:
>
> CJUMP |function | (PC, <reladdr24>) | (DB);
> RFRAME;
>
> Function:
> The CJUMP instruction is generated by the C compiler for
> function calls, and is not intended for use in assembly
> language programs. CJUMP combines a direct or PC-relative
> jump with register transfer operations that save the frame
> and stack pointers. The RFRAME instruction reversed the
> register transfers to restore the frame and stack pointers.
>
> ...
>
> instruction what it does
>
> CJUMP function(DB) JUMP function (DB), R2=I6, I6=I7;
>
> RFRAME; I7 = I6, I6 = DM(0,I6)
>
> So it looks like you do a look up into a table, then jump to
> some offset from that address, and fix the registers i6 and
> i7 along the way. It's from a C compiler, so you may want to
> find the original source code to figure out what is really going on.
>
> Patience, persistence, truth,
> Dr. mike >