DSPRelated.com
Forums

RE: SHARC 21065 (C compiler call code)

Started by Burgwedel Friedrich March 1, 2005

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 >



--On Tuesday, March 01, 2005 10:55 AM +0100 Burgwedel Friedrich
<> wrote:

> 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;

Nitpick: CJUMP isn't a "macro" because it's not expanded by the assembler.
It's a true instruction, implemented in the electronics of the chip at full
speed, so it takes only one cycle (plus the normal pipeline delays) to
execute. Thus the above sequence takes 3 cycles, not 5, to run.

If you tried to implement the same sequence piece-meal, you couldn't do it
in one instruction because there aren't enough data paths in the chip to
accommodate the transfers. But because this is a common sequence in C, ADI
implemented the sequence with custom logic to make it fast. I suppose even
more of the calling sequence could have been implemented with custom
hardware but one reaches diminishing returns when one stops finding uses
for the resulting delay slots and the cost of adding extra custom data
paths becomes prohibitive. It would be interesting to see what other RISC
architectures do for this kind of thing.

[Sorry about the double post earlier. My mail client crashed when I hit the
Send button and I didn't realize the message went out successfully.]




> Nitpick: CJUMP isn't a "macro" because it's not expanded by
> the assembler.

Sure; I missed to say "microcode macros", I just meant macros on an
abstract level -- the word "somehow" should have expressed this.

> -----Original Message-----
> From: Kenneth Porter [mailto:]
> Sent: Tuesday, March 01, 2005 2:44 PM
> To:
> Subject: RE: [adsp] SHARC 21065 (C compiler call code) >
> --On Tuesday, March 01, 2005 10:55 AM +0100 Burgwedel Friedrich
> <> wrote:
>
> > 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;
>
> Nitpick: CJUMP isn't a "macro" because it's not expanded by
> the assembler.
> It's a true instruction, implemented in the electronics of
> the chip at full
> speed, so it takes only one cycle (plus the normal pipeline
> delays) to
> execute. Thus the above sequence takes 3 cycles, not 5, to run.
>
> If you tried to implement the same sequence piece-meal, you
> couldn't do it
> in one instruction because there aren't enough data paths in
> the chip to
> accommodate the transfers. But because this is a common
> sequence in C, ADI
> implemented the sequence with custom logic to make it fast. I
> suppose even
> more of the calling sequence could have been implemented with custom
> hardware but one reaches diminishing returns when one stops
> finding uses
> for the resulting delay slots and the cost of adding extra
> custom data
> paths becomes prohibitive. It would be interesting to see
> what other RISC
> architectures do for this kind of thing.
>
> [Sorry about the double post earlier. My mail client crashed
> when I hit the
> Send button and I didn't realize the message went out successfully.]



--On Tuesday, March 01, 2005 3:09 PM +0100 Burgwedel Friedrich
<> wrote:

> Sure; I missed to say "microcode macros", I just meant macros on an
> abstract level -- the word "somehow" should have expressed this.

Does it in fact use microcode? I thought this architecture, being
RISC-like, was pure logic, and that CJUMP just used special data paths.




Hello

I need to write and read data from file. I use the following code, but it
doesn't work for writing.I don't know how to read in a file fread? Help would
be greatly appreciated.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char dfilename[32] = "default.txt";
int toto=9;
FILE *fpr;

// Test for writing
fpr= fopen(dfilename,"w");

fprintf(fpr, "Test \n");
fprintf(fpr," ;%d; \n",toto);

fclose(fpr);

// Test for writing
fpr= fopen(dfilename,"r");

freadf();

fclose(fpr);





> Does it in fact use microcode? I thought this architecture, being
> RISC-like, was pure logic, and that CJUMP just used special
> data paths.

I think you are right -- using microcode would require at least one
additional cycle, otherwise it could be done simply by logic -- and
would therefore decrease the maximum core clock rate.
As I said -- macro on an abstract level; don't mind how it is
implemented.

So long,
Friedrich

> -----Original Message-----
> From: Kenneth Porter [mailto:]
> Sent: Tuesday, March 01, 2005 5:53 PM
> To:
> Subject: RE: [adsp] SHARC 21065 (C compiler call code)



--On Tuesday, March 01, 2005 6:36 PM +0100
wrote:

> I need to write and read data from file.

This implies that you have hardware to implement a filesystem. Are you
talking about within the debugger, or some other environment? Did you look
at the explanation in the library manual for how the debugger supports file
I/O? (It's non-trivial, but a prerequisite to discussion.)


--On Tuesday, March 01, 2005 6:40 PM +0100 Burgwedel Friedrich
<> wrote:

> As I said -- macro on an abstract level; don't mind how it is
> implemented.

I only nitpick here because I've been led astray myself by false
assumptions, and "macro" suggests text replacement, which is clearly not
the case here. I just don't want the bystanders less familiar with the nuts
and bolts to go down the wrong ally. ;)



I'm working in simulation session only, no Ez-Kit at this time. Is it a problem? Selon Kenneth Porter <>:

>
> --On Tuesday, March 01, 2005 6:36 PM +0100
> wrote:
>
> > I need to write and read data from file.
>
> This implies that you have hardware to implement a filesystem. Are you
> talking about within the debugger, or some other environment? Did you look
> at the explanation in the library manual for how the debugger supports file
> I/O? (It's non-trivial, but a prerequisite to discussion.) >
>


--On Tuesday, March 01, 2005 7:49 PM +0100
wrote:

> I'm working in simulation session only, no Ez-Kit at this time. Is it a
> problem?

That's essentially the same as the debugger, so you should be fine. I think
you have to enable stdio support in the debugger somewhere. (I've left the
company where I used this so this is from memory.)