curtext = P;
switch(HEADTYPE) {
case 0:
case 4:
OFFSET = rnd(HEADR+textsize, 4096);
seek(cout, OFFSET, 0);
break;
case 1:
case 2:
case 3:
case 5:
case 6:
OFFSET = HEADR+textsize;
seek(cout, OFFSET, 0);
break;
}
for(t = 0; t < datsize; t += sizeof(buf)-100) {
if(datsize-t > sizeof(buf)-100)
datblk(t, sizeof(buf)-100, 0);
else
datblk(t, datsize-t, 0);
}
symsize = 0;
lcsize = 0;
if(!debug['s']) {
if(debug['v'])
Bprint(&bso, "%5.2f sym\n", cputime());
Bflush(&bso);
switch(HEADTYPE) {
case 0:
case 4:
OFFSET = rnd(HEADR+textsize, 4096)+datsize;
seek(cout, OFFSET, 0);
break;
case 3:
case 2:
case 1:
case 5:
case 6:
OFFSET = HEADR+textsize+datsize;
seek(cout, OFFSET, 0);
break;
}
if(!debug['s'])
asmsym();
if(debug['v'])
Bprint(&bso, "%5.2f pc\n", cputime());
Bflush(&bso);
if(!debug['s'])
asmlc();
cflush();
}
if(debug['v'])
Bprint(&bso, "%5.2f header\n", cputime());
Bflush(&bso);
OFFSET = 0;
seek(cout, OFFSET, 0);
switch(HEADTYPE) {
case 0:
lput(0x160L<<16); /* magic and sections */
lput(0L); /* time and date */
lput(rnd(HEADR+textsize, 4096)+datsize);
lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0413<<16)|0437L); /* magic and version */
lput(rnd(HEADR+textsize, 4096)); /* sizes */
lput(datsize);
lput(bsssize);
lput(entryvalue()); /* va of entry */
lput(INITTEXT-HEADR); /* va of base of text */
lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(0L);
lput(0L);
lput(0L);
lput(0L);
lput(~0L); /* gp value ?? */
break;
case 1:
lput(0x160L<<16); /* magic and sections */
lput(0L); /* time and date */
lput(HEADR+textsize+datsize);
lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0407<<16)|0437L); /* magic and version */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
lput(entryvalue()); /* va of entry */
lput(INITTEXT); /* va of base of text */
lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(lcsize);
lput(0L);
lput(0L);
lput(0L);
lput(~0L); /* gp value ?? */
lput(0L); /* complete mystery */
break;
case 2:
if (little)
t = 24;
else
t = 16;
lput(((((4*t)+0)*t)+7)); /* magic */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
lput(symsize); /* nsyms */
lput(entryvalue()); /* va of entry */
lput(0L);
lput(lcsize);
break;
case 3:
lput((0x160L<<16)|3L); /* magic and sections */
lput(time(0)); /* time and date */
lput(HEADR+textsize+datsize);
lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0407<<16)|0437L); /* magic and version */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
lput(entryvalue()); /* va of entry */
lput(INITTEXT); /* va of base of text */
lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(lcsize);
lput(0L);
lput(0L);
lput(0L);
lput(~0L); /* gp value ?? */
strnput(".text", 8); /* text segment */
lput(INITTEXT); /* address */
lput(INITTEXT);
lput(textsize);
lput(HEADR);
lput(0L);
lput(HEADR+textsize+datsize+symsize);
lput(lcsize & 0xffff); /* line number size */
lput(0x20L); /* flags */
strnput(".bss", 8); /* bss segment */
lput(INITDAT+datsize); /* address */
lput(INITDAT+datsize);
lput(bsssize);
lput(0L);
lput(0L);
lput(0L);
lput(0L);
lput(0x80L); /* flags */
break;
case 4:
lput((0x160L<<16)|3L); /* magic and sections */
lput(time(0)); /* time and date */
lput(rnd(HEADR+textsize, 4096)+datsize);
lput(symsize); /* nsyms */
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
lput((0413<<16)|01012L); /* magic and version */
lput(textsize); /* sizes */
lput(datsize);
lput(bsssize);
lput(entryvalue()); /* va of entry */
lput(INITTEXT); /* va of base of text */
lput(INITDAT); /* va of base of data */
lput(INITDAT+datsize); /* va of base of bss */
lput(~0L); /* gp reg mask */
lput(lcsize);
lput(0L);
lput(0L);
lput(0L);
lput(~0L); /* gp value ?? */
strnput(".text", 8); /* text segment */
lput(INITTEXT); /* address */
lput(INITTEXT);
lput(textsize);
lput(HEADR);
lput(0L);
lput(HEADR+textsize+datsize+symsize);
lput(lcsize & 0xffff); /* line number size */
lput(0x20L); /* flags */
case 16: /* sll $c,[r1],r2 */
v = regoff(&p->from);
r = p->reg;
if(r == NREG)
r = p->to.reg;
/* OP_SRR will use only the low 5 bits of the shift value */
if(v >= 32 && vshift(p->as))
o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
else
o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
break;
case 18: /* jmp [r1],0(r2) */
if(aflag)
return 0;
r = p->reg;
if(r == NREG)
r = o->param;
o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
break;
case 34: /* mov $con,fr ==> or/add $i,r,r2 */
v = regoff(&p->from);
r = AADDU;
if(o->a1 == C_ANDCON)
r = AOR;
o1 = OP_IRR(opirr(r), v, 0, REGTMP);
o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg); /* mtc1 */
break;
case 35: /* mov r,lext/luto/oreg ==> sw o(r) */
/*
* the lowbits of the constant cannot
* be moved into the offset of the load
* because the mips 4000 in 64-bit mode
* does a 64-bit add and it will screw up.
*/
v = regoff(&p->to);
r = p->to.reg;
if(r == NREG)
r = o->param;
if(r == REGTMP)
diag("cant synthesize large constant\n%P", p);
o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
break;
long
oprrr(int a)
{
switch(a) {
case AADD: return OP(4,0);
case AADDU: return OP(4,1);
case ASGT: return OP(5,2);
case ASGTU: return OP(5,3);
case AAND: return OP(4,4);
case AOR: return OP(4,5);
case AXOR: return OP(4,6);
case ASUB: return OP(4,2);
case ASUBU: return OP(4,3);
case ANOR: return OP(4,7);
case ASLL: return OP(0,4);
case ASRL: return OP(0,6);
case ASRA: return OP(0,7);
case AREM:
case ADIV: return OP(3,2);
case AREMU:
case ADIVU: return OP(3,3);
case AMUL: return OP(3,0);
case AMULU: return OP(3,1);
case AJMP: return OP(1,0);
case AJAL: return OP(1,1);
case ABREAK: return OP(1,5);
case ASYSCALL: return OP(1,4);
case ATLBP: return MMU(1,0);
case ATLBR: return MMU(0,1);
case ATLBWI: return MMU(0,2);
case ATLBWR: return MMU(0,6);
case ARFE: return MMU(2,0);
case ADIVF: return FPF(0,3);
case ADIVD: return FPD(0,3);
case AMULF: return FPF(0,2);
case AMULD: return FPD(0,2);
case ASUBF: return FPF(0,1);
case ASUBD: return FPD(0,1);
case AADDF: return FPF(0,0);
case AADDD: return FPD(0,0);
case AMOVFW: return FPF(4,4);
case AMOVDW: return FPD(4,4);
case AMOVWF: return FPW(4,0);
case AMOVDF: return FPD(4,0);
case AMOVWD: return FPW(4,1);
case AMOVFD: return FPF(4,1);
case AABSF: return FPF(0,5);
case AABSD: return FPD(0,5);
case AMOVF: return FPF(0,6);
case AMOVD: return FPD(0,6);
case ANEGF: return FPF(0,7);
case ANEGD: return FPD(0,7);
case ACMPEQF: return FPF(6,2);
case ACMPEQD: return FPD(6,2);
case ACMPGTF: return FPF(7,4);
case ACMPGTD: return FPD(7,4);
case ACMPGEF: return FPF(7,6);
case ACMPGED: return FPD(7,6);
case ADIVV: return OP(3,6);
case ADIVVU: return OP(3,7);
case AADDV: return OP(5,4);
case AADDVU: return OP(5,5);
}
diag("bad rrr %d", a);
return 0;
}
long
opirr(int a)
{
switch(a) {
case AADD: return SP(1,0);
case AADDU: return SP(1,1);
case ASGT: return SP(1,2);
case ASGTU: return SP(1,3);
case AAND: return SP(1,4);
case AOR: return SP(1,5);
case AXOR: return SP(1,6);
case ALAST: return SP(1,7);
case ASLL: return OP(0,0);
case ASRL: return OP(0,2);
case ASRA: return OP(0,3);
case AJMP: return SP(0,2);
case AJAL: return SP(0,3);
case ABEQ: return SP(0,4);
case ABNE: return SP(0,5);
case ABGEZ: return SP(0,1)|BCOND(0,1);
case ABGEZAL: return SP(0,1)|BCOND(2,1);
case ABGTZ: return SP(0,7);
case ABLEZ: return SP(0,6);
case ABLTZ: return SP(0,1)|BCOND(0,0);
case ABLTZAL: return SP(0,1)|BCOND(2,0);
case ABFPT: return SP(2,1)|(257<<16);
case ABFPF: return SP(2,1)|(256<<16);
case AMOVB:
case AMOVBU: return SP(5,0);
case AMOVH:
case AMOVHU: return SP(5,1);
case AMOVW: return SP(5,3);
case AMOVV: return SP(7,7);
case AMOVF: return SP(7,1);
case AMOVWL: return SP(5,2);
case AMOVWR: return SP(5,6);
case AMOVVL: return SP(5,4);
case AMOVVR: return SP(5,5);
case ABREAK: return SP(5,7);
case AMOVWL+ALAST: return SP(4,2);
case AMOVWR+ALAST: return SP(4,6);
case AMOVVL+ALAST: return SP(3,2);
case AMOVVR+ALAST: return SP(3,3);
case AMOVB+ALAST: return SP(4,0);
case AMOVBU+ALAST: return SP(4,4);
case AMOVH+ALAST: return SP(4,1);
case AMOVHU+ALAST: return SP(4,5);
case AMOVW+ALAST: return SP(4,3);
case AMOVV+ALAST: return SP(6,7);
case AMOVF+ALAST: return SP(6,1);
case ASLLV: return OP(7,0);
case ASRLV: return OP(7,2);
case ASRAV: return OP(7,3);
case ASLLV+ALAST: return OP(7,4);
case ASRLV+ALAST: return OP(7,6);
case ASRAV+ALAST: return OP(7,7);
case AADDV: return SP(3,0);
case AADDVU: return SP(3,1);
}
diag("bad irr %d", a);
abort();
return 0;
}
int
vshift(int a)
{
switch(a){
case ASLLV: return 1;
case ASRLV: return 1;
case ASRAV: return 1;
}
return 0;
}