static char *sccsid
="@(#)local2.c 1.1 (Berkeley) 12/15/82";
/* a lot of the machine dependent parts of the second pass */
# define BITMASK(n) ((1L<<n)-1)
fprintf( stderr
, "%s, line %d: ", filename
, lineno
);
lineid( l
, fn
) char *fn
; {
/* identify line l and file fn */
printf( "# line %d, file %s\n", l
, fn
);
OFFSZ spoff
; /* offset from stack pointer */
if( spoff
>= AUTOINIT
) spoff
-= AUTOINIT
;
printf( " .set .F%d,%ld\n", ftnno
, spoff
);
/* SHOULD BE L%d ... ftnno but must change pc/f77 */
printf( " .set LF%d,%ld\n", ftnno
, spoff
);
extern int ftlab1
, ftlab2
;
if( spoff
>= AUTOINIT
) spoff
-= AUTOINIT
;
printf( "L%d:\n", ftlab1
);
printf( " subl2 $%ld,sp\n", spoff
);
printf( " movab -%ld(sp),sp\n", spoff
);
printf( " jbr L%d\n", ftlab2
);
struct hoptab
{ int opmask
; char * opstring
; } ioptab
[] = {
/* output the appropriate string from the above table */
register struct hoptab
*q
;
for( q
= ioptab
; q
->opmask
>=0; ++q
){
printf( "%s", q
->opstring
);
if( f == 'F' ) printf( "e" );
else if( f == 'D' ) printf( "d" );
printf("%c", tolower(f
));
cerror( "no hoptab for %s", opst
[o
] );
rnames
[] = { /* keyed to register number tokens */
"r6", "r7", "r8", "r9", "r10", "r11",
SAREG
|STAREG
, SAREG
|STAREG
,
SAREG
|STAREG
, SAREG
|STAREG
, SAREG
|STAREG
, SAREG
|STAREG
,
SAREG
, SAREG
, SAREG
, SAREG
, SAREG
, SAREG
,
SAREG
, SAREG
, SAREG
, SAREG
,
mixtypes(p
, q
) NODE
*p
, *q
;
return( (tp
==FLOAT
|| tp
==DOUBLE
) !=
(tq
==FLOAT
|| tq
==DOUBLE
) );
if ( !ISPTR( n
->in
.type
) ) cerror("zzzcode- bad type");
zzzcode( p
, c
) register NODE
*p
; {
case 'N': /* logical ops, turned into 0-1 */
/* use register given by register 1 */
cbgen( 0, m
=getlab(), 'I' );
printf( " clrl %s\n", rnames
[getlr( p
, '1' )->tn
.rval
] );
cbgen( p
->in
.op
, p
->bn
.label
, c
);
if (xdebug
) eprint(p
, 0, &val
, &val
);
if (optype(p
->in
.op
) == LTYPE
|| p
->in
.op
== UNARY MUL
)
l
->in
.type
= (r
->in
.type
==FLOAT
|| r
->in
.type
==DOUBLE
? DOUBLE
: INT
);
if(r
->in
.name
[0] == '\0')
if (r
->tn
.lval
< 0 && r
->tn
.lval
>= -63)
r
->tn
.lval
= -r
->tn
.lval
;
r
->in
.type
= (r
->tn
.lval
< 0 ?
(r
->tn
.lval
>= -128 ? CHAR
: (r
->tn
.lval
>= -32768 ? SHORT
r
->in
.type
= (r
->tn
.lval
>= 0 ?
: ( r
->tn
.lval
<= 127 ? CHAR
: (r
->tn
.lval
<= 255 ? UCHAR
: (r
->tn
.lval
<= 32767 ? SHORT
: (r
->tn
.lval
<= 65535 ? USHORT
: INT
))))) : r
->in
.type
);
if (l
->in
.op
== REG
&& l
->in
.type
!= FLOAT
&& l
->in
.type
!= DOUBLE
)
else if (tlen(l
) > tlen(r
) && ISUNSIGNED(r
->in
.type
))
case 'B': /* get oreg value in temp register for left shift */
if (xdebug
) eprint(p
, 0, &val
, &val
);
if( tlen(r
) == sizeof(int) && r
->in
.type
!= FLOAT
)
case 'C': /* num words pushed on arg stack */
if (xdebug
) printf("->%d<-",gc_numbytes
);
printf("$%d", gc_numbytes
/(SZLONG
/SZCHAR
) );
case 'D': /* INCR and DECR */
zzzcode(p
->in
.left
, 'A');
case 'E': /* INCR and DECR, FOREFF */
if (p
->in
.right
->tn
.lval
== 1)
printf("%s", (p
->in
.op
== INCR
? "inc" : "dec") );
printf("%s", (p
->in
.op
== INCR
? "add" : "sub") );
case 'F': /* register type of right operand */
if (xdebug
) printf("->%d<-", ty
);
if ( ty
==DOUBLE
) printf("d");
else if ( ty
==FLOAT
) printf("f");
case 'L': /* type of left operand */
case 'R': /* type of right operand */
if (xdebug
) printf("->%d<-", n
->in
.type
);
case 'Z': /* complement mask for bit instr */
printf("$%ld", ~p
->in
.right
->tn
.lval
);
case 'U': /* 32 - n, for unsigned right shifts */
printf("$%d", 32 - p
->in
.right
->tn
.lval
);
case 'T': /* rounded structure length for arguments */
case 'S': /* structure assignment */
else if( p
->in
.op
== STARG
){ /* store an arg into a temporary */
else cerror( "STASG bad" );
if( r
->in
.op
== ICON
) r
->in
.op
= NAME
;
else if( r
->in
.op
== REG
) r
->in
.op
= OREG
;
else if( r
->in
.op
!= OREG
) cerror( "STASG-r" );
if( size
<= 0 || size
> 65535 )
cerror("structure size <0=0 or >65535");
printf(" movc3 $%d,", size
);
if( r
->in
.op
== NAME
) r
->in
.op
= ICON
;
else if( r
->in
.op
== OREG
) r
->in
.op
= REG
;
cerror( "illegal zzzcode" );
(t
==FLOAT
? "movf" : (t
==DOUBLE
? "movd" : "movl")),
rnames
[rs
], rnames
[rt
] );
INTAREG
|INTBREG
, INTAREG
|INTBREG
,
INAREG
|INBREG
, INAREG
|INBREG
|SOREG
|STARREG
|STARNM
|SNAME
|SCON
,
INTEMP
, INTAREG
|INAREG
|INTBREG
|INBREG
|SOREG
|STARREG
|STARNM
,
setregs(){ /* set up temporary registers */
fregs
= 6; /* tbl- 6 free regs on VAX (0-5) */
szty(t
){ /* size, in registers, needed to hold thing of type t */
return( (t
==DOUBLE
||t
==FLOAT
) ? 2 : 1 );
base( p
) register NODE
*p
; {
register int o
= p
->in
.op
;
if( (o
==ICON
&& p
->in
.name
[0] != '\0')) return( 100 ); /* ie no base reg */
if( o
==REG
) return( p
->tn
.rval
);
if( (o
==PLUS
|| o
==MINUS
) && p
->in
.left
->in
.op
== REG
&& p
->in
.right
->in
.op
==ICON
)
return( p
->in
.left
->tn
.rval
);
if( o
==OREG
&& !R2TEST(p
->tn
.rval
) && (p
->in
.type
==INT
|| p
->in
.type
==UNSIGNED
|| ISPTR(p
->in
.type
)) )
return( p
->tn
.rval
+ 0200*1 );
if( o
==INCR
&& p
->in
.left
->in
.op
==REG
) return( p
->in
.left
->tn
.rval
+ 0200*2 );
if( o
==ASG MINUS
&& p
->in
.left
->in
.op
==REG
) return( p
->in
.left
->tn
.rval
+ 0200*4 );
if( o
==UNARY MUL
&& p
->in
.left
->in
.op
==INCR
&& p
->in
.left
->in
.left
->in
.op
==REG
&& (p
->in
.type
==INT
|| p
->in
.type
==UNSIGNED
|| ISPTR(p
->in
.type
)) )
return( p
->in
.left
->in
.left
->tn
.rval
+ 0200*(1+2) );
offset( p
, tyl
) register NODE
*p
; int tyl
; {
if( tyl
==1 && p
->in
.op
==REG
&& (p
->in
.type
==INT
|| p
->in
.type
==UNSIGNED
) ) return( p
->tn
.rval
);
if( (p
->in
.op
==LS
&& p
->in
.left
->in
.op
==REG
&& (p
->in
.left
->in
.type
==INT
|| p
->in
.left
->in
.type
==UNSIGNED
) &&
(p
->in
.right
->in
.op
==ICON
&& p
->in
.right
->in
.name
[0]=='\0')
&& (1<<p
->in
.right
->tn
.lval
)==tyl
))
return( p
->in
.left
->tn
.rval
);
makeor2( p
, q
, b
, o
) register NODE
*p
, *q
; register int b
, o
; {
f
= p
->in
.left
; /* have to free this subtree later */
q
->in
.right
->tn
.lval
= -q
->in
.right
->tn
.lval
;
cerror("illegal makeor2");
p
->in
.name
[i
] = t
->in
.name
[i
];
p
->tn
.rval
= R2PACK( (b
& 0177), o
, (b
>>7) );
register int o
= p
->in
.op
;
if( o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
|| (o
==UNARY MUL
&& shumul(p
->in
.left
)) ) return(1);
shltype( o
, p
) register NODE
*p
; {
return( o
== REG
|| o
== NAME
|| o
== ICON
|| o
== OREG
|| ( o
==UNARY MUL
&& shumul(p
->in
.left
)) );
flshape( p
) register NODE
*p
; {
return( p
->in
.op
== REG
|| p
->in
.op
== NAME
|| p
->in
.op
== ICON
||
(p
->in
.op
== OREG
&& (!R2TEST(p
->tn
.rval
) || tlen(p
) == 1)) );
shtemp( p
) register NODE
*p
; {
if( p
->in
.op
== STARG
) p
= p
->in
.left
;
return( p
->in
.op
==NAME
|| p
->in
.op
==ICON
|| p
->in
.op
== OREG
|| (p
->in
.op
==UNARY MUL
&& shumul(p
->in
.left
)) );
shumul( p
) register NODE
*p
; {
printf("\nshumul:op=%d,lop=%d,rop=%d", p
->in
.op
, p
->in
.left
->in
.op
, p
->in
.right
->in
.op
);
printf(" prname=%s,plty=%d, prlval=%D\n", p
->in
.right
->in
.name
, p
->in
.left
->in
.type
, p
->in
.right
->tn
.lval
);
if( o
== NAME
|| (o
== OREG
&& !R2TEST(p
->tn
.rval
)) || o
== ICON
) return( STARNM
);
if( ( o
== INCR
|| o
== ASG MINUS
) &&
( p
->in
.left
->in
.op
== REG
&& p
->in
.right
->in
.op
== ICON
) &&
p
->in
.right
->in
.name
[0] == '\0' )
switch (p
->in
.left
->in
.type
)
if ( ISPTR(p
->in
.left
->in
.type
) ) {
return( p
->in
.right
->tn
.lval
== o
? STARREG
: 0);
adrcon( val
) CONSZ val
; {
conput( p
) register NODE
*p
; {
printf( "%s", rnames
[p
->tn
.rval
] );
cerror( "illegal conput" );
insput( p
) register NODE
*p
; {
upput( p
) register NODE
*p
; {
adrput( p
) register NODE
*p
; {
/* output an address, with offsets, from p */
/* addressable value of the constant */
printf( "%s", rnames
[p
->tn
.rval
] );
if( R2TEST(r
) ){ /* double indexing */
if( flags
& 1 ) printf("*");
if( flags
& 4 ) printf("-");
if( p
->tn
.lval
!= 0 || p
->in
.name
[0] != '\0' ) acon(p
);
if( R2UPK1(r
) != 100) printf( "(%s)", rnames
[R2UPK1(r
)] );
if( flags
& 2 ) printf("+");
printf( "[%s]", rnames
[R2UPK2(r
)] );
if( r
== AP
){ /* in the argument region */
if( p
->tn
.lval
<= 0 || p
->in
.name
[0] != '\0' ) werror( "bad arg temp" );
printf( CONFMT
, p
->tn
.lval
);
if( p
->tn
.lval
!= 0 || p
->in
.name
[0] != '\0') acon( p
);
printf( "(%s)", rnames
[p
->tn
.rval
] );
/* STARNM or STARREG found */
if( tshape(p
, STARNM
) ) {
else { /* STARREG - really auto inc or dec */
p->in.left->in.op = OREG;
printf("%s(%s)%s", (p
->in
.left
->in
.op
==INCR
? "" : "-"),
rnames
[p
->in
.left
->in
.left
->tn
.rval
],
(p
->in
.left
->in
.op
==INCR
? "+" : "") );
p
->tn
.rval
= p
->in
.left
->in
.left
->tn
.rval
;
p
->tn
.lval
= (p
->in
.left
->in
.op
== INCR
? -p
->in
.left
->in
.right
->tn
.lval
: 0);
cerror( "illegal address" );
acon( p
) register NODE
*p
; { /* print out a constant */
if( p
->in
.name
[0] == '\0' ){
printf( CONFMT
, p
->tn
.lval
);
else if( p
->tn
.lval
== 0 ) {
printf( "%.8s", p
->in
.name
);
printf( "%s", p
->in
.name
);
printf( "%.8s+", p
->in
.name
);
printf( "%s+", p
->in
.name
);
printf( CONFMT
, p
->tn
.lval
);
aacon( p ) register NODE *p; { /* print out a constant */
if( p->in.name[0] == '\0' ){
printf( CONFMT, p->tn.lval);
else if( p->tn.lval == 0 ) {
printf( "$%.8s", p->in.name );
printf( "$%s", p->in.name );
printf( CONFMT, p->tn.lval );
printf( "%.8s)", p->in.name );
printf( "%s)", p->in.name );
genscall( p
, cookie
) register NODE
*p
; {
/* structure valued call */
return( gencall( p
, cookie
) );
gencall( p
, cookie
) register NODE
*p
; {
/* generate the call given by p */
register NODE
*p1
, *ptemp
;
if( p
->in
.right
) temp
= argsize( p
->in
.right
);
if( p
->in
.op
== STCALL
|| p
->in
.op
== UNARY STCALL
){
/* set aside room for structure return */
if( p
->stn
.stsize
> temp
) temp1
= p
->stn
.stsize
;
if( temp
> maxargs
) maxargs
= temp
;
if( p
->in
.right
){ /* make temp node, put offset in, and generate args */
ptemp
->in
.name
[0] = '\0';
genargs( p
->in
.right
, ptemp
);
if( p1
->in
.op
!= OREG
|| R2TEST(p1
->tn
.rval
) ){
if( p1->in.op == REG && p->tn.rval == R5 ){
cerror( "call register overwrite" );
setup gc_numbytes so reference to ZC works */
gc_numbytes
= temp
&(0x3ff);
m
= match( p
, INTAREG
|INTBREG
);
/* compensate for deficiency in 'ret' instruction ... wah,kre */
/* (plus in assignment to gc_numbytes above, for neatness only) */
printf(" addl2 $%d,sp\n", (temp
&(~0x3ff)));
printf( " tst (sp)+\n" );
printf( " cmp (sp)+,(sp)+\n" );
printf( " add $%d,sp\n", temp);
cbgen( o
, lab
, mode
) { /* printf conditional and unconditional branches */
if( o
== 0 ) printf( " jbr L%d\n", lab
);
if( o
> UGT
) cerror( "bad conditional branch: %s", opst
[o
] );
printf( ccbranches
[o
-EQ
], lab
);
nextcook( p
, cookie
) NODE
*p
; {
/* we have failed to match p with cookie; try another */
if( cookie
== FORREW
) return( 0 ); /* hopeless! */
if( !(cookie
&(INTAREG
|INTBREG
)) ) return( INTAREG
|INTBREG
);
if( !(cookie
&INTEMP
) && asgop(p
->in
.op
) ) return( INTEMP
|INAREG
|INTAREG
|INTBREG
|INBREG
);
lastchance( p
, cook
) NODE
*p
; {
optim2( p
) register NODE
*p
; {
/* do local tree transformations and optimizations */
/* commute L and R to eliminate compliments and constants */
if( (p
->in
.left
->in
.op
==ICON
&&p
->in
.left
->in
.name
[0]==0) || p
->in
.left
->in
.op
==COMPL
) {
p
->in
.left
= p
->in
.right
;
/* change meaning of AND to ~R&L - bic on pdp11 */
if( r
->in
.op
==ICON
&& r
->in
.name
[0]==0 ) { /* compliment constant */
r
->tn
.lval
= ~r
->tn
.lval
;
else if( r
->in
.op
==COMPL
) { /* ~~A => A */
p
->in
.right
= r
->in
.left
;
else { /* insert complement node */
p
->in
.right
->in
.op
= COMPL
;
p
->in
.right
->in
.rall
= NOPREF
;
p
->in
.right
->in
.type
= r
->in
.type
;
p
->in
.right
->in
.left
= r
;
p
->in
.right
->in
.right
= NULL
;
/* OREG was built in clocal()
* for an auto or formal parameter
* now its address is being taken
* local code must unwind it
* back to PLUS/MINUS REG ICON
* according to local conventions
cerror("address of OREG taken");
main( argc
, argv
) char *argv
[]; {
return( mainp2( argc
, argv
) );
hardops(p
) register NODE
*p
; {
/* change hard to do operators into function calls. */
register struct functbl
*f
;
if( t
!=UNSIGNED
&& t
!=ULONG
) return;
for( f
=opfunc
; f
->fop
; f
++ ) {
if( o
==f
->fop
) goto convert
;
/* need to rewrite tree for ASG OP */
/* must change ASG OP to a simple OP */
q
->in
.left
= tcopy(p
->in
.left
);
q
->in
.right
= p
->in
.right
;
zappost(q
->in
.left
); /* remove post-INCR(DECR) from new node */
fixpre(q
->in
.left
); /* change pre-INCR(DECR) to +/- */
/* build comma op for args to function */
q
->in
.right
= p
->in
.right
;
/* put function name in left node of call */
p
->in
.left
= q
= talloc();
q
->in
.type
= INCREF( FTN
+ p
->in
.type
);
strcpy( q
->in
.name
, f
->func
);
/* look for ++ and -- operators and remove them */
p
->in
.right
->in
.op
= FREE
; /* zap constant */
if( ty
== BITYPE
) zappost( p
->in
.right
);
if( ty
!= LTYPE
) zappost( p
->in
.left
);
if( ty
== BITYPE
) fixpre( p
->in
.right
);
if( ty
!= LTYPE
) fixpre( p
->in
.left
);
myreader(p
) register NODE
*p
; {
walkf( p
, hardops
); /* convert ops to function calls */
canon( p
); /* expands r-vals for fileds */
/* jwf toff = 0; /* stack offset swindle */