"FPSR", LFCR, REG_FPSR,
"FPCR", LFCR, REG_FPCR,
- ".EQ", LCOND, 0,
- ".NE", LCOND, 1,
- ".CS", LCOND, 2,
- ".HS", LCOND, 2,
- ".CC", LCOND, 3,
- ".LO", LCOND, 3,
- ".MI", LCOND, 4,
- ".PL", LCOND, 5,
- ".VS", LCOND, 6,
- ".VC", LCOND, 7,
- ".HI", LCOND, 8,
- ".LS", LCOND, 9,
- ".GE", LCOND, 10,
- ".LT", LCOND, 11,
- ".GT", LCOND, 12,
- ".LE", LCOND, 13,
- ".AL", LCOND, Always,
+ ".EQ", LCOND, C_SCOND_EQ,
+ ".NE", LCOND, C_SCOND_NE,
+ ".CS", LCOND, C_SCOND_HS,
+ ".HS", LCOND, C_SCOND_HS,
+ ".CC", LCOND, C_SCOND_LO,
+ ".LO", LCOND, C_SCOND_LO,
+ ".MI", LCOND, C_SCOND_MI,
+ ".PL", LCOND, C_SCOND_PL,
+ ".VS", LCOND, C_SCOND_VS,
+ ".VC", LCOND, C_SCOND_VC,
+ ".HI", LCOND, C_SCOND_HI,
+ ".LS", LCOND, C_SCOND_LS,
+ ".GE", LCOND, C_SCOND_GE,
+ ".LT", LCOND, C_SCOND_LT,
+ ".GT", LCOND, C_SCOND_GT,
+ ".LE", LCOND, C_SCOND_LE,
+ ".AL", LCOND, C_SCOND_NONE,
".U", LS, C_UBIT,
".S", LS, C_SBIT,
/* hack to make B.NE etc. work: turn it into the corresponding conditional */
if(a == AB){
- a = bcode[scond&0xf];
- scond = (scond & ~0xf) | Always;
+ a = bcode[(scond^C_SCOND_XOR)&0xf];
+ scond = (scond & ~0xf) | C_SCOND_NONE;
}
if(pass == 1)
static void buildop(Link*);
+// Note about encoding: Prog.scond holds the condition encoding,
+// but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
+// The code that shifts the value << 28 has the responsibility
+// for XORing with C_SCOND_XOR too.
+
// asmoutnacl assembles the instruction p. It replaces asmout for NaCl.
// It returns the total number of bytes put in out, and it can change
// p->pc if extra padding is necessary.
if((p->pc&15) == 12)
p->pc += 4;
if(out != nil) {
- out[0] = ((p->scond&C_SCOND)<<28) | 0x03c0013f | ((p->to.reg&15) << 12) | ((p->to.reg&15) << 16); // BIC $0xc000000f, Rx
+ out[0] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03c0013f | ((p->to.reg&15) << 12) | ((p->to.reg&15) << 16); // BIC $0xc000000f, Rx
if(p->as == AB)
- out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff10 | (p->to.reg&15)<<0; // BX Rx
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff10 | (p->to.reg&15)<<0; // BX Rx
else // ABL
- out[1] = ((p->scond&C_SCOND)<<28) | 0x012fff30 | (p->to.reg&15)<<0; // BLX Rx
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff30 | (p->to.reg&15)<<0; // BLX Rx
}
size = 8;
}
// Note: 5c and 5g reg.c know that DIV/MOD smashes R12
// so that this return instruction expansion is valid.
out[0] = out[0] & ~0x3000; // change PC to R12
- out[1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
- out[2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ out[1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[2] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff1c; // BX R12
}
size += 8;
if(((p->pc+size) & 15) == 4)
// offset to update R13, so we need to additionally mask R13.
if(out != nil) {
out[size/4-1] &= ~0x3000; // change PC to R12
- out[size/4] = ((p->scond&C_SCOND)<<28) | 0x03cdd103; // BIC $0xc0000000, R13
- out[size/4+1] = ((p->scond&C_SCOND)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
- out[size/4+2] = ((p->scond&C_SCOND)<<28) | 0x012fff1c; // BX R12
+ out[size/4] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03cdd103; // BIC $0xc0000000, R13
+ out[size/4+1] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03ccc13f; // BIC $0xc000000f, R12
+ out[size/4+2] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x012fff1c; // BX R12
}
// p->pc+size is only ok at 4 or 12 mod 16.
if((p->pc+size)%8 == 0)
asmout(ctxt, p, o, out);
} else {
if(out != nil)
- out[0] = ((p->scond&C_SCOND)<<28) | 0x03c00103 | ((reg&15) << 16) | ((reg&15) << 12); // BIC $0xc0000000, Rx
+ out[0] = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | 0x03c00103 | ((reg&15) << 16) | ((reg&15) << 12); // BIC $0xc0000000, Rx
if((p->pc&15) == 12)
p->pc += 4;
size += 4;
case 35: /* mov PSR,R */
o1 = (2<<23) | (0xf<<16) | (0<<0);
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (p->from.reg & 1) << 22;
o1 |= (p->to.reg&15) << 12;
break;
o1 = (2<<23) | (0x29f<<12) | (0<<4);
if(p->scond & C_FBIT)
o1 ^= 0x010 << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (p->to.reg & 1) << 22;
o1 |= (p->from.reg&15) << 0;
break;
o1 = (2<<23) | (0x29f<<12) | (0<<4);
if(p->scond & C_FBIT)
o1 ^= 0x010 << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= immrot(ctxt->instoffset);
o1 |= (p->to.reg & 1) << 22;
o1 |= (p->from.reg&15) << 0;
}
if(ctxt->instoffset != 0)
ctxt->diag("offset must be zero in MOVM; %P", p);
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
if(p->scond & C_PBIT)
o1 |= 1 << 24;
if(p->scond & C_UBIT)
o1 |= (p->from.reg&15) << 16;
o1 |= (p->reg&15) << 0;
o1 |= (p->to.reg&15) << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
break;
case 56: /* move to FP[CS]R */
- o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
+ o1 = (((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28) | (0xe << 24) | (1<<8) | (1<<4);
o1 |= (((p->to.reg&1)+1)<<21) | ((p->from.reg&15) << 12);
break;
case 57: /* move from FP[CS]R */
- o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
+ o1 = (((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28) | (0xe << 24) | (1<<8) | (1<<4);
o1 |= (((p->from.reg&1)+1)<<21) | ((p->to.reg&15)<<12) | (1<<20);
break;
case 58: /* movbu R,R */
ctxt->diag("non-zero offset in ABX");
/*
o1 = oprrr(ctxt, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR
- o2 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R
+ o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R
*/
// p->to.reg may be REGLINK
o1 = oprrr(ctxt, AADD, p->scond);
o1 |= (p->to.reg&15) << 16;
o1 |= (REGTMP&15) << 12;
o2 = oprrr(ctxt, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR
- o3 = ((p->scond&C_SCOND)<<28) | (0x12fff<<8) | (1<<4) | (REGTMP&15); // BX Rtmp
+ o3 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | (REGTMP&15); // BX Rtmp
break;
case 76: /* bx O(R) when returning from fn*/
ctxt->diag("ABXRET");
o1 = (0x19<<20) | (0xf9f);
o1 |= (p->from.reg&15) << 16;
o1 |= (p->to.reg&15) << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 78: /* strex reg,oreg,reg */
aclass(ctxt, &p->from);
o1 |= (p->from.reg&15) << 16;
o1 |= (p->reg&15) << 0;
o1 |= (p->to.reg&15) << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 80: /* fmov zfcon,freg */
if(p->as == AMOVD) {
r = (p->to.reg&15) << 0;
// movf $1.0, r
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (r&15) << 12;
o1 |= (v&0xf) << 0;
o1 |= (v&0xf0) << 12;
o1 = 0x0eb00a00; // VMOV imm 32
if(p->as == AMOVD)
o1 = 0xeeb00b00; // VMOV imm 64
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
o1 |= (p->to.reg&15) << 12;
v = chipfloat5(ctxt, p->from.u.dval);
o1 |= (v&0xf) << 0;
o1 = oprrr(ctxt, p->as, p->scond);
o1 |= ((p->reg&15)<<12) | ((p->from.reg&15)<<0);
o2 = 0x0ef1fa10; // VMRS R15
- o2 |= (p->scond & C_SCOND) << 28;
+ o2 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 83: /* fcmp freg,, */
o1 = oprrr(ctxt, p->as, p->scond);
o1 |= ((p->from.reg&15)<<12) | (1<<16);
o2 = 0x0ef1fa10; // VMRS R15
- o2 |= (p->scond & C_SCOND) << 28;
+ o2 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 84: /* movfw freg,freg - truncate float-to-fix */
o1 = oprrr(ctxt, p->as, p->scond);
o1 = (0x1b<<20) | (0xf9f);
o1 |= (p->from.reg&15) << 16;
o1 |= (p->to.reg&15) << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 92: /* strexd reg,oreg,reg */
aclass(ctxt, &p->from);
o1 |= (p->from.reg&15) << 16;
o1 |= (p->reg&15) << 0;
o1 |= (p->to.reg&15) << 12;
- o1 |= (p->scond & C_SCOND) << 28;
+ o1 |= ((p->scond & C_SCOND) ^ C_SCOND_XOR) << 28;
break;
case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
o1 = omvl(ctxt, p, &p->from, REGTMP);
{
uint32 o;
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(sc & C_SBIT)
o |= 1 << 20;
if(sc & (C_PBIT|C_WBIT))
if(sc & (C_SBIT|C_PBIT|C_WBIT))
ctxt->diag(".nil/.nil/.W on bra instruction");
sc &= C_SCOND;
+ sc ^= C_SCOND_XOR;
if(a == ABL || a == ADUFFZERO || a == ADUFFCOPY)
return (sc<<28)|(0x5<<25)|(0x1<<24);
if(sc != 0xe)
if(sc & C_SBIT)
ctxt->diag(".nil on LDR/STR instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(!(sc & C_UBIT))
if(sc & C_SBIT)
ctxt->diag(".nil on LDRH/STRH instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(sc & C_WBIT)
if(sc & C_SBIT)
ctxt->diag(".nil on FLDR/FSTR instruction");
- o = (sc & C_SCOND) << 28;
+ o = ((sc & C_SCOND) ^ C_SCOND_XOR) << 28;
if(!(sc & C_PBIT))
o |= 1 << 24;
if(sc & C_WBIT)