static char *sccsid
="@(#)code.c 1.1 (Berkeley) %G%";
int proflg
= 0; /* are we generating profiling code? */
int strftn
= 0; /* is the current function one which returns a value */
int fdefflag
; /* are we within a function definition ? */
/* output a branch to label n */
/* exception is an ordinary function branching to retlab: then, return */
if( n
== retlab
&& !strftn
){
else printf( " jbr L%d\n", n
);
short log2tab
[] = {0, 0, 1, 2, 2, 3, 3, 3, 3};
/* cause the alignment to become a multiple of n */
if( lastloc
!= PROG
&& n
> 1 ) printf( " .align %d\n", n
>= 0 && n
< LOG2SZ
? log2tab
[n
] : 0 );
/* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */
if( l
== lastloc
) return(l
);
cerror( "illegal location counter" );
/* output something to define the current position as label n */
/* return a number usable for a label */
0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0};
/* code for the end of a function */
if( strftn
){ /* copy output (in R2) to caller */
register struct symtab
*p
;
i
= getlab(); /* label for return area */
printf("L%d: .space %d\n", i
, tsize(t
, p
->dimoff
, p
->sizoff
)/SZCHAR
);
{ int sz
= tsize(t
, p
->dimoff
, p
->sizoff
) / SZCHAR
;
sz
+= sizeof (int) - (sz
% sizeof (int));
printf(" .lcomm L%d,%d\n", i
, sz
);
printf(" movab L%d,r1\n", i
);
l
= block( REG
, NIL
, NIL
, PTR
|t
, p
->dimoff
, p
->sizoff
);
l
->tn
.lval
= 0; /* no offset */
r
= block( REG
, NIL
, NIL
, PTR
|t
, p
->dimoff
, p
->sizoff
);
l
= buildtree( UNARY MUL
, l
, NIL
);
r
= buildtree( UNARY MUL
, r
, NIL
);
l
= buildtree( ASSIGN
, l
, r
);
printf( " movab L%d,r0\n", i
);
/* turn off strftn flag, so return sequence will be generated */
printf( " .set L%d,0x%x\n", ftnno
, ent_mask
[reg_use
] );
printf( " .set L%d,%d # Hex = 0x%x\n", ftnno
, 0x3c| ent_mask
[reg_use
], ent_mask
[reg_use
] );
/* KLS kludge, under VMS if you use regs 2-5, you must save them. */
bfcode( a
, n
) int a
[]; {
/* code for the beginning of a function; a is an array of
indices in stab for the arguments; n is the number */
register struct symtab
*p
;
strftn
= (temp
==STRTY
) || (temp
==UNIONTY
);
printf( " .word L%d\n", ftnno
);
pstabdot(N_SLINE
, lineno
);
pstab(NULLNAME
, N_SLINE
);
printf("0,%d,LL%d\n", lineno
, labelno
);
printf("LL%d:\n", labelno
++);
printf( " jbr L%d\n", ftlab1
);
printf( "L%d:\n", ftlab2
);
if( proflg
) { /* profile code */
printf(" movab L%d,r0\n", i
);
printf("L%d: .long 0\n", i
);
if( p
->sclass
== REGISTER
){
temp
= p
->offset
; /* save register number */
p
->sclass
= PARAM
; /* forget that it is a register */
/*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p
->stype
), p
->offset
/SZCHAR
, temp
);
p
->offset
= temp
; /* remember register number */
p
->sclass
= REGISTER
; /* remember that it is a register */
else if( p
->stype
== STRTY
|| p
->stype
== UNIONTY
) {
if( oalloc( p
, &off
) ) cerror( "bad argument" );
if( oalloc( p
, &off
) ) cerror( "bad argument" );
bccode(){ /* called just before the first executable statment */
/* by now, the automatics and register variables are allocated */
SETOFF( autooff
, SZINT
);
/* set aside store area offset */
p2bbeg( autooff
, regvar
);
reg_use
= (reg_use
> regvar
? regvar
: reg_use
);
/* called just before final exit */
/* flag is 1 if errors, 0 if none */
/* called before removing automatics from stab */
aocode(p
) struct symtab
*p
; {
/* called when automatic p removed from stab */
/* called after removing all automatics from stab */
defnam( p
) register struct symtab
*p
; {
/* define the current location as the name p->sname */
if( p
->sclass
== EXTDEF
){
printf( " .globl %s\n", exname( p
->sname
) );
if( p
->sclass
== STATIC
&& p
->slevel
>1 ) deflab( p
->offset
);
else printf( "%s:\n", exname( p
->sname
) );
static int lastoctal
= 0;
/* put byte i+1 in a string */
if ( i
!= 0 ) printf( "\"\n" );
if ( i
== 0 ) printf("\t.ascii\t\"");
if ( t
== '\\' || t
== '"'){
* We escape the colon in strings so that
* c2 will, in its infinite wisdom, interpret
* the characters preceding the colon as a label.
* If we didn't escape the colon, c2 would
* throw away any trailing blanks or tabs after
* the colon, but reconstruct a assembly
* language semantically correct program.
* C2 hasn't been taught about strings.
else if ( t
== ':' || t
< 040 || t
>= 0177 ){
else if ( lastoctal
&& '0' <= t
&& t
<= '9' ){
printf("\"\n\t.ascii\t\"%c", t
);
if ( i
== 077 ) printf("\"\n");
if( t
< 0 ){ /* end of the string */
if( i
!= 0 ) printf( "\n" );
else { /* stash byte t into string */
if( i
== 0 ) printf( " .byte " );
if( i
== 07 ) printf( "\n" );
/* n integer words of zeros */
printf( " .space %d\n", (SZINT
/SZCHAR
)*n
);
fldal( t
) unsigned t
; { /* return the alignment of field of type t */
uerror( "illegal field type" );
fldty( p
) struct symtab
*p
; { /* fix up type of field p */
where(c
){ /* print location of error */
/* c is either 'u', 'c', or 'w' */
fprintf( stderr
, "%s, line %d: ", ftitle
, lineno
);
/* tbl - toreg() returns a pointer to a char string
which is the correct "register move" for the passed type
struct type_move
{TWORD fromtype
; char tostrng
[8];} toreg_strs
[] =
for ( p
=toreg_strs
; p
->fromtype
> 0; p
++)
if (p
->fromtype
== type
) return(p
->tostrng
);
/* type not found, must be a pointer type */
main( argc
, argv
) char *argv
[]; {
return(mainp1( argc
, argv
));
struct sw heapsw
[SWITSZ
]; /* heap for switches */
genswitch(p
,n
) register struct sw
*p
;{
/* p points to an array of structures, each consisting
of a constant value and a label.
The first is >=0 if there is a default label;
its value is the label number
The entries p[1] to p[n] are the nontrivial cases
range
= p
[n
].sval
-p
[1].sval
;
if( range
>0 && range
<= 3*n
&& n
>=4 ){ /* implement a direct switch */
dlab
= p
->slab
>= 0 ? p
->slab
: getlab();
printf(" casel r0,$%ld,$%ld\n", p
[1].sval
, range
);
for( i
=1,j
=p
[1].sval
; i
<=n
; j
++) {
printf(" .word L%d-L%d\n", (j
== p
[i
].sval
? ((j
=p
[i
++].sval
), p
[i
-1].slab
) : dlab
),
if( p
->slab
>= 0 ) branch( dlab
);
else printf("L%d:\n", dlab
);
if( n
>8 ) { /* heap switch */
heapsw
[0].slab
= dlab
= p
->slab
>= 0 ? p
->slab
: getlab();
makeheap(p
, n
, 1); /* build heap */
walkheap(1, n
); /* produce code */
if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) );
printf( CONFMT
, p
[i
].sval
);
printf( "\n jeql L%d\n", p
[i
].slab
);
if( p
->slab
>=0 ) branch( p
->slab
);
if( q
>1 ) makeheap(p
, q
-1, 2*n
);
if( q
<m
) makeheap(p
+q
, m
-q
, 2*n
+1);
l
= ((k
= i
/2 - 1) + 1)/2;
return( l
+ (m
-k
< l
? m
-k
: l
));
if( start
> limit
) return;
printf(" cmpl r0,$%d\n", heapsw
[start
].sval
);
printf(" jeql L%d\n", heapsw
[start
].slab
);
if( (2*start
) > limit
) {
printf(" jbr L%d\n", heapsw
[0].slab
);
if( (2*start
+1) <= limit
) {
printf(" jgtr L%d\n", label
);
printf(" jgtr L%d\n", heapsw
[0].slab
);
walkheap( 2*start
, limit
);
if( (2*start
+1) <= limit
) {
walkheap( 2*start
+1, limit
);