ar = 0; /* dest is really reference */
ad = 0; /* source/dest is really address */
ld = 0; /* opcode is load instruction */
sz = 20; /* size of load/store for overlap computation */
/*
* flags based on opcode
*/
switch(p->as) {
case ATEXT:
curtext = realp;
autosize = p->to.offset + 4;
ad = 1;
break;
case AJAL:
c = p->reg;
if(c == NREG)
c = REGLINK;
s->set.ireg |= 1<<c;
ar = 1;
ad = 1;
break;
case ABGEZAL:
case ABLTZAL:
s->set.ireg |= 1<<REGLINK;
case ABEQ:
case ABGEZ:
case ABGTZ:
case ABLEZ:
case ABLTZ:
case ABNE:
ar = 1;
ad = 1;
break;
case ABFPT:
case ABFPF:
ad = 1;
s->used.cc |= E_FCR;
break;
case ACMPEQD:
case ACMPEQF:
case ACMPGED:
case ACMPGEF:
case ACMPGTD:
case ACMPGTF:
ar = 1;
s->set.cc |= E_FCR;
p->mark |= FCMP;
break;
case AJMP:
ar = 1;
ad = 1;
break;
case AMOVB:
case AMOVBU:
sz = 1;
ld = 1;
break;
case AMOVH:
case AMOVHU:
sz = 2;
ld = 1;
break;
case AMOVF:
case AMOVW:
case AMOVWL:
case AMOVWR:
sz = 4;
ld = 1;
break;
case AMOVD:
case AMOVV:
case AMOVVL:
case AMOVVR:
sz = 8;
ld = 1;
break;
case ADIV:
case ADIVU:
case AMUL:
case AMULU:
case AREM:
case AREMU:
s->set.cc = E_HILO;
case AADD:
case AADDU:
case AAND:
case ANOR:
case AOR:
case ASGT:
case ASGTU:
case ASLL:
case ASRA:
case ASRL:
case ASUB:
case ASUBU:
case AXOR:
case AADDD:
case AADDF:
case AADDW:
case ASUBD:
case ASUBF:
case ASUBW:
case AMULF:
case AMULD:
case AMULW:
case ADIVF:
case ADIVD:
case ADIVW:
if(p->reg == NREG) {
if(p->to.type == D_REG || p->to.type == D_FREG)
p->reg = p->to.reg;
if(p->reg == NREG)
print("botch %P\n", p);
}
break;
}
/*
* flags based on 'to' field
*/
c = p->to.class;
if(c == 0) {
c = aclass(&p->to) + 1;
p->to.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->to);
case C_ZCON:
case C_SCON:
case C_ADD0CON:
case C_AND0CON:
case C_ADDCON:
case C_ANDCON:
case C_UCON:
case C_LCON:
case C_NONE:
case C_SBRA:
case C_LBRA:
break;
case C_HI:
case C_LO:
s->set.cc |= E_HILO;
break;
case C_FCREG:
s->set.cc |= E_FCR;
break;
case C_MREG:
s->set.cc |= E_MCR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->to.reg;
s->used.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
if(ar)
s->used.cc |= m;
else
s->set.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
break;
case C_REG:
if(ar)
s->used.ireg |= 1<<p->to.reg;
else
s->set.ireg |= 1<<p->to.reg;
break;
case C_FREG:
/* do better -- determine double prec */
if(ar) {
s->used.freg |= 1<<p->to.reg;
s->used.freg |= 1<<(p->to.reg|1);
} else {
s->set.freg |= 1<<p->to.reg;
s->set.freg |= 1<<(p->to.reg|1);
}
if(ld && p->from.type == D_REG)
p->mark |= LOAD;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
/*
* flags based on 'from' field
*/
c = p->from.class;
if(c == 0) {
c = aclass(&p->from) + 1;
p->from.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->from);
case C_ZCON:
case C_SCON:
case C_ADD0CON:
case C_AND0CON:
case C_ADDCON:
case C_ANDCON:
case C_UCON:
case C_LCON:
case C_NONE:
case C_SBRA:
case C_LBRA:
break;
case C_HI:
case C_LO:
s->used.cc |= E_HILO;
break;
case C_FCREG:
s->used.cc |= E_FCR;
break;
case C_MREG:
s->used.cc |= E_MCR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->from.reg;
s->used.ireg |= 1<<c;
if(ld)
p->mark |= LOAD;
s->size = sz;
s->soffset = regoff(&p->from);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
s->used.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
break;
case C_REG:
s->used.ireg |= 1<<p->from.reg;
break;
case C_FREG:
/* do better -- determine double prec */
s->used.freg |= 1<<p->from.reg;
s->used.freg |= 1<<(p->from.reg|1);
if(ld && p->to.type == D_REG)
p->mark |= LOAD;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
/*
* special case.
* loads from same address cannot pass.
* this is for hardware fifo's and the like
*/
if(sa->used.cc & sb->used.cc & E_MEM)
if(sa->p.reg == sb->p.reg)
if(regoff(&sa->p.from) == regoff(&sb->p.from))
return 1;
x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
(sb->set.cc & sa->used.cc);
if(x) {
/*
* allow SB and SP to pass each other.
* allow SB to pass SB iff doffsets are ok
* anything else conflicts
*/
if(x != E_MEMSP && x != E_MEMSB)
return 1;
x = sa->set.cc | sb->set.cc |
sa->used.cc | sb->used.cc;
if(x & E_MEM)
return 1;
if(offoverlap(sa, sb))
return 1;
}