static char sccsid
[] = "@(#)local2.c 1.4 (Berkeley) %G%";
/* 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
);
register OFFSZ spoff
; /* offset from stack pointer */
extern int ftlab1
, ftlab2
;
printf( " .set .F%d,%d\n", ftnno
, spoff
);
/* SHOULD BE L%d ... ftnno but must change pc/f77 */
printf( " .set LF%d,%d\n", ftnno
, spoff
);
printf( " .set LWM%d,0x%x\n", ftnno
, ent_mask
&0x1ffc|0x1000);
printf( " .set L%d,0x%x\n", ftnno
, ent_mask
&0x1ffc);
printf( "L%d:\n", ftlab1
);
printf( " subl3 $%d,fp,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( "e%s", q
->opstring
);
printf( "%s%c", q
->opstring
, tolower(f
));
cerror( "no hoptab for %s", opst
[o
] );
rnames
[] = { /* keyed to register number tokens */
"r6", "r7", "r8", "r9", "r10", "r11",
/* output register name and update entry mask */
SAREG
|STAREG
, SAREG
|STAREG
,
SAREG
|STAREG
, SAREG
|STAREG
, SAREG
|STAREG
, SAREG
|STAREG
,
SAREG
, SAREG
, SAREG
, SAREG
, SAREG
, SAREG
,
SAREG
, SAREG
, SAREG
, SAREG
,
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", rname(getlr( p
, '1' )->tn
.rval
) );
cbgen( p
->in
.op
, p
->bn
.label
, c
);
case 'A': /* assignment and load (integer only) */
if (xdebug
) eprint(p
, 0, &val
, &val
);
if (optype(p
->in
.op
) == LTYPE
|| p
->in
.op
== UNARY MUL
) {
if(r
->in
.type
==FLOAT
|| r
->in
.type
==DOUBLE
|| l
->in
.type
==FLOAT
|| l
->in
.type
==DOUBLE
)
if(r
->in
.name
[0] == '\0') {
if (r
->tn
.lval
< 0 && r
->tn
.lval
>= -63) {
r
->tn
.lval
= -r
->tn
.lval
;
if( tlen(l
) < tlen(r
) ) {
if (tlen(l
) == tlen(r
)) {
} else if (tlen(l
) > tlen(r
) && ISUNSIGNED(r
->in
.type
))
case 'B': /* get oreg value in temp register for shift */
if (xdebug
) eprint(p
, 0, &val
, &val
);
if( tlen(r
) == sizeof(int) && r
->in
.type
!= FLOAT
)
printf(ISUNSIGNED(r
->in
.type
) ? "movz" : "cvt");
case 'C': /* num bytes pushed on arg stack */
if (xdebug
) printf("->%d<-",gc_numbytes
);
(p
->in
.left
->in
.op
==ICON
&& gc_numbytes
<60)?'f':'s',
/* dont change to double (here's the only place to catch it) */
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': /* masked constant for fields */
printf(ACONFMT
, (p
->in
.right
->tn
.lval
&((1<<fldsz
)-1))<<fldshf
);
case 'H': /* opcode for shift */
if(p
->in
.op
== LS
|| p
->in
.op
== ASG LS
)
else if(ISUNSIGNED(p
->in
.left
->in
.type
))
case 'L': /* type of left operand */
case 'R': /* type of right operand */
if (xdebug
) printf("->%d<-", n
->in
.type
);
case 'M': /* initiate ediv for mod and unsigned div */
m
= getlr(p
, '1')->tn
.rval
;
printf("\tclrl\t%s\n\tmovl\t", r
);
printf(",%s\n", rname(m
+1));
if(!ISUNSIGNED(p
->in
.type
)) { /* should be MOD */
printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m
, r
);
/* Truncate int for type conversions:
LONG|ULONG -> CHAR|UCHAR|SHORT|USHORT
SHORT|USHORT -> CHAR|UCHAR
increment offset to correct byte */
cerror( "Illegal ZU type conversion" );
case 'T': /* rounded structure length for arguments */
printf("movab -%d(sp),sp", size
);
case 'S': /* structure assignment */
cerror( "illegal zzzcode" );
#define MOVB(dst, src, off) { \
printf("\tmovb\t"); upput(src, off); putchar(','); \
upput(dst, off); putchar('\n'); \
#define MOVW(dst, src, off) { \
printf("\tmovw\t"); upput(src, off); putchar(','); \
upput(dst, off); putchar('\n'); \
#define MOVL(dst, src, off) { \
printf("\tmovl\t"); upput(src, off); putchar(','); \
upput(dst, off); putchar('\n'); \
* Generate code for a structure assignment.
case STASG
: /* regular assignment */
case STARG
: /* place arg on the stack */
* Pun source for use in code generation.
if (size
<= 0 || size
> 65535)
cerror("structure size out of range");
* Generate optimized code based on structure size
* and alignment properties....
werror("optimized structure assignment (size %d alignment %d)", size
, p
->stn
.stalign
);
if (p
->stn
.stalign
!= 2) {
if (p
->stn
.stalign
!= 4) {
if (p
->stn
.stalign
!= 2) {
if (p
->stn
.stalign
== 4) {
* Can we ever get a register conflict with R1 here?
printf(",r1\n\tmovab\t");
printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size
);
* Reverse above pun for reclaim.
else if (r
->in
.op
== OREG
)
* Output the address of the second item in the
p
->tn
.lval
+= size
/SZCHAR
;
printf("%s", rname(p
->tn
.rval
+1));
cerror("illegal upper address op %s size %d",
rmove( rt
, rs
, t
) TWORD t
;{
printf( " movl %s,%s\n", rname(rs
), rname(rt
) );
printf( " movl %s,%s\n", rname(rs
+1), rname(rt
+1) );
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 Tahoe (0-5) */
szty(t
) TWORD t
;{ /* size, in registers, needed to hold thing of type t */
return(t
==DOUBLE
? 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 );
offset( p
, tyl
) register NODE
*p
; int tyl
; {
if(tyl
> 8) return( -1 );
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
)) );
register int o
= p
->in
.op
;
if( o
==NAME
|| o
==REG
|| o
==ICON
|| o
==OREG
|| (o
==UNARY MUL
&& shumul(p
->in
.left
)) ) return(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
)
&& p
->in
.type
!= PTR
+DOUBLE
)
special( p
, shape
) register NODE
*p
; {
if( shape
==SIREG
&& p
->in
.op
== OREG
&& R2TEST(p
->tn
.rval
) ) return(1);
adrcon( val
) CONSZ val
; {
conput( p
) register NODE
*p
; {
printf( "%s", rname(p
->tn
.rval
) );
cerror( "illegal conput" );
adrput( p
) register NODE
*p
; {
/* output an address, with offsets, from p */
/* addressable value of the constant */
printf( "%s", rname(p
->tn
.rval
) );
if(p
->in
.type
== DOUBLE
) /* for entry mask */
(void) rname(p
->tn
.rval
+1);
if( R2TEST(r
) ){ /* double indexing */
if( flags
& 1 ) printf("*");
if( p
->tn
.lval
!= 0 || p
->in
.name
[0] != '\0' ) acon(p
);
if( R2UPK1(r
) != 100) printf( "(%s)", rname(R2UPK1(r
)) );
printf( "[%s]", rname(R2UPK2(r
)) );
if( r
== FP
&& p
->tn
.lval
> 0 ){ /* in the argument region */
if( 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)", rname(p
->tn
.rval
) );
/* STARNM or STARREG found */
if( tshape(p
, STARNM
) ) {
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
);
genscall( p
, cookie
) register NODE
*p
; {
/* structure valued call */
return( gencall( p
, cookie
) );
genfcall( p
, cookie
) register NODE
*p
; {
static char *funcops
[6] = {
"sin", "cos", "sqrt", "exp", "log", "atan"
/* generate function opcodes */
if(p
->in
.op
==UNARY FORTCALL
&& p
->in
.type
==FLOAT
&&
(p1
= p
->in
.left
)->in
.op
==ICON
&&
p1
->tn
.lval
==0 && p1
->in
.type
==INCREF(FTN
|FLOAT
)) {
strcpy(p1
->in
.name
, p1
->in
.name
[1]);
if(!strcmp(p1
->in
.name
, funcops
[m
]))
uerror("no opcode for fortarn function %s", p1
->in
.name
);
uerror("illegal type of fortarn function");
order( p1
, INAREG
|INBREG
|SOREG
|STARREG
|STARNM
);
m
= match( p
, INTAREG
|INTBREG
);
gencall( p
, cookie
) register NODE
*p
; {
/* generate the call given by p */
register NODE
*p1
, *ptemp
;
register int temp
, temp1
;
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
) ){
setup gc_numbytes so reference to ZC works */
gc_numbytes
= temp
&(0x3ff);
m
= match( p
, INTAREG
|INTBREG
);
cbgen( o
, lab
, mode
) { /* printf conditional and unconditional branches */
if(o
!= 0 && (o
< EQ
|| o
> UGT
))
cerror( "bad conditional branch: %s", opst
[o
] );
o
== 0 ? "br" : 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 */
# define RV(p) p->in.right->tn.lval
# define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0)
register int o
= p
->in
.op
;
/* change unsigned mods and divs to logicals (mul is done in mip & c2) */
if(optype(o
) == BITYPE
&& ISUNSIGNED(p
->in
.left
->in
.type
)
&& nncon(p
->in
.right
) && (i
=ispow2(RV(p
)))>=0){
hardops(p
) register NODE
*p
; {
/* change hard to do operators into function calls. */
register struct functbl
*f
;
register TWORD t
, t1
, t2
;
for( f
=opfunc
; f
->fop
; f
++ ) {
if( o
==f
->fop
) goto convert
;
t1
= p
->in
.left
->in
.type
;
t2
= p
->in
.right
->in
.type
;
if ( t1
!= UNSIGNED
&& (t2
!= UNSIGNED
)) return;
/* 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 +/- */
/* turn logicals to compare 0 */
p
->in
.right
= q
= talloc();
/* build comma op for args to function */
t1
= p
->in
.left
->in
.type
;
if ( optype(p
->in
.op
) == BITYPE
) {
q
->in
.right
= p
->in
.right
;
t2
= p
->in
.right
->in
.type
;
/* 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
);
NODE
* addroreg(l
) NODE
*l
;
/* 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
) );
myreader(p
) register NODE
*p
; {
walkf( p
, hardops
); /* convert ops to function calls */
canon( p
); /* expands r-vals for fileds */