/* --------- Registers. --------- */
+const RRegUniverse* getRRegUniverse_AMD64 ( void )
+{
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. */
+ static RRegUniverse rRegUniverse_AMD64;
+ static Bool rRegUniverse_AMD64_initted = False;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_AMD64;
+
+ /* This isn't thread-safe. Sigh. */
+ if (LIKELY(rRegUniverse_AMD64_initted))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+ ru->regs[ru->size++] = hregAMD64_RSI();
+ ru->regs[ru->size++] = hregAMD64_RDI();
+ ru->regs[ru->size++] = hregAMD64_R8();
+ ru->regs[ru->size++] = hregAMD64_R9();
+ ru->regs[ru->size++] = hregAMD64_R12();
+ ru->regs[ru->size++] = hregAMD64_R13();
+ ru->regs[ru->size++] = hregAMD64_R14();
+ ru->regs[ru->size++] = hregAMD64_R15();
+ ru->regs[ru->size++] = hregAMD64_RBX();
+ ru->regs[ru->size++] = hregAMD64_XMM3();
+ ru->regs[ru->size++] = hregAMD64_XMM4();
+ ru->regs[ru->size++] = hregAMD64_XMM5();
+ ru->regs[ru->size++] = hregAMD64_XMM6();
+ ru->regs[ru->size++] = hregAMD64_XMM7();
+ ru->regs[ru->size++] = hregAMD64_XMM8();
+ ru->regs[ru->size++] = hregAMD64_XMM9();
+ ru->regs[ru->size++] = hregAMD64_XMM10();
+ ru->regs[ru->size++] = hregAMD64_XMM11();
+ ru->regs[ru->size++] = hregAMD64_XMM12();
+ ru->regs[ru->size++] = hregAMD64_R10();
+ ru->allocable = ru->size;
+ /* And other regs, not available to the allocator. */
+ ru->regs[ru->size++] = hregAMD64_RAX();
+ ru->regs[ru->size++] = hregAMD64_RCX();
+ ru->regs[ru->size++] = hregAMD64_RDX();
+ ru->regs[ru->size++] = hregAMD64_RSP();
+ ru->regs[ru->size++] = hregAMD64_RBP();
+ ru->regs[ru->size++] = hregAMD64_R11();
+ ru->regs[ru->size++] = hregAMD64_XMM0();
+ ru->regs[ru->size++] = hregAMD64_XMM1();
+
+ rRegUniverse_AMD64_initted = True;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
+
void ppHRegAMD64 ( HReg reg )
{
Int r;
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 16);
vex_printf("%s", ireg64_names[r]);
return;
- case HRcFlt64:
- r = hregNumber(reg);
- vassert(r >= 0 && r < 6);
- vex_printf("%%fake%d", r);
- return;
case HRcVec128:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 16);
vex_printf("%%xmm%d", r);
return;
{
Int r;
static const HChar* ireg32_names[16]
- = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
- "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
+ = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+ "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
/* Be generic for all virtual regs. */
if (hregIsVirtual(reg)) {
ppHReg(reg);
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 16);
vex_printf("%s", ireg32_names[r]);
return;
}
}
-HReg hregAMD64_RAX ( void ) { return mkHReg( 0, HRcInt64, False); }
-HReg hregAMD64_RCX ( void ) { return mkHReg( 1, HRcInt64, False); }
-HReg hregAMD64_RDX ( void ) { return mkHReg( 2, HRcInt64, False); }
-HReg hregAMD64_RBX ( void ) { return mkHReg( 3, HRcInt64, False); }
-HReg hregAMD64_RSP ( void ) { return mkHReg( 4, HRcInt64, False); }
-HReg hregAMD64_RBP ( void ) { return mkHReg( 5, HRcInt64, False); }
-HReg hregAMD64_RSI ( void ) { return mkHReg( 6, HRcInt64, False); }
-HReg hregAMD64_RDI ( void ) { return mkHReg( 7, HRcInt64, False); }
-HReg hregAMD64_R8 ( void ) { return mkHReg( 8, HRcInt64, False); }
-HReg hregAMD64_R9 ( void ) { return mkHReg( 9, HRcInt64, False); }
-HReg hregAMD64_R10 ( void ) { return mkHReg(10, HRcInt64, False); }
-HReg hregAMD64_R11 ( void ) { return mkHReg(11, HRcInt64, False); }
-HReg hregAMD64_R12 ( void ) { return mkHReg(12, HRcInt64, False); }
-HReg hregAMD64_R13 ( void ) { return mkHReg(13, HRcInt64, False); }
-HReg hregAMD64_R14 ( void ) { return mkHReg(14, HRcInt64, False); }
-HReg hregAMD64_R15 ( void ) { return mkHReg(15, HRcInt64, False); }
-
-HReg hregAMD64_XMM0 ( void ) { return mkHReg( 0, HRcVec128, False); }
-HReg hregAMD64_XMM1 ( void ) { return mkHReg( 1, HRcVec128, False); }
-HReg hregAMD64_XMM3 ( void ) { return mkHReg( 3, HRcVec128, False); }
-HReg hregAMD64_XMM4 ( void ) { return mkHReg( 4, HRcVec128, False); }
-HReg hregAMD64_XMM5 ( void ) { return mkHReg( 5, HRcVec128, False); }
-HReg hregAMD64_XMM6 ( void ) { return mkHReg( 6, HRcVec128, False); }
-HReg hregAMD64_XMM7 ( void ) { return mkHReg( 7, HRcVec128, False); }
-HReg hregAMD64_XMM8 ( void ) { return mkHReg( 8, HRcVec128, False); }
-HReg hregAMD64_XMM9 ( void ) { return mkHReg( 9, HRcVec128, False); }
-HReg hregAMD64_XMM10 ( void ) { return mkHReg(10, HRcVec128, False); }
-HReg hregAMD64_XMM11 ( void ) { return mkHReg(11, HRcVec128, False); }
-HReg hregAMD64_XMM12 ( void ) { return mkHReg(12, HRcVec128, False); }
-
-
-void getAllocableRegs_AMD64 ( Int* nregs, HReg** arr )
-{
-#if 0
- *nregs = 6;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
- (*arr)[ 0] = hregAMD64_RSI();
- (*arr)[ 1] = hregAMD64_RDI();
- (*arr)[ 2] = hregAMD64_RBX();
-
- (*arr)[ 3] = hregAMD64_XMM7();
- (*arr)[ 4] = hregAMD64_XMM8();
- (*arr)[ 5] = hregAMD64_XMM9();
-#endif
-#if 1
- *nregs = 20;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
- (*arr)[ 0] = hregAMD64_RSI();
- (*arr)[ 1] = hregAMD64_RDI();
- (*arr)[ 2] = hregAMD64_R8();
- (*arr)[ 3] = hregAMD64_R9();
- (*arr)[ 4] = hregAMD64_R12();
- (*arr)[ 5] = hregAMD64_R13();
- (*arr)[ 6] = hregAMD64_R14();
- (*arr)[ 7] = hregAMD64_R15();
- (*arr)[ 8] = hregAMD64_RBX();
-
- (*arr)[ 9] = hregAMD64_XMM3();
- (*arr)[10] = hregAMD64_XMM4();
- (*arr)[11] = hregAMD64_XMM5();
- (*arr)[12] = hregAMD64_XMM6();
- (*arr)[13] = hregAMD64_XMM7();
- (*arr)[14] = hregAMD64_XMM8();
- (*arr)[15] = hregAMD64_XMM9();
- (*arr)[16] = hregAMD64_XMM10();
- (*arr)[17] = hregAMD64_XMM11();
- (*arr)[18] = hregAMD64_XMM12();
- (*arr)[19] = hregAMD64_R10();
-#endif
-}
-
/* --------- Condition codes, Intel encoding. --------- */
/* --------- The amd64 assembler (bleh.) --------- */
/* Produce the low three bits of an integer register number. */
-static UChar iregBits210 ( HReg r )
+inline static UInt iregEnc210 ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return toUChar(n & 7);
+ return n & 7;
}
/* Produce bit 3 of an integer register number. */
-static UChar iregBit3 ( HReg r )
+inline static UInt iregEnc3 ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return toUChar((n >> 3) & 1);
+ return (n >> 3) & 1;
}
/* Produce a complete 4-bit integer register number. */
-static UChar iregBits3210 ( HReg r )
+inline static UInt iregEnc3210 ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return toUChar(n);
+ return n;
}
-/* Given an xmm (128bit V-class) register number, produce the
- equivalent numbered register in 64-bit I-class. This is a bit of
- fakery which facilitates using functions that work on integer
- register numbers to be used when assembling SSE instructions
- too. */
-static HReg vreg2ireg ( HReg r )
+/* Produce a complete 4-bit integer register number. */
+inline static UInt vregEnc3210 ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcVec128);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return mkHReg(n, HRcInt64, False);
+ return n;
}
-//uu /* Ditto for ymm regs. */
-//uu static HReg dvreg2ireg ( HReg r )
-//uu {
-//uu UInt n;
-//uu vassert(hregClass(r) == HRcVec256);
-//uu vassert(!hregIsVirtual(r));
-//uu n = hregNumber(r);
-//uu vassert(n <= 15);
-//uu return mkHReg(n, HRcInt64, False);
-//uu }
-
-static UChar mkModRegRM ( UInt mod, UInt reg, UInt regmem )
+inline static UChar mkModRegRM ( UInt mod, UInt reg, UInt regmem )
{
vassert(mod < 4);
vassert((reg|regmem) < 8);
- return toUChar( ((mod & 3) << 6)
- | ((reg & 7) << 3)
- | (regmem & 7) );
+ return (UChar)( ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7) );
}
-static UChar mkSIB ( UInt shift, UInt regindex, UInt regbase )
+inline static UChar mkSIB ( UInt shift, UInt regindex, UInt regbase )
{
vassert(shift < 4);
vassert((regindex|regbase) < 8);
- return toUChar( ((shift & 3) << 6)
- | ((regindex & 7) << 3)
- | (regbase & 7) );
+ return (UChar)( ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7) );
}
static UChar* emit32 ( UChar* p, UInt w32 )
| index != RSP
= 10 greg 100, scale index base, d32
*/
-static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
+static UChar* doAMode_M__wrk ( UChar* p, UInt gregEnc3210, AMD64AMode* am )
{
+ UInt gregEnc210 = gregEnc3210 & 7;
if (am->tag == Aam_IR) {
if (am->Aam.IR.imm == 0
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_R13())
) {
- *p++ = mkModRegRM(0, iregBits210(greg),
- iregBits210(am->Aam.IR.reg));
+ *p++ = mkModRegRM(0, gregEnc210, iregEnc210(am->Aam.IR.reg));
return p;
}
if (fits8bits(am->Aam.IR.imm)
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
) {
- *p++ = mkModRegRM(1, iregBits210(greg),
- iregBits210(am->Aam.IR.reg));
+ *p++ = mkModRegRM(1, gregEnc210, iregEnc210(am->Aam.IR.reg));
*p++ = toUChar(am->Aam.IR.imm & 0xFF);
return p;
}
if (! sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
&& ! sameHReg(am->Aam.IR.reg, hregAMD64_R12())
) {
- *p++ = mkModRegRM(2, iregBits210(greg),
- iregBits210(am->Aam.IR.reg));
+ *p++ = mkModRegRM(2, gregEnc210, iregEnc210(am->Aam.IR.reg));
p = emit32(p, am->Aam.IR.imm);
return p;
}
if ((sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
|| sameHReg(am->Aam.IR.reg, hregAMD64_R12()))
&& fits8bits(am->Aam.IR.imm)) {
- *p++ = mkModRegRM(1, iregBits210(greg), 4);
+ *p++ = mkModRegRM(1, gregEnc210, 4);
*p++ = 0x24;
*p++ = toUChar(am->Aam.IR.imm & 0xFF);
return p;
}
if (/* (sameHReg(am->Aam.IR.reg, hregAMD64_RSP())
- || wait for test case for RSP case */
+ || wait for test case for RSP case */
sameHReg(am->Aam.IR.reg, hregAMD64_R12())) {
- *p++ = mkModRegRM(2, iregBits210(greg), 4);
+ *p++ = mkModRegRM(2, gregEnc210, 4);
*p++ = 0x24;
p = emit32(p, am->Aam.IR.imm);
return p;
if (am->tag == Aam_IRRS) {
if (fits8bits(am->Aam.IRRS.imm)
&& ! sameHReg(am->Aam.IRRS.index, hregAMD64_RSP())) {
- *p++ = mkModRegRM(1, iregBits210(greg), 4);
- *p++ = mkSIB(am->Aam.IRRS.shift, iregBits210(am->Aam.IRRS.index),
- iregBits210(am->Aam.IRRS.base));
+ *p++ = mkModRegRM(1, gregEnc210, 4);
+ *p++ = mkSIB(am->Aam.IRRS.shift, iregEnc210(am->Aam.IRRS.index),
+ iregEnc210(am->Aam.IRRS.base));
*p++ = toUChar(am->Aam.IRRS.imm & 0xFF);
return p;
}
if (! sameHReg(am->Aam.IRRS.index, hregAMD64_RSP())) {
- *p++ = mkModRegRM(2, iregBits210(greg), 4);
- *p++ = mkSIB(am->Aam.IRRS.shift, iregBits210(am->Aam.IRRS.index),
- iregBits210(am->Aam.IRRS.base));
+ *p++ = mkModRegRM(2, gregEnc210, 4);
+ *p++ = mkSIB(am->Aam.IRRS.shift, iregEnc210(am->Aam.IRRS.index),
+ iregEnc210(am->Aam.IRRS.base));
p = emit32(p, am->Aam.IRRS.imm);
return p;
}
/*NOTREACHED*/
}
+static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
+{
+ return doAMode_M__wrk(p, iregEnc3210(greg), am);
+}
+
+static UChar* doAMode_M_enc ( UChar* p, UInt gregEnc3210, AMD64AMode* am )
+{
+ vassert(gregEnc3210 < 16);
+ return doAMode_M__wrk(p, gregEnc3210, am);
+}
+
/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
-static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
+inline
+static UChar* doAMode_R__wrk ( UChar* p, UInt gregEnc3210, UInt eregEnc3210 )
{
- *p++ = mkModRegRM(3, iregBits210(greg), iregBits210(ereg));
+ *p++ = mkModRegRM(3, gregEnc3210 & 7, eregEnc3210 & 7);
return p;
}
+static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
+{
+ return doAMode_R__wrk(p, iregEnc3210(greg), iregEnc3210(ereg));
+}
+
+static UChar* doAMode_R_enc_reg ( UChar* p, UInt gregEnc3210, HReg ereg )
+{
+ vassert(gregEnc3210 < 16);
+ return doAMode_R__wrk(p, gregEnc3210, iregEnc3210(ereg));
+}
+
+static UChar* doAMode_R_reg_enc ( UChar* p, HReg greg, UInt eregEnc3210 )
+{
+ vassert(eregEnc3210 < 16);
+ return doAMode_R__wrk(p, iregEnc3210(greg), eregEnc3210);
+}
+
+static UChar* doAMode_R_enc_enc ( UChar* p, UInt gregEnc3210, UInt eregEnc3210 )
+{
+ vassert( (gregEnc3210|eregEnc3210) < 16);
+ return doAMode_R__wrk(p, gregEnc3210, eregEnc3210);
+}
+
/* Clear the W bit on a REX byte, thereby changing the operand size
back to whatever that instruction's default operand size is. */
static inline UChar clearWBit ( UChar rex )
{
- return toUChar(rex & ~(1<<3));
+ return rex & ~(1<<3);
}
/* Make up a REX byte, with W=1 (size=64), for a (greg,amode) pair. */
-static UChar rexAMode_M ( HReg greg, AMD64AMode* am )
+inline static UChar rexAMode_M__wrk ( UInt gregEnc3210, AMD64AMode* am )
{
if (am->tag == Aam_IR) {
UChar W = 1; /* we want 64-bit mode */
- UChar R = iregBit3(greg);
+ UChar R = (gregEnc3210 >> 3) & 1;
UChar X = 0; /* not relevant */
- UChar B = iregBit3(am->Aam.IR.reg);
- return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ UChar B = iregEnc3(am->Aam.IR.reg);
+ return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
}
if (am->tag == Aam_IRRS) {
UChar W = 1; /* we want 64-bit mode */
- UChar R = iregBit3(greg);
- UChar X = iregBit3(am->Aam.IRRS.index);
- UChar B = iregBit3(am->Aam.IRRS.base);
- return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ UChar R = (gregEnc3210 >> 3) & 1;
+ UChar X = iregEnc3(am->Aam.IRRS.index);
+ UChar B = iregEnc3(am->Aam.IRRS.base);
+ return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
}
vassert(0);
return 0; /*NOTREACHED*/
}
+static UChar rexAMode_M ( HReg greg, AMD64AMode* am )
+{
+ return rexAMode_M__wrk(iregEnc3210(greg), am);
+}
+
+static UChar rexAMode_M_enc ( UInt gregEnc3210, AMD64AMode* am )
+{
+ vassert(gregEnc3210 < 16);
+ return rexAMode_M__wrk(gregEnc3210, am);
+}
+
+
/* Make up a REX byte, with W=1 (size=64), for a (greg,ereg) pair. */
-static UChar rexAMode_R ( HReg greg, HReg ereg )
+inline static UChar rexAMode_R__wrk ( UInt gregEnc3210, UInt eregEnc3210 )
{
UChar W = 1; /* we want 64-bit mode */
- UChar R = iregBit3(greg);
+ UChar R = (gregEnc3210 >> 3) & 1;
UChar X = 0; /* not relevant */
- UChar B = iregBit3(ereg);
- return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ UChar B = (eregEnc3210 >> 3) & 1;
+ return 0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0));
+}
+
+static UChar rexAMode_R ( HReg greg, HReg ereg )
+{
+ return rexAMode_R__wrk(iregEnc3210(greg), iregEnc3210(ereg));
+}
+
+static UChar rexAMode_R_enc_reg ( UInt gregEnc3210, HReg ereg )
+{
+ vassert(gregEnc3210 < 16);
+ return rexAMode_R__wrk(gregEnc3210, iregEnc3210(ereg));
+}
+
+static UChar rexAMode_R_reg_enc ( HReg greg, UInt eregEnc3210 )
+{
+ vassert(eregEnc3210 < 16);
+ return rexAMode_R__wrk(iregEnc3210(greg), eregEnc3210);
+}
+
+static UChar rexAMode_R_enc_enc ( UInt gregEnc3210, UInt eregEnc3210 )
+{
+ vassert((gregEnc3210|eregEnc3210) < 16);
+ return rexAMode_R__wrk(gregEnc3210, eregEnc3210);
}
//uu UChar rexB = 0;
//uu /* Same logic as in rexAMode_M. */
//uu if (am->tag == Aam_IR) {
-//uu rexR = iregBit3(greg);
+//uu rexR = iregEnc3(greg);
//uu rexX = 0; /* not relevant */
-//uu rexB = iregBit3(am->Aam.IR.reg);
+//uu rexB = iregEnc3(am->Aam.IR.reg);
//uu }
//uu else if (am->tag == Aam_IRRS) {
-//uu rexR = iregBit3(greg);
-//uu rexX = iregBit3(am->Aam.IRRS.index);
-//uu rexB = iregBit3(am->Aam.IRRS.base);
+//uu rexR = iregEnc3(greg);
+//uu rexX = iregEnc3(am->Aam.IRRS.index);
+//uu rexB = iregEnc3(am->Aam.IRRS.base);
//uu } else {
//uu vassert(0);
//uu }
vassert(nbuf >= 32);
vassert(mode64 == True);
- /* Wrap an integer as a int register, for use assembling
- GrpN insns, in which the greg field is used as a sub-opcode
- and does not really contain a register. */
-# define fake(_n) mkHReg((_n), HRcInt64, False)
-
/* vex_printf("asm "); ppAMD64Instr(i, mode64); vex_printf("\n"); */
switch (i->tag) {
widening rule) for constants under 1 million. We could
use this form for the range 0 to 0x7FFFFFFF inclusive, but
limit it to a smaller range for verifiability purposes. */
- if (1 & iregBit3(i->Ain.Imm64.dst))
+ if (1 & iregEnc3(i->Ain.Imm64.dst))
*p++ = 0x41;
- *p++ = 0xB8 + iregBits210(i->Ain.Imm64.dst);
+ *p++ = 0xB8 + iregEnc210(i->Ain.Imm64.dst);
p = emit32(p, (UInt)i->Ain.Imm64.imm64);
} else {
- *p++ = toUChar(0x48 + (1 & iregBit3(i->Ain.Imm64.dst)));
- *p++ = toUChar(0xB8 + iregBits210(i->Ain.Imm64.dst));
+ *p++ = toUChar(0x48 + (1 & iregEnc3(i->Ain.Imm64.dst)));
+ *p++ = toUChar(0xB8 + iregEnc210(i->Ain.Imm64.dst));
p = emit64(p, i->Ain.Imm64.imm64);
}
goto done;
of the dst to be zeroed out too. This saves 1
and sometimes 2 bytes compared to the more
obvious encoding in the 'else' branch. */
- if (1 & iregBit3(i->Ain.Alu64R.dst))
+ if (1 & iregEnc3(i->Ain.Alu64R.dst))
*p++ = 0x41;
- *p++ = 0xB8 + iregBits210(i->Ain.Alu64R.dst);
+ *p++ = 0xB8 + iregEnc210(i->Ain.Alu64R.dst);
p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
} else {
- *p++ = toUChar(0x48 + (1 & iregBit3(i->Ain.Alu64R.dst)));
+ *p++ = toUChar(0x48 + (1 & iregEnc3(i->Ain.Alu64R.dst)));
*p++ = 0xC7;
- *p++ = toUChar(0xC0 + iregBits210(i->Ain.Alu64R.dst));
+ *p++ = toUChar(0xC0 + iregEnc210(i->Ain.Alu64R.dst));
p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
}
goto done;
p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
} else
if (fits8bits(i->Ain.Alu64R.src->Armi.Imm.imm32)) {
- *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst );
+ *p++ = rexAMode_R_enc_reg( 0, i->Ain.Alu64R.dst );
*p++ = 0x83;
- p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu64R.dst);
*p++ = toUChar(0xFF & i->Ain.Alu64R.src->Armi.Imm.imm32);
} else {
- *p++ = rexAMode_R( fake(0), i->Ain.Alu64R.dst);
+ *p++ = rexAMode_R_enc_reg( 0, i->Ain.Alu64R.dst);
*p++ = 0x81;
- p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu64R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu64R.dst);
p = emit32(p, i->Ain.Alu64R.src->Armi.Imm.imm32);
}
goto done;
i->Ain.Alu64M.dst);
goto done;
case Ari_Imm:
- *p++ = rexAMode_M(fake(0), i->Ain.Alu64M.dst);
+ *p++ = rexAMode_M_enc(0, i->Ain.Alu64M.dst);
*p++ = 0xC7;
- p = doAMode_M(p, fake(0), i->Ain.Alu64M.dst);
+ p = doAMode_M_enc(p, 0, i->Ain.Alu64M.dst);
p = emit32(p, i->Ain.Alu64M.src->Ari.Imm.imm32);
goto done;
default:
default: goto bad;
}
if (i->Ain.Sh64.src == 0) {
- *p++ = rexAMode_R(fake(0), i->Ain.Sh64.dst);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Sh64.dst);
*p++ = toUChar(opc_cl);
- p = doAMode_R(p, fake(subopc), i->Ain.Sh64.dst);
+ p = doAMode_R_enc_reg(p, subopc, i->Ain.Sh64.dst);
goto done;
} else {
- *p++ = rexAMode_R(fake(0), i->Ain.Sh64.dst);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Sh64.dst);
*p++ = toUChar(opc_imm);
- p = doAMode_R(p, fake(subopc), i->Ain.Sh64.dst);
+ p = doAMode_R_enc_reg(p, subopc, i->Ain.Sh64.dst);
*p++ = (UChar)(i->Ain.Sh64.src);
goto done;
}
case Ain_Test64:
/* testq sign-extend($imm32), %reg */
- *p++ = rexAMode_R(fake(0), i->Ain.Test64.dst);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Test64.dst);
*p++ = 0xF7;
- p = doAMode_R(p, fake(0), i->Ain.Test64.dst);
+ p = doAMode_R_enc_reg(p, 0, i->Ain.Test64.dst);
p = emit32(p, i->Ain.Test64.imm32);
goto done;
case Ain_Unary64:
if (i->Ain.Unary64.op == Aun_NOT) {
- *p++ = rexAMode_R(fake(0), i->Ain.Unary64.dst);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Unary64.dst);
*p++ = 0xF7;
- p = doAMode_R(p, fake(2), i->Ain.Unary64.dst);
+ p = doAMode_R_enc_reg(p, 2, i->Ain.Unary64.dst);
goto done;
}
if (i->Ain.Unary64.op == Aun_NEG) {
- *p++ = rexAMode_R(fake(0), i->Ain.Unary64.dst);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Unary64.dst);
*p++ = 0xF7;
- p = doAMode_R(p, fake(3), i->Ain.Unary64.dst);
+ p = doAMode_R_enc_reg(p, 3, i->Ain.Unary64.dst);
goto done;
}
break;
p = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
} else
if (fits8bits(i->Ain.Alu32R.src->Armi.Imm.imm32)) {
- rex = clearWBit( rexAMode_R( fake(0), i->Ain.Alu32R.dst ) );
+ rex = clearWBit( rexAMode_R_enc_reg( 0, i->Ain.Alu32R.dst ) );
if (rex != 0x40) *p++ = rex;
*p++ = 0x83;
- p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu32R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu32R.dst);
*p++ = toUChar(0xFF & i->Ain.Alu32R.src->Armi.Imm.imm32);
} else {
- rex = clearWBit( rexAMode_R( fake(0), i->Ain.Alu32R.dst) );
+ rex = clearWBit( rexAMode_R_enc_reg( 0, i->Ain.Alu32R.dst) );
if (rex != 0x40) *p++ = rex;
*p++ = 0x81;
- p = doAMode_R(p, fake(subopc_imm), i->Ain.Alu32R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Ain.Alu32R.dst);
p = emit32(p, i->Ain.Alu32R.src->Armi.Imm.imm32);
}
goto done;
subopc = i->Ain.MulL.syned ? 5 : 4;
switch (i->Ain.MulL.src->tag) {
case Arm_Mem:
- *p++ = rexAMode_M( fake(0),
- i->Ain.MulL.src->Arm.Mem.am);
+ *p++ = rexAMode_M_enc(0, i->Ain.MulL.src->Arm.Mem.am);
*p++ = 0xF7;
- p = doAMode_M(p, fake(subopc),
- i->Ain.MulL.src->Arm.Mem.am);
+ p = doAMode_M_enc(p, subopc, i->Ain.MulL.src->Arm.Mem.am);
goto done;
case Arm_Reg:
- *p++ = rexAMode_R(fake(0),
- i->Ain.MulL.src->Arm.Reg.reg);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.MulL.src->Arm.Reg.reg);
*p++ = 0xF7;
- p = doAMode_R(p, fake(subopc),
- i->Ain.MulL.src->Arm.Reg.reg);
+ p = doAMode_R_enc_reg(p, subopc, i->Ain.MulL.src->Arm.Reg.reg);
goto done;
default:
goto bad;
goto bad;
/*FIXME*/
*p++ = 0xF7;
- p = doAMode_M(p, fake(subopc),
- i->Ain.Div.src->Arm.Mem.am);
+ p = doAMode_M_enc(p, subopc, i->Ain.Div.src->Arm.Mem.am);
goto done;
case Arm_Reg:
*p++ = clearWBit(
- rexAMode_R( fake(0), i->Ain.Div.src->Arm.Reg.reg));
+ rexAMode_R_enc_reg(0, i->Ain.Div.src->Arm.Reg.reg));
*p++ = 0xF7;
- p = doAMode_R(p, fake(subopc),
- i->Ain.Div.src->Arm.Reg.reg);
+ p = doAMode_R_enc_reg(p, subopc, i->Ain.Div.src->Arm.Reg.reg);
goto done;
default:
goto bad;
if (i->Ain.Div.sz == 8) {
switch (i->Ain.Div.src->tag) {
case Arm_Mem:
- *p++ = rexAMode_M( fake(0),
- i->Ain.Div.src->Arm.Mem.am);
+ *p++ = rexAMode_M_enc(0, i->Ain.Div.src->Arm.Mem.am);
*p++ = 0xF7;
- p = doAMode_M(p, fake(subopc),
- i->Ain.Div.src->Arm.Mem.am);
+ p = doAMode_M_enc(p, subopc, i->Ain.Div.src->Arm.Mem.am);
goto done;
case Arm_Reg:
- *p++ = rexAMode_R( fake(0),
- i->Ain.Div.src->Arm.Reg.reg);
+ *p++ = rexAMode_R_enc_reg(0, i->Ain.Div.src->Arm.Reg.reg);
*p++ = 0xF7;
- p = doAMode_R(p, fake(subopc),
- i->Ain.Div.src->Arm.Reg.reg);
+ p = doAMode_R_enc_reg(p, subopc, i->Ain.Div.src->Arm.Reg.reg);
goto done;
default:
goto bad;
switch (i->Ain.Push.src->tag) {
case Armi_Mem:
*p++ = clearWBit(
- rexAMode_M(fake(0), i->Ain.Push.src->Armi.Mem.am));
+ rexAMode_M_enc(0, i->Ain.Push.src->Armi.Mem.am));
*p++ = 0xFF;
- p = doAMode_M(p, fake(6), i->Ain.Push.src->Armi.Mem.am);
+ p = doAMode_M_enc(p, 6, i->Ain.Push.src->Armi.Mem.am);
goto done;
case Armi_Imm:
*p++ = 0x68;
p = emit32(p, i->Ain.Push.src->Armi.Imm.imm32);
goto done;
case Armi_Reg:
- *p++ = toUChar(0x40 + (1 & iregBit3(i->Ain.Push.src->Armi.Reg.reg)));
- *p++ = toUChar(0x50 + iregBits210(i->Ain.Push.src->Armi.Reg.reg));
+ *p++ = toUChar(0x40 + (1 & iregEnc3(i->Ain.Push.src->Armi.Reg.reg)));
+ *p++ = toUChar(0x50 + iregEnc210(i->Ain.Push.src->Armi.Reg.reg));
goto done;
default:
goto bad;
of the destination should be forced to zero, but doing 'xorq
%r,%r' kills the flag(s) we are about to read. Sigh. So
start off my moving $0 into the dest. */
- reg = iregBits3210(i->Ain.Set64.dst);
+ reg = iregEnc3210(i->Ain.Set64.dst);
vassert(reg < 16);
/* movq $0, %dst */
/* cmpxchg{8,16}b m{64,128}. Expected-value in %rdx:%rax, new
value in %rcx:%rbx. All 4 regs are hardwired in the ISA, so
aren't encoded in the insn. */
- rex = rexAMode_M( fake(1), i->Ain.ACAS.addr );
+ rex = rexAMode_M_enc(1, i->Ain.ACAS.addr );
if (i->Ain.ACAS.sz != 8)
rex = clearWBit(rex);
*p++ = rex;
*p++ = 0x0F;
*p++ = 0xC7;
- p = doAMode_M(p, fake(1), i->Ain.DACAS.addr);
+ p = doAMode_M_enc(p, 1, i->Ain.DACAS.addr);
goto done;
case Ain_A87Free:
if (i->Ain.A87PushPop.isPush) {
/* Load from memory into %st(0): flds/fldl amode */
*p++ = clearWBit(
- rexAMode_M(fake(0), i->Ain.A87PushPop.addr) );
+ rexAMode_M_enc(0, i->Ain.A87PushPop.addr) );
*p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
- p = doAMode_M(p, fake(0)/*subopcode*/, i->Ain.A87PushPop.addr);
+ p = doAMode_M_enc(p, 0/*subopcode*/, i->Ain.A87PushPop.addr);
} else {
/* Dump %st(0) to memory: fstps/fstpl amode */
*p++ = clearWBit(
- rexAMode_M(fake(3), i->Ain.A87PushPop.addr) );
+ rexAMode_M_enc(3, i->Ain.A87PushPop.addr) );
*p++ = i->Ain.A87PushPop.szB == 4 ? 0xD9 : 0xDD;
- p = doAMode_M(p, fake(3)/*subopcode*/, i->Ain.A87PushPop.addr);
+ p = doAMode_M_enc(p, 3/*subopcode*/, i->Ain.A87PushPop.addr);
goto done;
}
goto done;
case Ain_A87LdCW:
*p++ = clearWBit(
- rexAMode_M(fake(5), i->Ain.A87LdCW.addr) );
+ rexAMode_M_enc(5, i->Ain.A87LdCW.addr) );
*p++ = 0xD9;
- p = doAMode_M(p, fake(5)/*subopcode*/, i->Ain.A87LdCW.addr);
+ p = doAMode_M_enc(p, 5/*subopcode*/, i->Ain.A87LdCW.addr);
goto done;
case Ain_A87StSW:
*p++ = clearWBit(
- rexAMode_M(fake(7), i->Ain.A87StSW.addr) );
+ rexAMode_M_enc(7, i->Ain.A87StSW.addr) );
*p++ = 0xDD;
- p = doAMode_M(p, fake(7)/*subopcode*/, i->Ain.A87StSW.addr);
+ p = doAMode_M_enc(p, 7/*subopcode*/, i->Ain.A87StSW.addr);
goto done;
case Ain_Store:
break;
case Ain_LdMXCSR:
- *p++ = clearWBit(rexAMode_M( fake(0), i->Ain.LdMXCSR.addr));
+ *p++ = clearWBit(rexAMode_M_enc(0, i->Ain.LdMXCSR.addr));
*p++ = 0x0F;
*p++ = 0xAE;
- p = doAMode_M(p, fake(2)/*subopcode*/, i->Ain.LdMXCSR.addr);
+ p = doAMode_M_enc(p, 2/*subopcode*/, i->Ain.LdMXCSR.addr);
goto done;
case Ain_SseUComIS:
vassert(i->Ain.SseUComIS.sz == 4);
}
*p++ = clearWBit (
- rexAMode_R( vreg2ireg(i->Ain.SseUComIS.srcL),
- vreg2ireg(i->Ain.SseUComIS.srcR) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseUComIS.srcL),
+ vregEnc3210(i->Ain.SseUComIS.srcR) ));
*p++ = 0x0F;
*p++ = 0x2E;
- p = doAMode_R(p, vreg2ireg(i->Ain.SseUComIS.srcL),
- vreg2ireg(i->Ain.SseUComIS.srcR) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseUComIS.srcL),
+ vregEnc3210(i->Ain.SseUComIS.srcR) );
/* pushfq */
*p++ = 0x9C;
/* popq %dst */
- *p++ = toUChar(0x40 + (1 & iregBit3(i->Ain.SseUComIS.dst)));
- *p++ = toUChar(0x58 + iregBits210(i->Ain.SseUComIS.dst));
+ *p++ = toUChar(0x40 + (1 & iregEnc3(i->Ain.SseUComIS.dst)));
+ *p++ = toUChar(0x58 + iregEnc210(i->Ain.SseUComIS.dst));
goto done;
case Ain_SseSI2SF:
/* cvssi2s[sd] %src, %dst */
- rex = rexAMode_R( vreg2ireg(i->Ain.SseSI2SF.dst),
- i->Ain.SseSI2SF.src );
+ rex = rexAMode_R_enc_reg( vregEnc3210(i->Ain.SseSI2SF.dst),
+ i->Ain.SseSI2SF.src );
*p++ = toUChar(i->Ain.SseSI2SF.szD==4 ? 0xF3 : 0xF2);
*p++ = toUChar(i->Ain.SseSI2SF.szS==4 ? clearWBit(rex) : rex);
*p++ = 0x0F;
*p++ = 0x2A;
- p = doAMode_R( p, vreg2ireg(i->Ain.SseSI2SF.dst),
- i->Ain.SseSI2SF.src );
+ p = doAMode_R_enc_reg( p, vregEnc3210(i->Ain.SseSI2SF.dst),
+ i->Ain.SseSI2SF.src );
goto done;
case Ain_SseSF2SI:
/* cvss[sd]2si %src, %dst */
- rex = rexAMode_R( i->Ain.SseSF2SI.dst,
- vreg2ireg(i->Ain.SseSF2SI.src) );
+ rex = rexAMode_R_reg_enc( i->Ain.SseSF2SI.dst,
+ vregEnc3210(i->Ain.SseSF2SI.src) );
*p++ = toUChar(i->Ain.SseSF2SI.szS==4 ? 0xF3 : 0xF2);
*p++ = toUChar(i->Ain.SseSF2SI.szD==4 ? clearWBit(rex) : rex);
*p++ = 0x0F;
*p++ = 0x2D;
- p = doAMode_R( p, i->Ain.SseSF2SI.dst,
- vreg2ireg(i->Ain.SseSF2SI.src) );
+ p = doAMode_R_reg_enc( p, i->Ain.SseSF2SI.dst,
+ vregEnc3210(i->Ain.SseSF2SI.src) );
goto done;
case Ain_SseSDSS:
/* cvtsd2ss/cvtss2sd %src, %dst */
*p++ = toUChar(i->Ain.SseSDSS.from64 ? 0xF2 : 0xF3);
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.SseSDSS.dst),
- vreg2ireg(i->Ain.SseSDSS.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseSDSS.dst),
+ vregEnc3210(i->Ain.SseSDSS.src) ));
*p++ = 0x0F;
*p++ = 0x5A;
- p = doAMode_R( p, vreg2ireg(i->Ain.SseSDSS.dst),
- vreg2ireg(i->Ain.SseSDSS.src) );
+ p = doAMode_R_enc_enc( p, vregEnc3210(i->Ain.SseSDSS.dst),
+ vregEnc3210(i->Ain.SseSDSS.src) );
goto done;
case Ain_SseLdSt:
vassert(0);
}
*p++ = clearWBit(
- rexAMode_M( vreg2ireg(i->Ain.SseLdSt.reg), i->Ain.SseLdSt.addr));
+ rexAMode_M_enc(vregEnc3210(i->Ain.SseLdSt.reg),
+ i->Ain.SseLdSt.addr));
*p++ = 0x0F;
*p++ = toUChar(i->Ain.SseLdSt.isLoad ? 0x10 : 0x11);
- p = doAMode_M(p, vreg2ireg(i->Ain.SseLdSt.reg), i->Ain.SseLdSt.addr);
+ p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseLdSt.reg),
+ i->Ain.SseLdSt.addr);
goto done;
case Ain_SseLdzLO:
/* movs[sd] amode, %xmm-dst */
*p++ = toUChar(i->Ain.SseLdzLO.sz==4 ? 0xF3 : 0xF2);
*p++ = clearWBit(
- rexAMode_M(vreg2ireg(i->Ain.SseLdzLO.reg),
- i->Ain.SseLdzLO.addr));
+ rexAMode_M_enc(vregEnc3210(i->Ain.SseLdzLO.reg),
+ i->Ain.SseLdzLO.addr));
*p++ = 0x0F;
*p++ = 0x10;
- p = doAMode_M(p, vreg2ireg(i->Ain.SseLdzLO.reg),
- i->Ain.SseLdzLO.addr);
+ p = doAMode_M_enc(p, vregEnc3210(i->Ain.SseLdzLO.reg),
+ i->Ain.SseLdzLO.addr);
goto done;
case Ain_Sse32Fx4:
xtra = 0;
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.Sse32Fx4.dst),
- vreg2ireg(i->Ain.Sse32Fx4.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse32Fx4.dst),
+ vregEnc3210(i->Ain.Sse32Fx4.src) ));
*p++ = 0x0F;
switch (i->Ain.Sse32Fx4.op) {
case Asse_ADDF: *p++ = 0x58; break;
case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, vreg2ireg(i->Ain.Sse32Fx4.dst),
- vreg2ireg(i->Ain.Sse32Fx4.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse32Fx4.dst),
+ vregEnc3210(i->Ain.Sse32Fx4.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
xtra = 0;
*p++ = 0x66;
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.Sse64Fx2.dst),
- vreg2ireg(i->Ain.Sse64Fx2.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse64Fx2.dst),
+ vregEnc3210(i->Ain.Sse64Fx2.src) ));
*p++ = 0x0F;
switch (i->Ain.Sse64Fx2.op) {
case Asse_ADDF: *p++ = 0x58; break;
case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, vreg2ireg(i->Ain.Sse64Fx2.dst),
- vreg2ireg(i->Ain.Sse64Fx2.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse64Fx2.dst),
+ vregEnc3210(i->Ain.Sse64Fx2.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
xtra = 0;
*p++ = 0xF3;
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.Sse32FLo.dst),
- vreg2ireg(i->Ain.Sse32FLo.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse32FLo.dst),
+ vregEnc3210(i->Ain.Sse32FLo.src) ));
*p++ = 0x0F;
switch (i->Ain.Sse32FLo.op) {
case Asse_ADDF: *p++ = 0x58; break;
case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, vreg2ireg(i->Ain.Sse32FLo.dst),
- vreg2ireg(i->Ain.Sse32FLo.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse32FLo.dst),
+ vregEnc3210(i->Ain.Sse32FLo.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
xtra = 0;
*p++ = 0xF2;
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.Sse64FLo.dst),
- vreg2ireg(i->Ain.Sse64FLo.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.Sse64FLo.dst),
+ vregEnc3210(i->Ain.Sse64FLo.src) ));
*p++ = 0x0F;
switch (i->Ain.Sse64FLo.op) {
case Asse_ADDF: *p++ = 0x58; break;
case Asse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, vreg2ireg(i->Ain.Sse64FLo.dst),
- vreg2ireg(i->Ain.Sse64FLo.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.Sse64FLo.dst),
+ vregEnc3210(i->Ain.Sse64FLo.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
# define XX(_n) *p++ = (_n)
rex = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.SseReRg.dst),
- vreg2ireg(i->Ain.SseReRg.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseReRg.dst),
+ vregEnc3210(i->Ain.SseReRg.src) ));
switch (i->Ain.SseReRg.op) {
case Asse_MOV: /*movups*/ XX(rex); XX(0x0F); XX(0x10); break;
case Asse_UNPCKLQ: XX(0x66); XX(rex); XX(0x0F); XX(0x6C); break;
default: goto bad;
}
- p = doAMode_R(p, vreg2ireg(i->Ain.SseReRg.dst),
- vreg2ireg(i->Ain.SseReRg.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseReRg.dst),
+ vregEnc3210(i->Ain.SseReRg.src) );
# undef XX
goto done;
/* movaps %src, %dst */
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.SseCMov.dst),
- vreg2ireg(i->Ain.SseCMov.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseCMov.dst),
+ vregEnc3210(i->Ain.SseCMov.src) ));
*p++ = 0x0F;
*p++ = 0x28;
- p = doAMode_R(p, vreg2ireg(i->Ain.SseCMov.dst),
- vreg2ireg(i->Ain.SseCMov.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseCMov.dst),
+ vregEnc3210(i->Ain.SseCMov.src) );
/* Fill in the jump offset. */
*(ptmp-1) = toUChar(p - ptmp);
case Ain_SseShuf:
*p++ = 0x66;
*p++ = clearWBit(
- rexAMode_R( vreg2ireg(i->Ain.SseShuf.dst),
- vreg2ireg(i->Ain.SseShuf.src) ));
+ rexAMode_R_enc_enc( vregEnc3210(i->Ain.SseShuf.dst),
+ vregEnc3210(i->Ain.SseShuf.src) ));
*p++ = 0x0F;
*p++ = 0x70;
- p = doAMode_R(p, vreg2ireg(i->Ain.SseShuf.dst),
- vreg2ireg(i->Ain.SseShuf.src) );
+ p = doAMode_R_enc_enc(p, vregEnc3210(i->Ain.SseShuf.dst),
+ vregEnc3210(i->Ain.SseShuf.src) );
*p++ = (UChar)(i->Ain.SseShuf.order);
goto done;
/* --- decl 8(%rbp) --- */
/* Need to compute the REX byte for the decl in order to prove
that we don't need it, since this is a 32-bit inc and all
- registers involved in the amode are < r8. "fake(1)" because
+ registers involved in the amode are < r8. "1" because
there's no register in this encoding; instead the register
field is used as a sub opcode. The encoding for "decl r/m32"
- is FF /1, hence the fake(1). */
- rex = clearWBit(rexAMode_M(fake(1), i->Ain.EvCheck.amCounter));
+ is FF /1, hence the "1". */
+ rex = clearWBit(rexAMode_M_enc(1, i->Ain.EvCheck.amCounter));
if (rex != 0x40) goto bad; /* We don't expect to need the REX byte. */
*p++ = 0xFF;
- p = doAMode_M(p, fake(1), i->Ain.EvCheck.amCounter);
+ p = doAMode_M_enc(p, 1, i->Ain.EvCheck.amCounter);
vassert(p - p0 == 3);
/* --- jns nofail --- */
*p++ = 0x79;
/* Once again, verify we don't need REX. The encoding is FF /4.
We don't need REX.W since by default FF /4 in 64-bit mode
implies a 64 bit load. */
- rex = clearWBit(rexAMode_M(fake(4), i->Ain.EvCheck.amFailAddr));
+ rex = clearWBit(rexAMode_M_enc(4, i->Ain.EvCheck.amFailAddr));
if (rex != 0x40) goto bad;
*p++ = 0xFF;
- p = doAMode_M(p, fake(4), i->Ain.EvCheck.amFailAddr);
+ p = doAMode_M_enc(p, 4, i->Ain.EvCheck.amFailAddr);
vassert(p - p0 == 8); /* also ensures that 0x03 offset above is ok */
/* And crosscheck .. */
vassert(evCheckSzB_AMD64() == 8);
done:
vassert(p - &buf[0] <= 32);
return p - &buf[0];
-
-# undef fake
}
float regs, and 16 real vector regs.
*/
-extern void ppHRegAMD64 ( HReg );
+#define ST_IN static inline
+ST_IN HReg hregAMD64_RSI ( void ) { return mkHReg(False, HRcInt64, 6, 0); }
+ST_IN HReg hregAMD64_RDI ( void ) { return mkHReg(False, HRcInt64, 7, 1); }
+ST_IN HReg hregAMD64_R8 ( void ) { return mkHReg(False, HRcInt64, 8, 2); }
+ST_IN HReg hregAMD64_R9 ( void ) { return mkHReg(False, HRcInt64, 9, 3); }
+ST_IN HReg hregAMD64_R12 ( void ) { return mkHReg(False, HRcInt64, 12, 4); }
+ST_IN HReg hregAMD64_R13 ( void ) { return mkHReg(False, HRcInt64, 13, 5); }
+ST_IN HReg hregAMD64_R14 ( void ) { return mkHReg(False, HRcInt64, 14, 6); }
+ST_IN HReg hregAMD64_R15 ( void ) { return mkHReg(False, HRcInt64, 15, 7); }
+ST_IN HReg hregAMD64_RBX ( void ) { return mkHReg(False, HRcInt64, 3, 8); }
+
+ST_IN HReg hregAMD64_XMM3 ( void ) { return mkHReg(False, HRcVec128, 3, 9); }
+ST_IN HReg hregAMD64_XMM4 ( void ) { return mkHReg(False, HRcVec128, 4, 10); }
+ST_IN HReg hregAMD64_XMM5 ( void ) { return mkHReg(False, HRcVec128, 5, 11); }
+ST_IN HReg hregAMD64_XMM6 ( void ) { return mkHReg(False, HRcVec128, 6, 12); }
+ST_IN HReg hregAMD64_XMM7 ( void ) { return mkHReg(False, HRcVec128, 7, 13); }
+ST_IN HReg hregAMD64_XMM8 ( void ) { return mkHReg(False, HRcVec128, 8, 14); }
+ST_IN HReg hregAMD64_XMM9 ( void ) { return mkHReg(False, HRcVec128, 9, 15); }
+ST_IN HReg hregAMD64_XMM10 ( void ) { return mkHReg(False, HRcVec128, 10, 16); }
+ST_IN HReg hregAMD64_XMM11 ( void ) { return mkHReg(False, HRcVec128, 11, 17); }
+ST_IN HReg hregAMD64_XMM12 ( void ) { return mkHReg(False, HRcVec128, 12, 18); }
+
+ST_IN HReg hregAMD64_R10 ( void ) { return mkHReg(False, HRcInt64, 10, 19); }
+
+ST_IN HReg hregAMD64_RAX ( void ) { return mkHReg(False, HRcInt64, 0, 20); }
+ST_IN HReg hregAMD64_RCX ( void ) { return mkHReg(False, HRcInt64, 1, 21); }
+ST_IN HReg hregAMD64_RDX ( void ) { return mkHReg(False, HRcInt64, 2, 22); }
+ST_IN HReg hregAMD64_RSP ( void ) { return mkHReg(False, HRcInt64, 4, 23); }
+ST_IN HReg hregAMD64_RBP ( void ) { return mkHReg(False, HRcInt64, 5, 24); }
+ST_IN HReg hregAMD64_R11 ( void ) { return mkHReg(False, HRcInt64, 11, 25); }
+
+ST_IN HReg hregAMD64_XMM0 ( void ) { return mkHReg(False, HRcVec128, 0, 26); }
+ST_IN HReg hregAMD64_XMM1 ( void ) { return mkHReg(False, HRcVec128, 1, 27); }
+#undef ST_IN
-extern HReg hregAMD64_RAX ( void );
-extern HReg hregAMD64_RBX ( void );
-extern HReg hregAMD64_RCX ( void );
-extern HReg hregAMD64_RDX ( void );
-extern HReg hregAMD64_RSP ( void );
-extern HReg hregAMD64_RBP ( void );
-extern HReg hregAMD64_RSI ( void );
-extern HReg hregAMD64_RDI ( void );
-extern HReg hregAMD64_R8 ( void );
-extern HReg hregAMD64_R9 ( void );
-extern HReg hregAMD64_R10 ( void );
-extern HReg hregAMD64_R11 ( void );
-extern HReg hregAMD64_R12 ( void );
-extern HReg hregAMD64_R13 ( void );
-extern HReg hregAMD64_R14 ( void );
-extern HReg hregAMD64_R15 ( void );
-
-extern HReg hregAMD64_FAKE0 ( void );
-extern HReg hregAMD64_FAKE1 ( void );
-extern HReg hregAMD64_FAKE2 ( void );
-extern HReg hregAMD64_FAKE3 ( void );
-extern HReg hregAMD64_FAKE4 ( void );
-extern HReg hregAMD64_FAKE5 ( void );
-
-extern HReg hregAMD64_XMM0 ( void );
-extern HReg hregAMD64_XMM1 ( void );
-extern HReg hregAMD64_XMM3 ( void );
-extern HReg hregAMD64_XMM4 ( void );
-extern HReg hregAMD64_XMM5 ( void );
-extern HReg hregAMD64_XMM6 ( void );
-extern HReg hregAMD64_XMM7 ( void );
-extern HReg hregAMD64_XMM8 ( void );
-extern HReg hregAMD64_XMM9 ( void );
-extern HReg hregAMD64_XMM10 ( void );
-extern HReg hregAMD64_XMM11 ( void );
-extern HReg hregAMD64_XMM12 ( void );
+extern void ppHRegAMD64 ( HReg );
/* --------- Condition codes, AMD encoding. --------- */
extern void genReload_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
-extern void getAllocableRegs_AMD64 ( Int*, HReg** );
+extern const RRegUniverse* getRRegUniverse_AMD64 ( void );
+
extern HInstrArray* iselSB_AMD64 ( const IRSB*,
VexArch,
const VexArchInfo*,
static HReg newVRegI ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcInt64, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegV ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
switch (bb->tyenv->types[i]) {
case Ity_I1:
case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
- hreg = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
break;
case Ity_I128:
- hreg = mkHReg(j++, HRcInt64, True);
- hregHI = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
+ hregHI = mkHReg(True, HRcInt64, 0, j++);
break;
case Ity_F32:
case Ity_F64:
case Ity_V128:
- hreg = mkHReg(j++, HRcVec128, True);
+ hreg = mkHReg(True, HRcVec128, 0, j++);
break;
case Ity_V256:
- hreg = mkHReg(j++, HRcVec128, True);
- hregHI = mkHReg(j++, HRcVec128, True);
+ hreg = mkHReg(True, HRcVec128, 0, j++);
+ hregHI = mkHReg(True, HRcVec128, 0, j++);
break;
default:
ppIRType(bb->tyenv->types[i]);
#include "host_generic_regs.h"
#include "host_arm64_defs.h"
-//ZZ UInt arm_hwcaps = 0;
-
/* --------- Registers. --------- */
Q regs (128 bit vector)
*/
-void ppHRegARM64 ( HReg reg ) {
- Int r;
- /* Be generic for all virtual regs. */
- if (hregIsVirtual(reg)) {
- ppHReg(reg);
- return;
- }
- /* But specific for real regs. */
- switch (hregClass(reg)) {
- case HRcInt64:
- r = hregNumber(reg);
- vassert(r >= 0 && r < 31);
- vex_printf("x%d", r);
- return;
- case HRcFlt64:
- r = hregNumber(reg);
- vassert(r >= 0 && r < 32);
- vex_printf("d%d", r);
- return;
- case HRcVec128:
- r = hregNumber(reg);
- vassert(r >= 0 && r < 32);
- vex_printf("q%d", r);
- return;
- default:
- vpanic("ppHRegARM64");
- }
-}
-
-static void ppHRegARM64asSreg ( HReg reg ) {
- ppHRegARM64(reg);
- vex_printf("(S-reg)");
-}
-
-HReg hregARM64_X0 ( void ) { return mkHReg(0, HRcInt64, False); }
-HReg hregARM64_X1 ( void ) { return mkHReg(1, HRcInt64, False); }
-HReg hregARM64_X2 ( void ) { return mkHReg(2, HRcInt64, False); }
-HReg hregARM64_X3 ( void ) { return mkHReg(3, HRcInt64, False); }
-HReg hregARM64_X4 ( void ) { return mkHReg(4, HRcInt64, False); }
-HReg hregARM64_X5 ( void ) { return mkHReg(5, HRcInt64, False); }
-HReg hregARM64_X6 ( void ) { return mkHReg(6, HRcInt64, False); }
-HReg hregARM64_X7 ( void ) { return mkHReg(7, HRcInt64, False); }
-HReg hregARM64_X8 ( void ) { return mkHReg(8, HRcInt64, False); }
-HReg hregARM64_X9 ( void ) { return mkHReg(9, HRcInt64, False); }
-HReg hregARM64_X10 ( void ) { return mkHReg(10, HRcInt64, False); }
-HReg hregARM64_X11 ( void ) { return mkHReg(11, HRcInt64, False); }
-HReg hregARM64_X12 ( void ) { return mkHReg(12, HRcInt64, False); }
-HReg hregARM64_X13 ( void ) { return mkHReg(13, HRcInt64, False); }
-HReg hregARM64_X14 ( void ) { return mkHReg(14, HRcInt64, False); }
-HReg hregARM64_X15 ( void ) { return mkHReg(15, HRcInt64, False); }
-HReg hregARM64_X21 ( void ) { return mkHReg(21, HRcInt64, False); }
-HReg hregARM64_X22 ( void ) { return mkHReg(22, HRcInt64, False); }
-HReg hregARM64_X23 ( void ) { return mkHReg(23, HRcInt64, False); }
-HReg hregARM64_X24 ( void ) { return mkHReg(24, HRcInt64, False); }
-HReg hregARM64_X25 ( void ) { return mkHReg(25, HRcInt64, False); }
-HReg hregARM64_X26 ( void ) { return mkHReg(26, HRcInt64, False); }
-HReg hregARM64_X27 ( void ) { return mkHReg(27, HRcInt64, False); }
-HReg hregARM64_X28 ( void ) { return mkHReg(28, HRcInt64, False); }
-
-// Should really use D8 .. D15 for class F64, since they are callee
-// save
-HReg hregARM64_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
-HReg hregARM64_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
-HReg hregARM64_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
-HReg hregARM64_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
-HReg hregARM64_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
-HReg hregARM64_D13 ( void ) { return mkHReg(13, HRcFlt64, False); }
-HReg hregARM64_Q16 ( void ) { return mkHReg(16, HRcVec128, False); }
-HReg hregARM64_Q17 ( void ) { return mkHReg(17, HRcVec128, False); }
-HReg hregARM64_Q18 ( void ) { return mkHReg(18, HRcVec128, False); }
-HReg hregARM64_Q19 ( void ) { return mkHReg(19, HRcVec128, False); }
-HReg hregARM64_Q20 ( void ) { return mkHReg(20, HRcVec128, False); }
-
-void getAllocableRegs_ARM64 ( Int* nregs, HReg** arr )
+const RRegUniverse* getRRegUniverse_ARM64 ( void )
{
- Int i = 0;
- *nregs = 26;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
-
- // callee saves ones (22 to 28) are listed first, since we prefer
- // them if they're available
- (*arr)[i++] = hregARM64_X22();
- (*arr)[i++] = hregARM64_X23();
- (*arr)[i++] = hregARM64_X24();
- (*arr)[i++] = hregARM64_X25();
- (*arr)[i++] = hregARM64_X26();
- (*arr)[i++] = hregARM64_X27();
- (*arr)[i++] = hregARM64_X28();
-
- (*arr)[i++] = hregARM64_X0();
- (*arr)[i++] = hregARM64_X1();
- (*arr)[i++] = hregARM64_X2();
- (*arr)[i++] = hregARM64_X3();
- (*arr)[i++] = hregARM64_X4();
- (*arr)[i++] = hregARM64_X5();
- (*arr)[i++] = hregARM64_X6();
- (*arr)[i++] = hregARM64_X7();
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. */
+ static RRegUniverse rRegUniverse_ARM64;
+ static Bool rRegUniverse_ARM64_initted = False;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_ARM64;
+
+ /* This isn't thread-safe. Sigh. */
+ if (LIKELY(rRegUniverse_ARM64_initted))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+
+ ru->regs[ru->size++] = hregARM64_X22();
+ ru->regs[ru->size++] = hregARM64_X23();
+ ru->regs[ru->size++] = hregARM64_X24();
+ ru->regs[ru->size++] = hregARM64_X25();
+ ru->regs[ru->size++] = hregARM64_X26();
+ ru->regs[ru->size++] = hregARM64_X27();
+ ru->regs[ru->size++] = hregARM64_X28();
+
+ ru->regs[ru->size++] = hregARM64_X0();
+ ru->regs[ru->size++] = hregARM64_X1();
+ ru->regs[ru->size++] = hregARM64_X2();
+ ru->regs[ru->size++] = hregARM64_X3();
+ ru->regs[ru->size++] = hregARM64_X4();
+ ru->regs[ru->size++] = hregARM64_X5();
+ ru->regs[ru->size++] = hregARM64_X6();
+ ru->regs[ru->size++] = hregARM64_X7();
// X8 is used as a ProfInc temporary, not available to regalloc.
// X9 is a chaining/spill temporary, not available to regalloc.
// Do we really need all these?
- //(*arr)[i++] = hregARM64_X10();
- //(*arr)[i++] = hregARM64_X11();
- //(*arr)[i++] = hregARM64_X12();
- //(*arr)[i++] = hregARM64_X13();
- //(*arr)[i++] = hregARM64_X14();
- //(*arr)[i++] = hregARM64_X15();
+ //ru->regs[ru->size++] = hregARM64_X10();
+ //ru->regs[ru->size++] = hregARM64_X11();
+ //ru->regs[ru->size++] = hregARM64_X12();
+ //ru->regs[ru->size++] = hregARM64_X13();
+ //ru->regs[ru->size++] = hregARM64_X14();
+ //ru->regs[ru->size++] = hregARM64_X15();
// X21 is the guest state pointer, not available to regalloc.
// vector regs. Unfortunately not callee-saved.
- (*arr)[i++] = hregARM64_Q16();
- (*arr)[i++] = hregARM64_Q17();
- (*arr)[i++] = hregARM64_Q18();
- (*arr)[i++] = hregARM64_Q19();
- (*arr)[i++] = hregARM64_Q20();
+ ru->regs[ru->size++] = hregARM64_Q16();
+ ru->regs[ru->size++] = hregARM64_Q17();
+ ru->regs[ru->size++] = hregARM64_Q18();
+ ru->regs[ru->size++] = hregARM64_Q19();
+ ru->regs[ru->size++] = hregARM64_Q20();
// F64 regs, all of which are callee-saved
- (*arr)[i++] = hregARM64_D8();
- (*arr)[i++] = hregARM64_D9();
- (*arr)[i++] = hregARM64_D10();
- (*arr)[i++] = hregARM64_D11();
- (*arr)[i++] = hregARM64_D12();
- (*arr)[i++] = hregARM64_D13();
+ ru->regs[ru->size++] = hregARM64_D8();
+ ru->regs[ru->size++] = hregARM64_D9();
+ ru->regs[ru->size++] = hregARM64_D10();
+ ru->regs[ru->size++] = hregARM64_D11();
+ ru->regs[ru->size++] = hregARM64_D12();
+ ru->regs[ru->size++] = hregARM64_D13();
+
+ ru->allocable = ru->size;
+ /* And other regs, not available to the allocator. */
// unavail: x21 as GSP
// x8 is used as a ProfInc temporary
// If the set of available registers changes or if the e/r status
// changes, be sure to re-check/sync the definition of
// getRegUsage for ARM64Instr_Call too.
- vassert(i == *nregs);
+
+ ru->regs[ru->size++] = hregARM64_X8();
+ ru->regs[ru->size++] = hregARM64_X9();
+ ru->regs[ru->size++] = hregARM64_X21();
+
+ rRegUniverse_ARM64_initted = True;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
+
+void ppHRegARM64 ( HReg reg ) {
+ Int r;
+ /* Be generic for all virtual regs. */
+ if (hregIsVirtual(reg)) {
+ ppHReg(reg);
+ return;
+ }
+ /* But specific for real regs. */
+ switch (hregClass(reg)) {
+ case HRcInt64:
+ r = hregEncoding(reg);
+ vassert(r >= 0 && r < 31);
+ vex_printf("x%d", r);
+ return;
+ case HRcFlt64:
+ r = hregEncoding(reg);
+ vassert(r >= 0 && r < 32);
+ vex_printf("d%d", r);
+ return;
+ case HRcVec128:
+ r = hregEncoding(reg);
+ vassert(r >= 0 && r < 32);
+ vex_printf("q%d", r);
+ return;
+ default:
+ vpanic("ppHRegARM64");
+ }
+}
+
+static void ppHRegARM64asSreg ( HReg reg ) {
+ ppHRegARM64(reg);
+ vex_printf("(S-reg)");
}
}
-//ZZ /* Emit an instruction into buf and return the number of bytes used.
-//ZZ Note that buf is not the insn's final place, and therefore it is
-//ZZ imperative to emit position-independent code. */
+/* Emit an instruction into buf and return the number of bytes used.
+ Note that buf is not the insn's final place, and therefore it is
+ imperative to emit position-independent code. */
-static inline UChar iregNo ( HReg r )
+static inline UInt iregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 30);
- return toUChar(n);
+ return n;
}
-static inline UChar dregNo ( HReg r )
+static inline UInt dregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcFlt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
- return toUChar(n);
+ return n;
}
-static inline UChar qregNo ( HReg r )
+static inline UInt qregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcVec128);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
- return toUChar(n);
+ return n;
}
#define BITS4(zzb3,zzb2,zzb1,zzb0) \
/* Get an immediate into a register, using only that register. */
-static UInt* imm64_to_iregNo ( UInt* p, Int xD, ULong imm64 )
+static UInt* imm64_to_ireg ( UInt* p, Int xD, ULong imm64 )
{
if (imm64 == 0) {
// This has to be special-cased, since the logic below
generating exactly 4 instructions, regardless of the value of the
immediate. This is used when generating sections of code that need
to be patched later, so as to guarantee a specific size. */
-static UInt* imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
+static UInt* imm64_to_ireg_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
{
UShort h[4];
h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
}
/* Check whether p points at a 4-insn sequence cooked up by
- imm64_to_iregNo_EXACTLY4(). */
-static Bool is_imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
+ imm64_to_ireg_EXACTLY4(). */
+static Bool is_imm64_to_ireg_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
{
UShort h[4];
h[3] = (UShort)((imm64 >> 48) & 0xFFFF);
vassert(-256 <= simm9 && simm9 <= 255);
UInt instr = X_2_6_3_9_2_5_5(X00, X111000, isLoad ? X010 : X000,
simm9 & 0x1FF, X00,
- iregNo(am->ARM64am.RI9.reg), wD);
+ iregEnc(am->ARM64am.RI9.reg), wD);
*p++ = instr;
return p;
}
UInt uimm12 = am->ARM64am.RI12.uimm12;
UInt scale = am->ARM64am.RI12.szB;
vassert(scale == 1); /* failure of this is serious. Do not ignore. */
- UInt xN = iregNo(am->ARM64am.RI12.reg);
+ UInt xN = iregEnc(am->ARM64am.RI12.reg);
vassert(xN <= 30);
UInt instr = X_2_6_2_12_5_5(X00, X111001, isLoad ? X01 : X00,
uimm12, xN, wD);
/* STRB Xd, [Xn|SP, Xm]: 00 111 000 001 m 011 0 10 n d
LDRB Xd, [Xn|SP, Xm]: 00 111 000 011 m 011 0 10 n d
*/
- UInt xN = iregNo(am->ARM64am.RR.base);
- UInt xM = iregNo(am->ARM64am.RR.index);
+ UInt xN = iregEnc(am->ARM64am.RR.base);
+ UInt xM = iregEnc(am->ARM64am.RR.index);
vassert(xN <= 30);
UInt instr = X_3_8_5_6_5_5(X001, isLoad ? X11000011 : X11000001,
xM, X011010, xN, wD);
vassert(-256 <= simm9 && simm9 <= 255);
UInt instr = X_2_6_3_9_2_5_5(X01, X111000, isLoad ? X010 : X000,
simm9 & 0x1FF, X00,
- iregNo(am->ARM64am.RI9.reg), wD);
+ iregEnc(am->ARM64am.RI9.reg), wD);
*p++ = instr;
return p;
}
UInt uimm12 = am->ARM64am.RI12.uimm12;
UInt scale = am->ARM64am.RI12.szB;
vassert(scale == 2); /* failure of this is serious. Do not ignore. */
- UInt xN = iregNo(am->ARM64am.RI12.reg);
+ UInt xN = iregEnc(am->ARM64am.RI12.reg);
vassert(xN <= 30);
UInt instr = X_2_6_2_12_5_5(X01, X111001, isLoad ? X01 : X00,
uimm12, xN, wD);
/* STRH Xd, [Xn|SP, Xm]: 01 111 000 001 m 011 0 10 n d
LDRH Xd, [Xn|SP, Xm]: 01 111 000 011 m 011 0 10 n d
*/
- UInt xN = iregNo(am->ARM64am.RR.base);
- UInt xM = iregNo(am->ARM64am.RR.index);
+ UInt xN = iregEnc(am->ARM64am.RR.base);
+ UInt xM = iregEnc(am->ARM64am.RR.index);
vassert(xN <= 30);
UInt instr = X_3_8_5_6_5_5(X011, isLoad ? X11000011 : X11000001,
xM, X011010, xN, wD);
vassert(-256 <= simm9 && simm9 <= 255);
UInt instr = X_2_6_3_9_2_5_5(X10, X111000, isLoad ? X010 : X000,
simm9 & 0x1FF, X00,
- iregNo(am->ARM64am.RI9.reg), wD);
+ iregEnc(am->ARM64am.RI9.reg), wD);
*p++ = instr;
return p;
}
UInt uimm12 = am->ARM64am.RI12.uimm12;
UInt scale = am->ARM64am.RI12.szB;
vassert(scale == 4); /* failure of this is serious. Do not ignore. */
- UInt xN = iregNo(am->ARM64am.RI12.reg);
+ UInt xN = iregEnc(am->ARM64am.RI12.reg);
vassert(xN <= 30);
UInt instr = X_2_6_2_12_5_5(X10, X111001, isLoad ? X01 : X00,
uimm12, xN, wD);
/* STR Wd, [Xn|SP, Xm]: 10 111 000 001 m 011 0 10 n d
LDR Wd, [Xn|SP, Xm]: 10 111 000 011 m 011 0 10 n d
*/
- UInt xN = iregNo(am->ARM64am.RR.base);
- UInt xM = iregNo(am->ARM64am.RR.index);
+ UInt xN = iregEnc(am->ARM64am.RR.base);
+ UInt xM = iregEnc(am->ARM64am.RR.index);
vassert(xN <= 30);
UInt instr = X_3_8_5_6_5_5(X101, isLoad ? X11000011 : X11000001,
xM, X011010, xN, wD);
*/
Int simm9 = am->ARM64am.RI9.simm9;
vassert(-256 <= simm9 && simm9 <= 255);
- UInt xN = iregNo(am->ARM64am.RI9.reg);
+ UInt xN = iregEnc(am->ARM64am.RI9.reg);
vassert(xN <= 30);
UInt instr = X_2_6_3_9_2_5_5(X11, X111000, isLoad ? X010 : X000,
simm9 & 0x1FF, X00, xN, xD);
UInt uimm12 = am->ARM64am.RI12.uimm12;
UInt scale = am->ARM64am.RI12.szB;
vassert(scale == 8); /* failure of this is serious. Do not ignore. */
- UInt xN = iregNo(am->ARM64am.RI12.reg);
+ UInt xN = iregEnc(am->ARM64am.RI12.reg);
vassert(xN <= 30);
UInt instr = X_2_6_2_12_5_5(X11, X111001, isLoad ? X01 : X00,
uimm12, xN, xD);
/* STR Xd, [Xn|SP, Xm]: 11 111 000 001 m 011 0 10 n d
LDR Xd, [Xn|SP, Xm]: 11 111 000 011 m 011 0 10 n d
*/
- UInt xN = iregNo(am->ARM64am.RR.base);
- UInt xM = iregNo(am->ARM64am.RR.index);
+ UInt xN = iregEnc(am->ARM64am.RR.base);
+ UInt xM = iregEnc(am->ARM64am.RR.index);
vassert(xN <= 30);
UInt instr = X_3_8_5_6_5_5(X111, isLoad ? X11000011 : X11000001,
xM, X011010, xN, xD);
switch (i->tag) {
case ARM64in_Arith: {
- UInt rD = iregNo(i->ARM64in.Arith.dst);
- UInt rN = iregNo(i->ARM64in.Arith.argL);
+ UInt rD = iregEnc(i->ARM64in.Arith.dst);
+ UInt rN = iregEnc(i->ARM64in.Arith.argL);
ARM64RIA* argR = i->ARM64in.Arith.argR;
switch (argR->tag) {
case ARM64riA_I12:
);
break;
case ARM64riA_R: {
- UInt rM = iregNo(i->ARM64in.Arith.argR->ARM64riA.R.reg);
+ UInt rM = iregEnc(i->ARM64in.Arith.argR->ARM64riA.R.reg);
*p++ = X_3_8_5_6_5_5(
i->ARM64in.Arith.isAdd ? X100 : X110,
X01011000, rM, X000000, rN, rD
}
case ARM64in_Cmp: {
UInt rD = 31; /* XZR, we are going to dump the result */
- UInt rN = iregNo(i->ARM64in.Cmp.argL);
+ UInt rN = iregEnc(i->ARM64in.Cmp.argL);
ARM64RIA* argR = i->ARM64in.Cmp.argR;
Bool is64 = i->ARM64in.Cmp.is64;
switch (argR->tag) {
case ARM64riA_R: {
/* 1 11 01011 00 0 Rm 000000 Rn Rd = SUBS Xd, Xn, Xm */
/* 0 11 01011 00 0 Rm 000000 Rn Rd = SUBS Wd, Wn, Wm */
- UInt rM = iregNo(i->ARM64in.Cmp.argR->ARM64riA.R.reg);
+ UInt rM = iregEnc(i->ARM64in.Cmp.argR->ARM64riA.R.reg);
*p++ = X_3_8_5_6_5_5(is64 ? X111 : X011,
X01011000, rM, X000000, rN, rD);
break;
goto done;
}
case ARM64in_Logic: {
- UInt rD = iregNo(i->ARM64in.Logic.dst);
- UInt rN = iregNo(i->ARM64in.Logic.argL);
+ UInt rD = iregEnc(i->ARM64in.Logic.dst);
+ UInt rN = iregEnc(i->ARM64in.Logic.argL);
ARM64RIL* argR = i->ARM64in.Logic.argR;
UInt opc = 0; /* invalid */
vassert(rD < 31);
/* 1 01 01010 00 0 m 000000 n d = ORR Xd, Xn, Xm */
/* 1 00 01010 00 0 m 000000 n d = AND Xd, Xn, Xm */
/* 1 10 01010 00 0 m 000000 n d = EOR Xd, Xn, Xm */
- UInt rM = iregNo(argR->ARM64riL.R.reg);
+ UInt rM = iregEnc(argR->ARM64riL.R.reg);
vassert(rM < 31);
*p++ = X_3_8_5_6_5_5(opc, X01010000, rM, X000000, rN, rD);
break;
}
case ARM64in_Test: {
UInt rD = 31; /* XZR, we are going to dump the result */
- UInt rN = iregNo(i->ARM64in.Test.argL);
+ UInt rN = iregEnc(i->ARM64in.Test.argL);
ARM64RIL* argR = i->ARM64in.Test.argR;
switch (argR->tag) {
case ARM64riL_I13: {
goto done;
}
case ARM64in_Shift: {
- UInt rD = iregNo(i->ARM64in.Shift.dst);
- UInt rN = iregNo(i->ARM64in.Shift.argL);
+ UInt rD = iregEnc(i->ARM64in.Shift.dst);
+ UInt rN = iregEnc(i->ARM64in.Shift.argL);
ARM64RI6* argR = i->ARM64in.Shift.argR;
vassert(rD < 31);
vassert(rN < 31);
/* 100 1101 0110 mm 001000 nn dd LSL Xd, Xn, Xm */
/* 100 1101 0110 mm 001001 nn dd LSR Xd, Xn, Xm */
/* 100 1101 0110 mm 001010 nn dd ASR Xd, Xn, Xm */
- UInt rM = iregNo(argR->ARM64ri6.R.reg);
+ UInt rM = iregEnc(argR->ARM64ri6.R.reg);
vassert(rM < 31);
UInt subOpc = 0;
switch (i->ARM64in.Shift.op) {
goto done;
}
case ARM64in_Unary: {
- UInt rDst = iregNo(i->ARM64in.Unary.dst);
- UInt rSrc = iregNo(i->ARM64in.Unary.src);
+ UInt rDst = iregEnc(i->ARM64in.Unary.dst);
+ UInt rSrc = iregEnc(i->ARM64in.Unary.src);
switch (i->ARM64in.Unary.op) {
case ARM64un_CLZ:
/* 1 10 1101 0110 00000 00010 0 nn dd CLZ Xd, Xn */
101 01010 00 0 m 000000 11111 d
*/
UInt instr = 0xAA0003E0;
- UInt d = iregNo(i->ARM64in.MovI.dst);
- UInt m = iregNo(i->ARM64in.MovI.src);
+ UInt d = iregEnc(i->ARM64in.MovI.dst);
+ UInt m = iregEnc(i->ARM64in.MovI.src);
*p++ = instr | ((m & 31) << 16) | ((d & 31) << 0);
goto done;
}
case ARM64in_Imm64: {
- p = imm64_to_iregNo( p, iregNo(i->ARM64in.Imm64.dst),
- i->ARM64in.Imm64.imm64 );
+ p = imm64_to_ireg( p, iregEnc(i->ARM64in.Imm64.dst),
+ i->ARM64in.Imm64.imm64 );
goto done;
}
case ARM64in_LdSt64: {
p = do_load_or_store64( p, i->ARM64in.LdSt64.isLoad,
- iregNo(i->ARM64in.LdSt64.rD),
+ iregEnc(i->ARM64in.LdSt64.rD),
i->ARM64in.LdSt64.amode );
goto done;
}
case ARM64in_LdSt32: {
p = do_load_or_store32( p, i->ARM64in.LdSt32.isLoad,
- iregNo(i->ARM64in.LdSt32.rD),
+ iregEnc(i->ARM64in.LdSt32.rD),
i->ARM64in.LdSt32.amode );
goto done;
}
case ARM64in_LdSt16: {
p = do_load_or_store16( p, i->ARM64in.LdSt16.isLoad,
- iregNo(i->ARM64in.LdSt16.rD),
+ iregEnc(i->ARM64in.LdSt16.rD),
i->ARM64in.LdSt16.amode );
goto done;
}
case ARM64in_LdSt8: {
p = do_load_or_store8( p, i->ARM64in.LdSt8.isLoad,
- iregNo(i->ARM64in.LdSt8.rD),
+ iregEnc(i->ARM64in.LdSt8.rD),
i->ARM64in.LdSt8.amode );
goto done;
}
/* Update the guest PC. */
/* imm64 x9, dstGA */
/* str x9, amPC */
- p = imm64_to_iregNo(p, /*x*/9, i->ARM64in.XDirect.dstGA);
+ p = imm64_to_ireg(p, /*x*/9, i->ARM64in.XDirect.dstGA);
p = do_load_or_store64(p, False/*!isLoad*/,
/*x*/9, i->ARM64in.XDirect.amPC);
const void* disp_cp_chain_me
= i->ARM64in.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
: disp_cp_chain_me_to_slowEP;
- p = imm64_to_iregNo_EXACTLY4(p, /*x*/9,
- (Addr)disp_cp_chain_me);
+ p = imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)disp_cp_chain_me);
*p++ = 0xD63F0120;
/* --- END of PATCHABLE BYTES --- */
/* Update the guest PC. */
/* str r-dstGA, amPC */
p = do_load_or_store64(p, False/*!isLoad*/,
- iregNo(i->ARM64in.XIndir.dstGA),
+ iregEnc(i->ARM64in.XIndir.dstGA),
i->ARM64in.XIndir.amPC);
/* imm64 x9, VG_(disp_cp_xindir) */
/* br x9 */
- p = imm64_to_iregNo(p, /*x*/9, (Addr)disp_cp_xindir);
+ p = imm64_to_ireg(p, /*x*/9, (Addr)disp_cp_xindir);
*p++ = 0xD61F0120; /* br x9 */
/* Fix up the conditional jump, if there was one. */
/* Update the guest PC. */
/* str r-dstGA, amPC */
p = do_load_or_store64(p, False/*!isLoad*/,
- iregNo(i->ARM64in.XAssisted.dstGA),
+ iregEnc(i->ARM64in.XAssisted.dstGA),
i->ARM64in.XAssisted.amPC);
/* movw r21, $magic_number */
"unexpected jump kind");
}
vassert(trcval != 0);
- p = imm64_to_iregNo(p, /*x*/21, (ULong)trcval);
+ p = imm64_to_ireg(p, /*x*/21, (ULong)trcval);
/* imm64 x9, VG_(disp_cp_xassisted) */
/* br x9 */
- p = imm64_to_iregNo(p, /*x*/9, (Addr)disp_cp_xassisted);
+ p = imm64_to_ireg(p, /*x*/9, (Addr)disp_cp_xassisted);
*p++ = 0xD61F0120; /* br x9 */
/* Fix up the conditional jump, if there was one. */
case ARM64in_CSel: {
/* 100 1101 0100 mm cond 00 nn dd = CSEL Xd, Xn, Xm, cond */
- UInt dd = iregNo(i->ARM64in.CSel.dst);
- UInt nn = iregNo(i->ARM64in.CSel.argL);
- UInt mm = iregNo(i->ARM64in.CSel.argR);
+ UInt dd = iregEnc(i->ARM64in.CSel.dst);
+ UInt nn = iregEnc(i->ARM64in.CSel.argL);
+ UInt mm = iregEnc(i->ARM64in.CSel.argR);
UInt cond = (UInt)i->ARM64in.CSel.cond;
vassert(dd < 31 && nn < 31 && mm < 31 && cond < 16);
*p++ = X_3_8_5_6_5_5(X100, X11010100, mm, cond << 2, nn, dd);
}
// x9 = &target
- p = imm64_to_iregNo( (UInt*)p,
- /*x*/9, (ULong)i->ARM64in.Call.target );
+ p = imm64_to_ireg( (UInt*)p, /*x*/9, (ULong)i->ARM64in.Call.target );
// blr x9
*p++ = 0xD63F0120;
// Patch the hole if necessary
if (i->ARM64in.Call.cond != ARM64cc_AL) {
ULong dist = (ULong)(p - ptmp);
- /* imm64_to_iregNo produces between 1 and 4 insns, and
+ /* imm64_to_ireg produces between 1 and 4 insns, and
then there's the BLR itself. Hence: */
vassert(dist >= 2 && dist <= 5);
vassert(ptmp != NULL);
case ARM64in_FromSP: {
/* 10,0 10001 00 0..(12)..0 11111 dd MOV Xd, xsp */
- UInt dd = iregNo(i->ARM64in.FromSP.dst);
+ UInt dd = iregEnc(i->ARM64in.FromSP.dst);
vassert(dd < 31);
*p++ = X_2_6_2_12_5_5(X10, X010001, X00, 0, X11111, dd);
goto done;
100 11011 010 mm 011111 nn dd SMULH Xd, Xn,Xm
100 11011 000 mm 011111 nn dd MUL Xd, Xn,Xm
*/
- UInt dd = iregNo(i->ARM64in.Mul.dst);
- UInt nn = iregNo(i->ARM64in.Mul.argL);
- UInt mm = iregNo(i->ARM64in.Mul.argR);
+ UInt dd = iregEnc(i->ARM64in.Mul.dst);
+ UInt nn = iregEnc(i->ARM64in.Mul.argL);
+ UInt mm = iregEnc(i->ARM64in.Mul.argR);
vassert(dd < 31 && nn < 31 && mm < 31);
switch (i->ARM64in.Mul.op) {
case ARM64mul_ZX:
/* 10 111101 01 imm12 n t LDR St, [Xn|SP, #imm12 * 4]
10 111101 00 imm12 n t STR St, [Xn|SP, #imm12 * 4]
*/
- UInt sD = dregNo(i->ARM64in.VLdStS.sD);
- UInt rN = iregNo(i->ARM64in.VLdStS.rN);
+ UInt sD = dregEnc(i->ARM64in.VLdStS.sD);
+ UInt rN = iregEnc(i->ARM64in.VLdStS.rN);
UInt uimm12 = i->ARM64in.VLdStS.uimm12;
Bool isLD = i->ARM64in.VLdStS.isLoad;
vassert(uimm12 < 16384 && 0 == (uimm12 & 3));
/* 11 111101 01 imm12 n t LDR Dt, [Xn|SP, #imm12 * 8]
11 111101 00 imm12 n t STR Dt, [Xn|SP, #imm12 * 8]
*/
- UInt dD = dregNo(i->ARM64in.VLdStD.dD);
- UInt rN = iregNo(i->ARM64in.VLdStD.rN);
+ UInt dD = dregEnc(i->ARM64in.VLdStD.dD);
+ UInt rN = iregEnc(i->ARM64in.VLdStD.rN);
UInt uimm12 = i->ARM64in.VLdStD.uimm12;
Bool isLD = i->ARM64in.VLdStD.isLoad;
vassert(uimm12 < 32768 && 0 == (uimm12 & 7));
/* 0100 1100 0000 0000 0111 11 rN rQ st1 {vQ.2d}, [<rN|SP>]
0100 1100 0100 0000 0111 11 rN rQ ld1 {vQ.2d}, [<rN|SP>]
*/
- UInt rQ = qregNo(i->ARM64in.VLdStQ.rQ);
- UInt rN = iregNo(i->ARM64in.VLdStQ.rN);
+ UInt rQ = qregEnc(i->ARM64in.VLdStQ.rQ);
+ UInt rN = iregEnc(i->ARM64in.VLdStQ.rN);
vassert(rQ < 32);
vassert(rN < 31);
if (i->ARM64in.VLdStQ.isLoad) {
100 11110 00 1 00 011 000000 n d UCVTF Sd, Xn
100 11110 01 1 00 011 000000 n d UCVTF Dd, Xn
*/
- UInt rN = iregNo(i->ARM64in.VCvtI2F.rS);
- UInt rD = dregNo(i->ARM64in.VCvtI2F.rD);
+ UInt rN = iregEnc(i->ARM64in.VCvtI2F.rS);
+ UInt rD = dregEnc(i->ARM64in.VCvtI2F.rD);
ARM64CvtOp how = i->ARM64in.VCvtI2F.how;
/* Just handle cases as they show up. */
switch (how) {
Fn is Dn when x==1, Sn when x==0
20:19 carry the rounding mode, using the same encoding as FPCR
*/
- UInt rD = iregNo(i->ARM64in.VCvtF2I.rD);
- UInt rN = dregNo(i->ARM64in.VCvtF2I.rS);
+ UInt rD = iregEnc(i->ARM64in.VCvtF2I.rD);
+ UInt rN = dregEnc(i->ARM64in.VCvtF2I.rS);
ARM64CvtOp how = i->ARM64in.VCvtF2I.how;
UChar armRM = i->ARM64in.VCvtF2I.armRM;
/* Just handle cases as they show up. */
---------- 01 ----- 0,0 --------- FCVT Sd, Dn (D->S)
Rounding, when dst is smaller than src, is per the FPCR.
*/
- UInt dd = dregNo(i->ARM64in.VCvtSD.dst);
- UInt nn = dregNo(i->ARM64in.VCvtSD.src);
+ UInt dd = dregEnc(i->ARM64in.VCvtSD.dst);
+ UInt nn = dregEnc(i->ARM64in.VCvtSD.src);
if (i->ARM64in.VCvtSD.sToD) {
*p++ = X_3_5_8_6_5_5(X000, X11110, X00100010, X110000, nn, dd);
} else {
------------------- 1,0 --------- FNEG ------
------------------- 1,1 --------- FSQRT -----
*/
- UInt dD = dregNo(i->ARM64in.VUnaryD.dst);
- UInt dN = dregNo(i->ARM64in.VUnaryD.src);
+ UInt dD = dregEnc(i->ARM64in.VUnaryD.dst);
+ UInt dN = dregEnc(i->ARM64in.VUnaryD.src);
UInt b16 = 2; /* impossible */
UInt b15 = 2; /* impossible */
switch (i->ARM64in.VUnaryD.op) {
------------------- 1,0 --------- FNEG ------
------------------- 1,1 --------- FSQRT -----
*/
- UInt sD = dregNo(i->ARM64in.VUnaryS.dst);
- UInt sN = dregNo(i->ARM64in.VUnaryS.src);
+ UInt sD = dregEnc(i->ARM64in.VUnaryS.dst);
+ UInt sN = dregEnc(i->ARM64in.VUnaryS.src);
UInt b16 = 2; /* impossible */
UInt b15 = 2; /* impossible */
switch (i->ARM64in.VUnaryS.op) {
---------------- 0010 ------ FADD --------
---------------- 0011 ------ FSUB --------
*/
- UInt dD = dregNo(i->ARM64in.VBinD.dst);
- UInt dN = dregNo(i->ARM64in.VBinD.argL);
- UInt dM = dregNo(i->ARM64in.VBinD.argR);
+ UInt dD = dregEnc(i->ARM64in.VBinD.dst);
+ UInt dN = dregEnc(i->ARM64in.VBinD.argL);
+ UInt dM = dregEnc(i->ARM64in.VBinD.argR);
UInt b1512 = 16; /* impossible */
switch (i->ARM64in.VBinD.op) {
case ARM64fpb_DIV: b1512 = X0001; break;
---------------- 0010 ------ FADD --------
---------------- 0011 ------ FSUB --------
*/
- UInt sD = dregNo(i->ARM64in.VBinS.dst);
- UInt sN = dregNo(i->ARM64in.VBinS.argL);
- UInt sM = dregNo(i->ARM64in.VBinS.argR);
+ UInt sD = dregEnc(i->ARM64in.VBinS.dst);
+ UInt sN = dregEnc(i->ARM64in.VBinS.argL);
+ UInt sM = dregEnc(i->ARM64in.VBinS.argR);
UInt b1512 = 16; /* impossible */
switch (i->ARM64in.VBinS.op) {
case ARM64fpb_DIV: b1512 = X0001; break;
}
case ARM64in_VCmpD: {
/* 000 11110 01 1 m 00 1000 n 00 000 FCMP Dn, Dm */
- UInt dN = dregNo(i->ARM64in.VCmpD.argL);
- UInt dM = dregNo(i->ARM64in.VCmpD.argR);
+ UInt dN = dregEnc(i->ARM64in.VCmpD.argL);
+ UInt dM = dregEnc(i->ARM64in.VCmpD.argR);
*p++ = X_3_8_5_6_5_5(X000, X11110011, dM, X001000, dN, X00000);
goto done;
}
case ARM64in_VCmpS: {
/* 000 11110 00 1 m 00 1000 n 00 000 FCMP Sn, Sm */
- UInt sN = dregNo(i->ARM64in.VCmpS.argL);
- UInt sM = dregNo(i->ARM64in.VCmpS.argR);
+ UInt sN = dregEnc(i->ARM64in.VCmpS.argL);
+ UInt sM = dregEnc(i->ARM64in.VCmpS.argR);
*p++ = X_3_8_5_6_5_5(X000, X11110001, sM, X001000, sN, X00000);
goto done;
}
000 11110 01 1 m cond 11 n d FCSEL Dd,Dn,Dm,cond
*/
Bool isD = i->ARM64in.VFCSel.isD;
- UInt dd = dregNo(i->ARM64in.VFCSel.dst);
- UInt nn = dregNo(i->ARM64in.VFCSel.argL);
- UInt mm = dregNo(i->ARM64in.VFCSel.argR);
+ UInt dd = dregEnc(i->ARM64in.VFCSel.dst);
+ UInt nn = dregEnc(i->ARM64in.VFCSel.argL);
+ UInt mm = dregEnc(i->ARM64in.VFCSel.argR);
UInt cond = (UInt)i->ARM64in.VFCSel.cond;
vassert(cond < 16);
*p++ = X_3_8_5_6_5_5(X000, isD ? X11110011 : X11110001,
}
case ARM64in_FPCR: {
Bool toFPCR = i->ARM64in.FPCR.toFPCR;
- UInt iReg = iregNo(i->ARM64in.FPCR.iReg);
+ UInt iReg = iregEnc(i->ARM64in.FPCR.iReg);
if (toFPCR) {
/* 0xD51B44 000 Rt MSR fpcr, rT */
*p++ = 0xD51B4400 | (iReg & 0x1F);
}
case ARM64in_FPSR: {
Bool toFPSR = i->ARM64in.FPSR.toFPSR;
- UInt iReg = iregNo(i->ARM64in.FPSR.iReg);
+ UInt iReg = iregEnc(i->ARM64in.FPSR.iReg);
if (toFPSR) {
/* 0xD51B44 001 Rt MSR fpsr, rT */
*p++ = 0xD51B4420 | (iReg & 0x1F);
010 01110 11 1 m 111111 n d FRSQRTS Vd.2d, Vn.2d, Vm.2d
010 01110 10 1 m 111111 n d FRSQRTS Vd.4s, Vn.4s, Vm.4s
*/
- UInt vD = qregNo(i->ARM64in.VBinV.dst);
- UInt vN = qregNo(i->ARM64in.VBinV.argL);
- UInt vM = qregNo(i->ARM64in.VBinV.argR);
+ UInt vD = qregEnc(i->ARM64in.VBinV.dst);
+ UInt vN = qregEnc(i->ARM64in.VBinV.argL);
+ UInt vM = qregEnc(i->ARM64in.VBinV.argR);
switch (i->ARM64in.VBinV.op) {
case ARM64vecb_ADD64x2:
*p++ = X_3_8_5_6_5_5(X010, X01110111, vM, X100001, vN, vD);
010 01110 sz 1 00000 001110 n d SUQADD@sz Vd, Vn
011 01110 sz 1 00000 001110 n d USQADD@sz Vd, Vn
*/
- UInt vD = qregNo(i->ARM64in.VModifyV.mod);
- UInt vN = qregNo(i->ARM64in.VModifyV.arg);
+ UInt vD = qregEnc(i->ARM64in.VModifyV.mod);
+ UInt vN = qregEnc(i->ARM64in.VModifyV.arg);
switch (i->ARM64in.VModifyV.op) {
case ARM64vecmo_SUQADD64x2:
*p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X001110, vN, vD);
011 01110 11 1 00001 110110 n d FRECPE Vd.2d, Vn.2d
011 01110 10 1 00001 110110 n d FRECPE Vd.4s, Vn.4s
*/
- UInt vD = qregNo(i->ARM64in.VUnaryV.dst);
- UInt vN = qregNo(i->ARM64in.VUnaryV.arg);
+ UInt vD = qregEnc(i->ARM64in.VUnaryV.dst);
+ UInt vN = qregEnc(i->ARM64in.VUnaryV.arg);
switch (i->ARM64in.VUnaryV.op) {
case ARM64vecu_FABS64x2:
*p++ = X_3_8_5_6_5_5(X010, X01110111, X00000, X111110, vN, vD);
001 01110 01 1,00001 010010 n d UQXTN Vd.4h, Vn.4s
001 01110 10 1,00001 010010 n d UQXTN Vd.2s, Vn.2d
*/
- UInt vD = qregNo(i->ARM64in.VNarrowV.dst);
- UInt vN = qregNo(i->ARM64in.VNarrowV.src);
+ UInt vD = qregEnc(i->ARM64in.VNarrowV.dst);
+ UInt vN = qregEnc(i->ARM64in.VNarrowV.src);
UInt dszBlg2 = i->ARM64in.VNarrowV.dszBlg2;
vassert(dszBlg2 >= 0 && dszBlg2 <= 2);
switch (i->ARM64in.VNarrowV.op) {
8h | sh in 0..15 -> let xxxx = sh in 001x:xxx
16b | sh in 0..7 -> let xxx = sh in 0001:xxx
*/
- UInt vD = qregNo(i->ARM64in.VShiftImmV.dst);
- UInt vN = qregNo(i->ARM64in.VShiftImmV.src);
+ UInt vD = qregEnc(i->ARM64in.VShiftImmV.dst);
+ UInt vN = qregEnc(i->ARM64in.VShiftImmV.src);
UInt sh = i->ARM64in.VShiftImmV.amt;
UInt tmpl = 0; /* invalid */
where imm4 = the shift amount, in bytes,
Vn is low operand, Vm is high operand
*/
- UInt vD = qregNo(i->ARM64in.VExtV.dst);
- UInt vN = qregNo(i->ARM64in.VExtV.srcLo);
- UInt vM = qregNo(i->ARM64in.VExtV.srcHi);
+ UInt vD = qregEnc(i->ARM64in.VExtV.dst);
+ UInt vN = qregEnc(i->ARM64in.VExtV.srcLo);
+ UInt vM = qregEnc(i->ARM64in.VExtV.srcHi);
UInt imm4 = i->ARM64in.VExtV.amtB;
vassert(imm4 >= 1 && imm4 <= 15);
*p++ = X_3_8_5_6_5_5(X011, X01110000, vM,
goto done;
}
case ARM64in_VImmQ: {
- UInt rQ = qregNo(i->ARM64in.VImmQ.rQ);
+ UInt rQ = qregEnc(i->ARM64in.VImmQ.rQ);
UShort imm = i->ARM64in.VImmQ.imm;
vassert(rQ < 32);
switch (imm) {
This isn't wonderful, in the sense that the upper half of
the vector register stays unchanged and thus the insn is
data dependent on its output register. */
- UInt dd = dregNo(i->ARM64in.VDfromX.rD);
- UInt xx = iregNo(i->ARM64in.VDfromX.rX);
+ UInt dd = dregEnc(i->ARM64in.VDfromX.rD);
+ UInt xx = iregEnc(i->ARM64in.VDfromX.rX);
vassert(xx < 31);
*p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
goto done;
1001 1110 0110 0111 0000 00 nn dd FMOV Vd.D[0], Xn
I think this zeroes out the top half of the destination, which
is what we need. TODO: can we do VDfromX and VQfromXX better? */
- UInt dd = qregNo(i->ARM64in.VQfromX.rQ);
- UInt xx = iregNo(i->ARM64in.VQfromX.rXlo);
+ UInt dd = qregEnc(i->ARM64in.VQfromX.rQ);
+ UInt xx = iregEnc(i->ARM64in.VQfromX.rXlo);
vassert(xx < 31);
*p++ = 0x9E670000 | X_2_6_2_12_5_5(0,0,0,0,xx,dd);
goto done;
0100 1110 0000 1000 0001 11 nn dd INS Vd.D[0], Xn
0100 1110 0001 1000 0001 11 nn dd INS Vd.D[1], Xn
*/
- UInt qq = qregNo(i->ARM64in.VQfromXX.rQ);
- UInt xhi = iregNo(i->ARM64in.VQfromXX.rXhi);
- UInt xlo = iregNo(i->ARM64in.VQfromXX.rXlo);
+ UInt qq = qregEnc(i->ARM64in.VQfromXX.rQ);
+ UInt xhi = iregEnc(i->ARM64in.VQfromXX.rXhi);
+ UInt xlo = iregEnc(i->ARM64in.VQfromXX.rXlo);
vassert(xhi < 31 && xlo < 31);
*p++ = 0x4E081C00 | X_2_6_2_12_5_5(0,0,0,0,xlo,qq);
*p++ = 0x4E181C00 | X_2_6_2_12_5_5(0,0,0,0,xhi,qq);
/* 010 0111 0000 01000 001111 nn dd UMOV Xd, Vn.D[0]
010 0111 0000 11000 001111 nn dd UMOV Xd, Vn.D[1]
*/
- UInt dd = iregNo(i->ARM64in.VXfromQ.rX);
- UInt nn = qregNo(i->ARM64in.VXfromQ.rQ);
+ UInt dd = iregEnc(i->ARM64in.VXfromQ.rX);
+ UInt nn = qregEnc(i->ARM64in.VXfromQ.rQ);
UInt laneNo = i->ARM64in.VXfromQ.laneNo;
vassert(dd < 31);
vassert(laneNo < 2);
/* 000 11110001 00110 000000 n d FMOV Wd, Sn
100 11110011 00110 000000 n d FMOV Xd, Dn
*/
- UInt dd = iregNo(i->ARM64in.VXfromDorS.rX);
- UInt nn = dregNo(i->ARM64in.VXfromDorS.rDorS);
+ UInt dd = iregEnc(i->ARM64in.VXfromDorS.rX);
+ UInt nn = dregEnc(i->ARM64in.VXfromDorS.rDorS);
Bool fromD = i->ARM64in.VXfromDorS.fromD;
vassert(dd < 31);
*p++ = X_3_8_5_6_5_5(fromD ? X100 : X000,
HReg rN = i->ARM64in.VMov.src;
switch (i->ARM64in.VMov.szB) {
case 16: {
- UInt dd = qregNo(rD);
- UInt nn = qregNo(rN);
+ UInt dd = qregEnc(rD);
+ UInt nn = qregEnc(rN);
*p++ = X_3_8_5_6_5_5(X010, X01110101, nn, X000111, nn, dd);
goto done;
}
case 8: {
- UInt dd = dregNo(rD);
- UInt nn = dregNo(rN);
+ UInt dd = dregEnc(rD);
+ UInt nn = dregEnc(rN);
*p++ = X_3_8_5_6_5_5(X000, X11110011, X00000, X010000, nn, dd);
goto done;
}
add x8, x8, #1
str x8, [x9]
*/
- p = imm64_to_iregNo_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL);
+ p = imm64_to_ireg_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL);
*p++ = 0xF9400128;
*p++ = 0x91000508;
*p++ = 0xF9000128;
movk x9, disp_cp_chain_me_to_EXPECTED[63:48], lsl 48
blr x9
viz
- <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+ <16 bytes generated by imm64_to_ireg_EXACTLY4>
D6 3F 01 20
*/
UInt* p = (UInt*)place_to_chain;
vassert(0 == (3 & (HWord)p));
- vassert(is_imm64_to_iregNo_EXACTLY4(
- p, /*x*/9, (Addr)disp_cp_chain_me_EXPECTED));
+ vassert(is_imm64_to_ireg_EXACTLY4(
+ p, /*x*/9, (Addr)disp_cp_chain_me_EXPECTED));
vassert(p[4] == 0xD63F0120);
/* And what we want to change it to is:
movk x9, place_to_jump_to[63:48], lsl 48
br x9
viz
- <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+ <16 bytes generated by imm64_to_ireg_EXACTLY4>
D6 1F 01 20
The replacement has the same length as the original.
*/
- (void)imm64_to_iregNo_EXACTLY4(
- p, /*x*/9, (Addr)place_to_jump_to);
+ (void)imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)place_to_jump_to);
p[4] = 0xD61F0120;
VexInvalRange vir = {(HWord)p, 20};
movk x9, place_to_jump_to_EXPECTED[63:48], lsl 48
br x9
viz
- <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+ <16 bytes generated by imm64_to_ireg_EXACTLY4>
D6 1F 01 20
*/
UInt* p = (UInt*)place_to_unchain;
vassert(0 == (3 & (HWord)p));
- vassert(is_imm64_to_iregNo_EXACTLY4(
+ vassert(is_imm64_to_ireg_EXACTLY4(
p, /*x*/9, (Addr)place_to_jump_to_EXPECTED));
vassert(p[4] == 0xD61F0120);
movk x9, disp_cp_chain_me_to[63:48], lsl 48
blr x9
viz
- <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+ <16 bytes generated by imm64_to_ireg_EXACTLY4>
D6 3F 01 20
*/
- (void)imm64_to_iregNo_EXACTLY4(
- p, /*x*/9, (Addr)disp_cp_chain_me);
+ (void)imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)disp_cp_chain_me);
p[4] = 0xD63F0120;
VexInvalRange vir = {(HWord)p, 20};
vassert(endness_host == VexEndnessLE);
UInt* p = (UInt*)place_to_patch;
vassert(0 == (3 & (HWord)p));
- vassert(is_imm64_to_iregNo_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL));
+ vassert(is_imm64_to_ireg_EXACTLY4(p, /*x*/9, 0x6555755585559566ULL));
vassert(p[4] == 0xF9400128);
vassert(p[5] == 0x91000508);
vassert(p[6] == 0xF9000128);
- imm64_to_iregNo_EXACTLY4(p, /*x*/9,
- (Addr)location_of_counter);
+ imm64_to_ireg_EXACTLY4(p, /*x*/9, (Addr)location_of_counter);
VexInvalRange vir = {(HWord)p, 4*4};
return vir;
}
/* --------- Registers. --------- */
-/* The usual HReg abstraction.
- There are 31 general purpose regs.
-*/
+#define ST_IN static inline
+ST_IN HReg hregARM64_X22 ( void ) { return mkHReg(False, HRcInt64, 22, 0); }
+ST_IN HReg hregARM64_X23 ( void ) { return mkHReg(False, HRcInt64, 23, 1); }
+ST_IN HReg hregARM64_X24 ( void ) { return mkHReg(False, HRcInt64, 24, 2); }
+ST_IN HReg hregARM64_X25 ( void ) { return mkHReg(False, HRcInt64, 25, 3); }
+ST_IN HReg hregARM64_X26 ( void ) { return mkHReg(False, HRcInt64, 26, 4); }
+ST_IN HReg hregARM64_X27 ( void ) { return mkHReg(False, HRcInt64, 27, 5); }
+ST_IN HReg hregARM64_X28 ( void ) { return mkHReg(False, HRcInt64, 28, 6); }
+
+ST_IN HReg hregARM64_X0 ( void ) { return mkHReg(False, HRcInt64, 0, 7); }
+ST_IN HReg hregARM64_X1 ( void ) { return mkHReg(False, HRcInt64, 1, 8); }
+ST_IN HReg hregARM64_X2 ( void ) { return mkHReg(False, HRcInt64, 2, 9); }
+ST_IN HReg hregARM64_X3 ( void ) { return mkHReg(False, HRcInt64, 3, 10); }
+ST_IN HReg hregARM64_X4 ( void ) { return mkHReg(False, HRcInt64, 4, 11); }
+ST_IN HReg hregARM64_X5 ( void ) { return mkHReg(False, HRcInt64, 5, 12); }
+ST_IN HReg hregARM64_X6 ( void ) { return mkHReg(False, HRcInt64, 6, 13); }
+ST_IN HReg hregARM64_X7 ( void ) { return mkHReg(False, HRcInt64, 7, 14); }
+
+ST_IN HReg hregARM64_Q16 ( void ) { return mkHReg(False, HRcVec128, 16, 15); }
+ST_IN HReg hregARM64_Q17 ( void ) { return mkHReg(False, HRcVec128, 17, 16); }
+ST_IN HReg hregARM64_Q18 ( void ) { return mkHReg(False, HRcVec128, 18, 17); }
+ST_IN HReg hregARM64_Q19 ( void ) { return mkHReg(False, HRcVec128, 19, 18); }
+ST_IN HReg hregARM64_Q20 ( void ) { return mkHReg(False, HRcVec128, 20, 19); }
+
+ST_IN HReg hregARM64_D8 ( void ) { return mkHReg(False, HRcFlt64, 8, 20); }
+ST_IN HReg hregARM64_D9 ( void ) { return mkHReg(False, HRcFlt64, 9, 21); }
+ST_IN HReg hregARM64_D10 ( void ) { return mkHReg(False, HRcFlt64, 10, 22); }
+ST_IN HReg hregARM64_D11 ( void ) { return mkHReg(False, HRcFlt64, 11, 23); }
+ST_IN HReg hregARM64_D12 ( void ) { return mkHReg(False, HRcFlt64, 12, 24); }
+ST_IN HReg hregARM64_D13 ( void ) { return mkHReg(False, HRcFlt64, 13, 25); }
+
+ST_IN HReg hregARM64_X8 ( void ) { return mkHReg(False, HRcInt64, 8, 26); }
+ST_IN HReg hregARM64_X9 ( void ) { return mkHReg(False, HRcInt64, 9, 27); }
+ST_IN HReg hregARM64_X21 ( void ) { return mkHReg(False, HRcInt64, 21, 28); }
+#undef ST_IN
extern void ppHRegARM64 ( HReg );
-extern HReg hregARM64_X0 ( void );
-extern HReg hregARM64_X1 ( void );
-extern HReg hregARM64_X2 ( void );
-extern HReg hregARM64_X3 ( void );
-extern HReg hregARM64_X4 ( void );
-extern HReg hregARM64_X5 ( void );
-extern HReg hregARM64_X6 ( void );
-extern HReg hregARM64_X7 ( void );
-extern HReg hregARM64_X8 ( void );
-extern HReg hregARM64_X9 ( void );
-extern HReg hregARM64_X10 ( void );
-extern HReg hregARM64_X11 ( void );
-extern HReg hregARM64_X12 ( void );
-extern HReg hregARM64_X13 ( void );
-extern HReg hregARM64_X14 ( void );
-extern HReg hregARM64_X15 ( void );
-extern HReg hregARM64_X21 ( void );
-extern HReg hregARM64_X22 ( void );
-extern HReg hregARM64_X23 ( void );
-extern HReg hregARM64_X24 ( void );
-extern HReg hregARM64_X25 ( void );
-extern HReg hregARM64_X26 ( void );
-extern HReg hregARM64_X27 ( void );
-extern HReg hregARM64_X28 ( void );
-extern HReg hregARM64_D8 ( void );
-extern HReg hregARM64_D9 ( void );
-extern HReg hregARM64_D10 ( void );
-extern HReg hregARM64_D11 ( void );
-extern HReg hregARM64_D12 ( void );
-extern HReg hregARM64_D13 ( void );
-extern HReg hregARM64_Q16 ( void );
-extern HReg hregARM64_Q17 ( void );
-extern HReg hregARM64_Q18 ( void );
-extern HReg hregARM64_Q19 ( void );
-extern HReg hregARM64_Q20 ( void );
-
/* Number of registers used arg passing in function calls */
#define ARM64_N_ARGREGS 8 /* x0 .. x7 */
extern void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
-extern void getAllocableRegs_ARM64 ( Int*, HReg** );
+extern const RRegUniverse* getRRegUniverse_ARM64 ( void );
+
extern HInstrArray* iselSB_ARM64 ( const IRSB*,
VexArch,
const VexArchInfo*,
static HReg newVRegI ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcInt64, 0, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegD ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt64, 0, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegV ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
switch (bb->tyenv->types[i]) {
case Ity_I1:
case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
- hreg = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
break;
case Ity_I128:
- hreg = mkHReg(j++, HRcInt64, True);
- hregHI = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
+ hregHI = mkHReg(True, HRcInt64, 0, j++);
break;
case Ity_F32: // we'll use HRcFlt64 regs for F32 too
case Ity_F64:
- hreg = mkHReg(j++, HRcFlt64, True);
+ hreg = mkHReg(True, HRcFlt64, 0, j++);
break;
case Ity_V128:
- hreg = mkHReg(j++, HRcVec128, True);
+ hreg = mkHReg(True, HRcVec128, 0, j++);
break;
case Ity_V256:
- hreg = mkHReg(j++, HRcVec128, True);
- hregHI = mkHReg(j++, HRcVec128, True);
+ hreg = mkHReg(True, HRcVec128, 0, j++);
+ hregHI = mkHReg(True, HRcVec128, 0, j++);
break;
default:
ppIRType(bb->tyenv->types[i]);
/* --------- Registers. --------- */
-/* The usual HReg abstraction.
- There are 16 general purpose regs.
-*/
+const RRegUniverse* getRRegUniverse_ARM ( void )
+{
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. */
+ static RRegUniverse rRegUniverse_ARM;
+ static Bool rRegUniverse_ARM_initted = False;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_ARM;
+
+ /* This isn't thread-safe. Sigh. */
+ if (LIKELY(rRegUniverse_ARM_initted))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+
+ /* Callee saves ones are listed first, since we prefer them
+ if they're available. */
+ ru->regs[ru->size++] = hregARM_R4();
+ ru->regs[ru->size++] = hregARM_R5();
+ ru->regs[ru->size++] = hregARM_R6();
+ ru->regs[ru->size++] = hregARM_R7();
+ ru->regs[ru->size++] = hregARM_R10();
+ ru->regs[ru->size++] = hregARM_R11();
+ /* Otherwise we'll have to slum it out with caller-saves ones. */
+ ru->regs[ru->size++] = hregARM_R0();
+ ru->regs[ru->size++] = hregARM_R1();
+ ru->regs[ru->size++] = hregARM_R2();
+ ru->regs[ru->size++] = hregARM_R3();
+ ru->regs[ru->size++] = hregARM_R9();
+ /* FP registers. Note: these are all callee-save. Yay! Hence we
+ don't need to mention them as trashed in getHRegUsage for
+ ARMInstr_Call. */
+ ru->regs[ru->size++] = hregARM_D8();
+ ru->regs[ru->size++] = hregARM_D9();
+ ru->regs[ru->size++] = hregARM_D10();
+ ru->regs[ru->size++] = hregARM_D11();
+ ru->regs[ru->size++] = hregARM_D12();
+ ru->regs[ru->size++] = hregARM_S26();
+ ru->regs[ru->size++] = hregARM_S27();
+ ru->regs[ru->size++] = hregARM_S28();
+ ru->regs[ru->size++] = hregARM_S29();
+ ru->regs[ru->size++] = hregARM_S30();
+ ru->regs[ru->size++] = hregARM_Q8();
+ ru->regs[ru->size++] = hregARM_Q9();
+ ru->regs[ru->size++] = hregARM_Q10();
+ ru->regs[ru->size++] = hregARM_Q11();
+ ru->regs[ru->size++] = hregARM_Q12();
+ ru->allocable = ru->size;
+
+ /* And other regs, not available to the allocator. */
+
+ // unavail: r8 as GSP
+ // r12 is used as a spill/reload temporary
+ // r13 as SP
+ // r14 as LR
+ // r15 as PC
+ //
+ // All in all, we have 11 allocatable integer registers:
+ // 0 1 2 3 4 5 6 7 9 10 11, with r8 dedicated as GSP
+ // and r12 dedicated as a spill temporary.
+ // 13 14 and 15 are not under the allocator's control.
+ //
+ // Hence for the allocatable registers we have:
+ //
+ // callee-saved: 4 5 6 7 (8) 9 10 11
+ // caller-saved: 0 1 2 3
+ // Note 9 is ambiguous: the base EABI does not give an e/r-saved
+ // designation for it, but the Linux instantiation of the ABI
+ // specifies it as callee-saved.
+ //
+ // If the set of available registers changes or if the e/r status
+ // changes, be sure to re-check/sync the definition of
+ // getHRegUsage for ARMInstr_Call too.
+ ru->regs[ru->size++] = hregARM_R8();
+ ru->regs[ru->size++] = hregARM_R12();
+ ru->regs[ru->size++] = hregARM_R13();
+ ru->regs[ru->size++] = hregARM_R14();
+ ru->regs[ru->size++] = hregARM_R15();
+ ru->regs[ru->size++] = hregARM_Q13();
+ ru->regs[ru->size++] = hregARM_Q14();
+ ru->regs[ru->size++] = hregARM_Q15();
+
+ rRegUniverse_ARM_initted = True;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
void ppHRegARM ( HReg reg ) {
Int r;
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 16);
vex_printf("r%d", r);
return;
case HRcFlt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("d%d", r);
return;
case HRcFlt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("s%d", r);
return;
case HRcVec128:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 16);
vex_printf("q%d", r);
return;
}
}
-HReg hregARM_R0 ( void ) { return mkHReg(0, HRcInt32, False); }
-HReg hregARM_R1 ( void ) { return mkHReg(1, HRcInt32, False); }
-HReg hregARM_R2 ( void ) { return mkHReg(2, HRcInt32, False); }
-HReg hregARM_R3 ( void ) { return mkHReg(3, HRcInt32, False); }
-HReg hregARM_R4 ( void ) { return mkHReg(4, HRcInt32, False); }
-HReg hregARM_R5 ( void ) { return mkHReg(5, HRcInt32, False); }
-HReg hregARM_R6 ( void ) { return mkHReg(6, HRcInt32, False); }
-HReg hregARM_R7 ( void ) { return mkHReg(7, HRcInt32, False); }
-HReg hregARM_R8 ( void ) { return mkHReg(8, HRcInt32, False); }
-HReg hregARM_R9 ( void ) { return mkHReg(9, HRcInt32, False); }
-HReg hregARM_R10 ( void ) { return mkHReg(10, HRcInt32, False); }
-HReg hregARM_R11 ( void ) { return mkHReg(11, HRcInt32, False); }
-HReg hregARM_R12 ( void ) { return mkHReg(12, HRcInt32, False); }
-HReg hregARM_R13 ( void ) { return mkHReg(13, HRcInt32, False); }
-HReg hregARM_R14 ( void ) { return mkHReg(14, HRcInt32, False); }
-HReg hregARM_R15 ( void ) { return mkHReg(15, HRcInt32, False); }
-HReg hregARM_D8 ( void ) { return mkHReg(8, HRcFlt64, False); }
-HReg hregARM_D9 ( void ) { return mkHReg(9, HRcFlt64, False); }
-HReg hregARM_D10 ( void ) { return mkHReg(10, HRcFlt64, False); }
-HReg hregARM_D11 ( void ) { return mkHReg(11, HRcFlt64, False); }
-HReg hregARM_D12 ( void ) { return mkHReg(12, HRcFlt64, False); }
-HReg hregARM_S26 ( void ) { return mkHReg(26, HRcFlt32, False); }
-HReg hregARM_S27 ( void ) { return mkHReg(27, HRcFlt32, False); }
-HReg hregARM_S28 ( void ) { return mkHReg(28, HRcFlt32, False); }
-HReg hregARM_S29 ( void ) { return mkHReg(29, HRcFlt32, False); }
-HReg hregARM_S30 ( void ) { return mkHReg(30, HRcFlt32, False); }
-HReg hregARM_Q8 ( void ) { return mkHReg(8, HRcVec128, False); }
-HReg hregARM_Q9 ( void ) { return mkHReg(9, HRcVec128, False); }
-HReg hregARM_Q10 ( void ) { return mkHReg(10, HRcVec128, False); }
-HReg hregARM_Q11 ( void ) { return mkHReg(11, HRcVec128, False); }
-HReg hregARM_Q12 ( void ) { return mkHReg(12, HRcVec128, False); }
-HReg hregARM_Q13 ( void ) { return mkHReg(13, HRcVec128, False); }
-HReg hregARM_Q14 ( void ) { return mkHReg(14, HRcVec128, False); }
-HReg hregARM_Q15 ( void ) { return mkHReg(15, HRcVec128, False); }
-
-void getAllocableRegs_ARM ( Int* nregs, HReg** arr )
-{
- Int i = 0;
- *nregs = 26;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
- // callee saves ones are listed first, since we prefer them
- // if they're available
- (*arr)[i++] = hregARM_R4();
- (*arr)[i++] = hregARM_R5();
- (*arr)[i++] = hregARM_R6();
- (*arr)[i++] = hregARM_R7();
- (*arr)[i++] = hregARM_R10();
- (*arr)[i++] = hregARM_R11();
- // otherwise we'll have to slum it out with caller-saves ones
- (*arr)[i++] = hregARM_R0();
- (*arr)[i++] = hregARM_R1();
- (*arr)[i++] = hregARM_R2();
- (*arr)[i++] = hregARM_R3();
- (*arr)[i++] = hregARM_R9();
- // FP hreegisters. Note: these are all callee-save. Yay!
- // Hence we don't need to mention them as trashed in
- // getHRegUsage for ARMInstr_Call.
- (*arr)[i++] = hregARM_D8();
- (*arr)[i++] = hregARM_D9();
- (*arr)[i++] = hregARM_D10();
- (*arr)[i++] = hregARM_D11();
- (*arr)[i++] = hregARM_D12();
- (*arr)[i++] = hregARM_S26();
- (*arr)[i++] = hregARM_S27();
- (*arr)[i++] = hregARM_S28();
- (*arr)[i++] = hregARM_S29();
- (*arr)[i++] = hregARM_S30();
-
- (*arr)[i++] = hregARM_Q8();
- (*arr)[i++] = hregARM_Q9();
- (*arr)[i++] = hregARM_Q10();
- (*arr)[i++] = hregARM_Q11();
- (*arr)[i++] = hregARM_Q12();
-
- //(*arr)[i++] = hregARM_Q13();
- //(*arr)[i++] = hregARM_Q14();
- //(*arr)[i++] = hregARM_Q15();
-
- // unavail: r8 as GSP
- // r12 is used as a spill/reload temporary
- // r13 as SP
- // r14 as LR
- // r15 as PC
- //
- // All in all, we have 11 allocatable integer registers:
- // 0 1 2 3 4 5 6 7 9 10 11, with r8 dedicated as GSP
- // and r12 dedicated as a spill temporary.
- // 13 14 and 15 are not under the allocator's control.
- //
- // Hence for the allocatable registers we have:
- //
- // callee-saved: 4 5 6 7 (8) 9 10 11
- // caller-saved: 0 1 2 3
- // Note 9 is ambiguous: the base EABI does not give an e/r-saved
- // designation for it, but the Linux instantiation of the ABI
- // specifies it as callee-saved.
- //
- // If the set of available registers changes or if the e/r status
- // changes, be sure to re-check/sync the definition of
- // getHRegUsage for ARMInstr_Call too.
- vassert(i == *nregs);
-}
-
-
/* --------- Condition codes, ARM encoding. --------- */
Note that buf is not the insn's final place, and therefore it is
imperative to emit position-independent code. */
-static inline UChar iregNo ( HReg r )
+static inline UInt iregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt32);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return toUChar(n);
+ return n;
}
-static inline UChar dregNo ( HReg r )
+static inline UInt dregEnc ( HReg r )
{
UInt n;
- if (hregClass(r) != HRcFlt64)
- ppHRegClass(hregClass(r));
vassert(hregClass(r) == HRcFlt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
- return toUChar(n);
+ return n;
}
-static inline UChar fregNo ( HReg r )
+static inline UInt fregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcFlt32);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
- return toUChar(n);
+ return n;
}
-static inline UChar qregNo ( HReg r )
+static inline UInt qregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcVec128);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 15);
- return toUChar(n);
+ return n;
}
#define BITS4(zzb3,zzb2,zzb1,zzb0) \
instr |= ri->ARMri84.I84.imm8;
} else {
instr = 0 << 25;
- instr |= iregNo(ri->ARMri84.R.reg);
+ instr |= iregEnc(ri->ARMri84.R.reg);
}
return instr;
}
instr |= imm5 << 7;
} else {
instr = 1 << 4;
- instr |= iregNo(ri->ARMri5.R.reg) << 8;
+ instr |= iregEnc(ri->ARMri5.R.reg) << 8;
}
return instr;
}
/* Get an immediate into a register, using only that
register. (very lame..) */
-static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
+static UInt* imm32_to_ireg ( UInt* p, Int rD, UInt imm32 )
{
UInt instr;
vassert(rD >= 0 && rD <= 14); // r15 not good to mess with!
generating exactly 2 instructions, regardless of the value of the
immediate. This is used when generating sections of code that need
to be patched later, so as to guarantee a specific size. */
-static UInt* imm32_to_iregNo_EXACTLY2 ( UInt* p, Int rD, UInt imm32 )
+static UInt* imm32_to_ireg_EXACTLY2 ( UInt* p, Int rD, UInt imm32 )
{
if (VEX_ARM_ARCHLEVEL(arm_hwcaps) > 6) {
/* Generate movw rD, #low16 ; movt rD, #high16. */
}
/* Check whether p points at a 2-insn sequence cooked up by
- imm32_to_iregNo_EXACTLY2(). */
-static Bool is_imm32_to_iregNo_EXACTLY2 ( UInt* p, Int rD, UInt imm32 )
+ imm32_to_ireg_EXACTLY2(). */
+static Bool is_imm32_to_ireg_EXACTLY2 ( UInt* p, Int rD, UInt imm32 )
{
if (VEX_ARM_ARCHLEVEL(arm_hwcaps) > 6) {
/* Generate movw rD, #low16 ; movt rD, #high16. */
}
vassert(simm12 >= 0 && simm12 <= 4095);
instr = XXXXX___(X1110,X0101,BITS4(bP,bB,0,bL),
- iregNo(am->ARMam1.RI.reg),
+ iregEnc(am->ARMam1.RI.reg),
rD);
instr |= simm12;
*p++ = instr;
switch (i->tag) {
case ARMin_Alu: {
UInt instr, subopc;
- UInt rD = iregNo(i->ARMin.Alu.dst);
- UInt rN = iregNo(i->ARMin.Alu.argL);
+ UInt rD = iregEnc(i->ARMin.Alu.dst);
+ UInt rN = iregEnc(i->ARMin.Alu.argL);
ARMRI84* argR = i->ARMin.Alu.argR;
switch (i->ARMin.Alu.op) {
case ARMalu_ADDS: /* fallthru */
}
case ARMin_Shift: {
UInt instr, subopc;
- UInt rD = iregNo(i->ARMin.Shift.dst);
- UInt rM = iregNo(i->ARMin.Shift.argL);
+ UInt rD = iregEnc(i->ARMin.Shift.dst);
+ UInt rM = iregEnc(i->ARMin.Shift.argL);
ARMRI5* argR = i->ARMin.Shift.argR;
switch (i->ARMin.Shift.op) {
case ARMsh_SHL: subopc = X0000; break;
}
case ARMin_Unary: {
UInt instr;
- UInt rDst = iregNo(i->ARMin.Unary.dst);
- UInt rSrc = iregNo(i->ARMin.Unary.src);
+ UInt rDst = iregEnc(i->ARMin.Unary.dst);
+ UInt rSrc = iregEnc(i->ARMin.Unary.src);
switch (i->ARMin.Unary.op) {
case ARMun_CLZ:
instr = XXXXXXXX(X1110,X0001,X0110,X1111,
UInt SBZ = 0;
instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
((subopc << 1) & 0xF) | 1,
- iregNo(i->ARMin.CmpOrTst.argL), SBZ );
+ iregEnc(i->ARMin.CmpOrTst.argL), SBZ );
*p++ = instr;
goto done;
}
UInt SBZ = 0;
instr |= XXXXX___(X1110, (1 & (subopc >> 3)),
(subopc << 1) & 0xF, SBZ,
- iregNo(i->ARMin.Mov.dst));
+ iregEnc(i->ARMin.Mov.dst));
*p++ = instr;
goto done;
}
case ARMin_Imm32: {
- p = imm32_to_iregNo( (UInt*)p, iregNo(i->ARMin.Imm32.dst),
- i->ARMin.Imm32.imm32 );
+ p = imm32_to_ireg( (UInt*)p, iregEnc(i->ARMin.Imm32.dst),
+ i->ARMin.Imm32.imm32 );
goto done;
}
case ARMin_LdSt32:
}
vassert(simm12 >= 0 && simm12 <= 4095);
instr = XXXXX___(cc,X0101,BITS4(bP,bB,0,bL),
- iregNo(am->ARMam1.RI.reg),
- iregNo(rD));
+ iregEnc(am->ARMam1.RI.reg),
+ iregEnc(rD));
instr |= simm12;
*p++ = instr;
goto done;
vassert(!(bL == 0 && bS == 1)); // "! signed store"
/**/ if (bL == 0 && bS == 0) {
// strh
- instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,0), iregNo(rN),
- iregNo(rD), imm8hi, X1011, imm8lo);
+ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,0), iregEnc(rN),
+ iregEnc(rD), imm8hi, X1011, imm8lo);
*p++ = instr;
goto done;
}
else if (bL == 1 && bS == 0) {
// ldrh
- instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
- iregNo(rD), imm8hi, X1011, imm8lo);
+ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregEnc(rN),
+ iregEnc(rD), imm8hi, X1011, imm8lo);
*p++ = instr;
goto done;
}
else if (bL == 1 && bS == 1) {
// ldrsh
- instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
- iregNo(rD), imm8hi, X1111, imm8lo);
+ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregEnc(rN),
+ iregEnc(rD), imm8hi, X1111, imm8lo);
*p++ = instr;
goto done;
}
imm8hi = (simm8 >> 4) & 0xF;
imm8lo = simm8 & 0xF;
// ldrsb
- instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregNo(rN),
- iregNo(rD), imm8hi, X1101, imm8lo);
+ instr = XXXXXXXX(cc,X0001, BITS4(bP,1,0,1), iregEnc(rN),
+ iregEnc(rD), imm8hi, X1101, imm8lo);
*p++ = instr;
goto done;
} else {
/* movw r12, lo16(dstGA) */
/* movt r12, hi16(dstGA) */
/* str r12, amR15T */
- p = imm32_to_iregNo(p, /*r*/12, i->ARMin.XDirect.dstGA);
+ p = imm32_to_ireg(p, /*r*/12, i->ARMin.XDirect.dstGA);
p = do_load_or_store32(p, False/*!isLoad*/,
/*r*/12, i->ARMin.XDirect.amR15T);
const void* disp_cp_chain_me
= i->ARMin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
: disp_cp_chain_me_to_slowEP;
- p = imm32_to_iregNo_EXACTLY2(p, /*r*/12,
- (UInt)(Addr)disp_cp_chain_me);
+ p = imm32_to_ireg_EXACTLY2(p, /*r*/12,
+ (UInt)(Addr)disp_cp_chain_me);
*p++ = 0xE12FFF3C;
/* --- END of PATCHABLE BYTES --- */
/* Update the guest R15T. */
/* str r-dstGA, amR15T */
p = do_load_or_store32(p, False/*!isLoad*/,
- iregNo(i->ARMin.XIndir.dstGA),
+ iregEnc(i->ARMin.XIndir.dstGA),
i->ARMin.XIndir.amR15T);
/* movw r12, lo16(VG_(disp_cp_xindir)) */
/* movt r12, hi16(VG_(disp_cp_xindir)) */
/* bx r12 (A1) */
- p = imm32_to_iregNo(p, /*r*/12,
- (UInt)(Addr)disp_cp_xindir);
+ p = imm32_to_ireg(p, /*r*/12, (UInt)(Addr)disp_cp_xindir);
*p++ = 0xE12FFF1C;
/* Fix up the conditional jump, if there was one. */
/* Update the guest R15T. */
/* str r-dstGA, amR15T */
p = do_load_or_store32(p, False/*!isLoad*/,
- iregNo(i->ARMin.XAssisted.dstGA),
+ iregEnc(i->ARMin.XAssisted.dstGA),
i->ARMin.XAssisted.amR15T);
/* movw r8, $magic_number */
vpanic("emit_ARMInstr.ARMin_XAssisted: unexpected jump kind");
}
vassert(trcval != 0);
- p = imm32_to_iregNo(p, /*r*/8, trcval);
+ p = imm32_to_ireg(p, /*r*/8, trcval);
/* movw r12, lo16(VG_(disp_cp_xassisted)) */
/* movt r12, hi16(VG_(disp_cp_xassisted)) */
/* bx r12 (A1) */
- p = imm32_to_iregNo(p, /*r*/12,
- (UInt)(Addr)disp_cp_xassisted);
+ p = imm32_to_ireg(p, /*r*/12, (UInt)(Addr)disp_cp_xassisted);
*p++ = 0xE12FFF1C;
/* Fix up the conditional jump, if there was one. */
UInt SBZ = 0;
instr |= XXXXX___(i->ARMin.CMov.cond, (1 & (subopc >> 3)),
(subopc << 1) & 0xF, SBZ,
- iregNo(i->ARMin.CMov.dst));
+ iregEnc(i->ARMin.CMov.dst));
*p++ = instr;
goto done;
}
if (i->ARMin.Call.cond == ARMcc_AL/*call always happens*/
|| i->ARMin.Call.rloc.pri == RLPri_None/*no fixup action*/) {
// r"scratchNo" = &target
- p = imm32_to_iregNo( (UInt*)p,
- scratchNo, (UInt)i->ARMin.Call.target );
+ p = imm32_to_ireg( (UInt*)p,
+ scratchNo, (UInt)i->ARMin.Call.target );
// blx{cond} r"scratchNo"
instr = XXX___XX(i->ARMin.Call.cond, X0001, X0010, /*___*/
X0011, scratchNo);
*p++ = 0; // filled in later
// r"scratchNo" = &target
- p = imm32_to_iregNo( (UInt*)p,
- scratchNo, (UInt)i->ARMin.Call.target );
+ p = imm32_to_ireg( (UInt*)p,
+ scratchNo, (UInt)i->ARMin.Call.target );
// blx{AL} r"scratchNo"
instr = XXX___XX(ARMcc_AL, X0001, X0010, /*___*/
/* Do the 'else' actions */
switch (i->ARMin.Call.rloc.pri) {
case RLPri_Int:
- p = imm32_to_iregNo_EXACTLY2(p, /*r*/0, 0x55555555);
+ p = imm32_to_ireg_EXACTLY2(p, /*r*/0, 0x55555555);
break;
case RLPri_2Int:
vassert(0); //ATC
- p = imm32_to_iregNo_EXACTLY2(p, /*r*/0, 0x55555555);
+ p = imm32_to_ireg_EXACTLY2(p, /*r*/0, 0x55555555);
/* mov r1, r0 */
*p++ = 0xE1A01000;
break;
goto bad;
}
case ARMin_VLdStD: {
- UInt dD = dregNo(i->ARMin.VLdStD.dD);
- UInt rN = iregNo(i->ARMin.VLdStD.amode->reg);
+ UInt dD = dregEnc(i->ARMin.VLdStD.dD);
+ UInt rN = iregEnc(i->ARMin.VLdStD.amode->reg);
Int simm11 = i->ARMin.VLdStD.amode->simm11;
UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
UInt bU = simm11 >= 0 ? 1 : 0;
goto done;
}
case ARMin_VLdStS: {
- UInt fD = fregNo(i->ARMin.VLdStS.fD);
- UInt rN = iregNo(i->ARMin.VLdStS.amode->reg);
+ UInt fD = fregEnc(i->ARMin.VLdStS.fD);
+ UInt rN = iregEnc(i->ARMin.VLdStS.amode->reg);
Int simm11 = i->ARMin.VLdStS.amode->simm11;
UInt off8 = simm11 >= 0 ? simm11 : ((UInt)(-simm11));
UInt bU = simm11 >= 0 ? 1 : 0;
goto done;
}
case ARMin_VAluD: {
- UInt dN = dregNo(i->ARMin.VAluD.argL);
- UInt dD = dregNo(i->ARMin.VAluD.dst);
- UInt dM = dregNo(i->ARMin.VAluD.argR);
+ UInt dN = dregEnc(i->ARMin.VAluD.argL);
+ UInt dD = dregEnc(i->ARMin.VAluD.dst);
+ UInt dM = dregEnc(i->ARMin.VAluD.argR);
UInt pqrs = X1111; /* undefined */
switch (i->ARMin.VAluD.op) {
case ARMvfp_ADD: pqrs = X0110; break;
goto done;
}
case ARMin_VAluS: {
- UInt dN = fregNo(i->ARMin.VAluS.argL);
- UInt dD = fregNo(i->ARMin.VAluS.dst);
- UInt dM = fregNo(i->ARMin.VAluS.argR);
+ UInt dN = fregEnc(i->ARMin.VAluS.argL);
+ UInt dD = fregEnc(i->ARMin.VAluS.dst);
+ UInt dM = fregEnc(i->ARMin.VAluS.argR);
UInt bN = dN & 1;
UInt bD = dD & 1;
UInt bM = dM & 1;
goto done;
}
case ARMin_VUnaryD: {
- UInt dD = dregNo(i->ARMin.VUnaryD.dst);
- UInt dM = dregNo(i->ARMin.VUnaryD.src);
+ UInt dD = dregEnc(i->ARMin.VUnaryD.dst);
+ UInt dM = dregEnc(i->ARMin.VUnaryD.src);
UInt insn = 0;
switch (i->ARMin.VUnaryD.op) {
case ARMvfpu_COPY:
goto done;
}
case ARMin_VUnaryS: {
- UInt fD = fregNo(i->ARMin.VUnaryS.dst);
- UInt fM = fregNo(i->ARMin.VUnaryS.src);
+ UInt fD = fregEnc(i->ARMin.VUnaryS.dst);
+ UInt fM = fregEnc(i->ARMin.VUnaryS.src);
UInt insn = 0;
switch (i->ARMin.VUnaryS.op) {
case ARMvfpu_COPY:
goto done;
}
case ARMin_VCmpD: {
- UInt dD = dregNo(i->ARMin.VCmpD.argL);
- UInt dM = dregNo(i->ARMin.VCmpD.argR);
+ UInt dD = dregEnc(i->ARMin.VCmpD.argL);
+ UInt dM = dregEnc(i->ARMin.VCmpD.argR);
UInt insn = XXXXXXXX(0xE, X1110, X1011, X0100, dD, X1011, X0100, dM);
*p++ = insn; /* FCMPD dD, dM */
*p++ = 0xEEF1FA10; /* FMSTAT */
}
case ARMin_VCMovD: {
UInt cc = (UInt)i->ARMin.VCMovD.cond;
- UInt dD = dregNo(i->ARMin.VCMovD.dst);
- UInt dM = dregNo(i->ARMin.VCMovD.src);
+ UInt dD = dregEnc(i->ARMin.VCMovD.dst);
+ UInt dM = dregEnc(i->ARMin.VCMovD.src);
vassert(cc < 16 && cc != ARMcc_AL);
UInt insn = XXXXXXXX(cc, X1110,X1011,X0000,dD,X1011,X0100,dM);
*p++ = insn;
}
case ARMin_VCMovS: {
UInt cc = (UInt)i->ARMin.VCMovS.cond;
- UInt fD = fregNo(i->ARMin.VCMovS.dst);
- UInt fM = fregNo(i->ARMin.VCMovS.src);
+ UInt fD = fregEnc(i->ARMin.VCMovS.dst);
+ UInt fM = fregEnc(i->ARMin.VCMovS.src);
vassert(cc < 16 && cc != ARMcc_AL);
UInt insn = XXXXXXXX(cc, X1110, BITS4(1,(fD & 1),1,1),
X0000,(fD >> 1),X1010,
}
case ARMin_VCvtSD: {
if (i->ARMin.VCvtSD.sToD) {
- UInt dD = dregNo(i->ARMin.VCvtSD.dst);
- UInt fM = fregNo(i->ARMin.VCvtSD.src);
+ UInt dD = dregEnc(i->ARMin.VCvtSD.dst);
+ UInt fM = fregEnc(i->ARMin.VCvtSD.src);
UInt insn = XXXXXXXX(0xE, X1110, X1011, X0111, dD, X1010,
BITS4(1,1, (fM & 1), 0),
(fM >> 1));
*p++ = insn;
goto done;
} else {
- UInt fD = fregNo(i->ARMin.VCvtSD.dst);
- UInt dM = dregNo(i->ARMin.VCvtSD.src);
+ UInt fD = fregEnc(i->ARMin.VCvtSD.dst);
+ UInt dM = dregEnc(i->ARMin.VCvtSD.src);
UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(fD & 1),1,1),
X0111, (fD >> 1),
X1011, X1100, dM);
}
}
case ARMin_VXferD: {
- UInt dD = dregNo(i->ARMin.VXferD.dD);
- UInt rHi = iregNo(i->ARMin.VXferD.rHi);
- UInt rLo = iregNo(i->ARMin.VXferD.rLo);
+ UInt dD = dregEnc(i->ARMin.VXferD.dD);
+ UInt rHi = iregEnc(i->ARMin.VXferD.rHi);
+ UInt rLo = iregEnc(i->ARMin.VXferD.rLo);
/* vmov dD, rLo, rHi is
E C 4 rHi rLo B (0,0,dD[4],1) dD[3:0]
vmov rLo, rHi, dD is
goto done;
}
case ARMin_VXferS: {
- UInt fD = fregNo(i->ARMin.VXferS.fD);
- UInt rLo = iregNo(i->ARMin.VXferS.rLo);
+ UInt fD = fregEnc(i->ARMin.VXferS.fD);
+ UInt rLo = iregEnc(i->ARMin.VXferS.rLo);
/* vmov fD, rLo is
E E 0 fD[4:1] rLo A (fD[0],0,0,1) 0
vmov rLo, fD is
Bool syned = i->ARMin.VCvtID.syned;
if (iToD && syned) {
// FSITOD: I32S-in-freg to F64-in-dreg
- UInt regF = fregNo(i->ARMin.VCvtID.src);
- UInt regD = dregNo(i->ARMin.VCvtID.dst);
+ UInt regF = fregEnc(i->ARMin.VCvtID.src);
+ UInt regD = dregEnc(i->ARMin.VCvtID.dst);
UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
X1011, BITS4(1,1,(regF & 1),0),
(regF >> 1) & 0xF);
}
if (iToD && (!syned)) {
// FUITOD: I32U-in-freg to F64-in-dreg
- UInt regF = fregNo(i->ARMin.VCvtID.src);
- UInt regD = dregNo(i->ARMin.VCvtID.dst);
+ UInt regF = fregEnc(i->ARMin.VCvtID.src);
+ UInt regD = dregEnc(i->ARMin.VCvtID.dst);
UInt insn = XXXXXXXX(0xE, X1110, X1011, X1000, regD,
X1011, BITS4(0,1,(regF & 1),0),
(regF >> 1) & 0xF);
}
if ((!iToD) && syned) {
// FTOSID: F64-in-dreg to I32S-in-freg
- UInt regD = dregNo(i->ARMin.VCvtID.src);
- UInt regF = fregNo(i->ARMin.VCvtID.dst);
+ UInt regD = dregEnc(i->ARMin.VCvtID.src);
+ UInt regF = fregEnc(i->ARMin.VCvtID.dst);
UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
X1101, (regF >> 1) & 0xF,
X1011, X0100, regD);
}
if ((!iToD) && (!syned)) {
// FTOUID: F64-in-dreg to I32U-in-freg
- UInt regD = dregNo(i->ARMin.VCvtID.src);
- UInt regF = fregNo(i->ARMin.VCvtID.dst);
+ UInt regD = dregEnc(i->ARMin.VCvtID.src);
+ UInt regF = fregEnc(i->ARMin.VCvtID.dst);
UInt insn = XXXXXXXX(0xE, X1110, BITS4(1,(regF & 1),1,1),
X1100, (regF >> 1) & 0xF,
X1011, X0100, regD);
}
case ARMin_FPSCR: {
Bool toFPSCR = i->ARMin.FPSCR.toFPSCR;
- UInt iReg = iregNo(i->ARMin.FPSCR.iReg);
+ UInt iReg = iregEnc(i->ARMin.FPSCR.iReg);
if (toFPSCR) {
/* fmxr fpscr, iReg is EEE1 iReg A10 */
*p++ = 0xEEE10A10 | ((iReg & 0xF) << 12);
}
case ARMin_NLdStQ: {
- UInt regD = qregNo(i->ARMin.NLdStQ.dQ) << 1;
+ UInt regD = qregEnc(i->ARMin.NLdStQ.dQ) << 1;
UInt regN, regM;
UInt D = regD >> 4;
UInt bL = i->ARMin.NLdStQ.isLoad ? 1 : 0;
vassert(hregClass(i->ARMin.NLdStQ.dQ) == HRcVec128);
regD &= 0xF;
if (i->ARMin.NLdStQ.amode->tag == ARMamN_RR) {
- regN = iregNo(i->ARMin.NLdStQ.amode->ARMamN.RR.rN);
- regM = iregNo(i->ARMin.NLdStQ.amode->ARMamN.RR.rM);
+ regN = iregEnc(i->ARMin.NLdStQ.amode->ARMamN.RR.rN);
+ regM = iregEnc(i->ARMin.NLdStQ.amode->ARMamN.RR.rM);
} else {
- regN = iregNo(i->ARMin.NLdStQ.amode->ARMamN.R.rN);
+ regN = iregEnc(i->ARMin.NLdStQ.amode->ARMamN.R.rN);
regM = 15;
}
insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
goto done;
}
case ARMin_NLdStD: {
- UInt regD = dregNo(i->ARMin.NLdStD.dD);
+ UInt regD = dregEnc(i->ARMin.NLdStD.dD);
UInt regN, regM;
UInt D = regD >> 4;
UInt bL = i->ARMin.NLdStD.isLoad ? 1 : 0;
vassert(hregClass(i->ARMin.NLdStD.dD) == HRcFlt64);
regD &= 0xF;
if (i->ARMin.NLdStD.amode->tag == ARMamN_RR) {
- regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rN);
- regM = iregNo(i->ARMin.NLdStD.amode->ARMamN.RR.rM);
+ regN = iregEnc(i->ARMin.NLdStD.amode->ARMamN.RR.rN);
+ regM = iregEnc(i->ARMin.NLdStD.amode->ARMamN.RR.rM);
} else {
- regN = iregNo(i->ARMin.NLdStD.amode->ARMamN.R.rN);
+ regN = iregEnc(i->ARMin.NLdStD.amode->ARMamN.R.rN);
regM = 15;
}
insn = XXXXXXXX(0xF, X0100, BITS4(0, D, bL, 0),
if (i->ARMin.NUnaryS.src->tag != ARMNRS_Scalar)
goto bad;
regD = (hregClass(i->ARMin.NUnaryS.dst->reg) == HRcVec128)
- ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1)
- : dregNo(i->ARMin.NUnaryS.dst->reg);
+ ? (qregEnc(i->ARMin.NUnaryS.dst->reg) << 1)
+ : dregEnc(i->ARMin.NUnaryS.dst->reg);
regM = (hregClass(i->ARMin.NUnaryS.src->reg) == HRcVec128)
- ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1)
- : dregNo(i->ARMin.NUnaryS.src->reg);
+ ? (qregEnc(i->ARMin.NUnaryS.src->reg) << 1)
+ : dregEnc(i->ARMin.NUnaryS.src->reg);
D = regD >> 4;
M = regM >> 4;
regD &= 0xf;
*p++ = insn;
goto done;
case ARMneon_SETELEM:
- regD = Q ? (qregNo(i->ARMin.NUnaryS.dst->reg) << 1) :
- dregNo(i->ARMin.NUnaryS.dst->reg);
- regM = iregNo(i->ARMin.NUnaryS.src->reg);
+ regD = Q ? (qregEnc(i->ARMin.NUnaryS.dst->reg) << 1) :
+ dregEnc(i->ARMin.NUnaryS.dst->reg);
+ regM = iregEnc(i->ARMin.NUnaryS.src->reg);
M = regM >> 4;
D = regD >> 4;
regM &= 0xF;
*p++ = insn;
goto done;
case ARMneon_GETELEMU:
- regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
- dregNo(i->ARMin.NUnaryS.src->reg);
- regD = iregNo(i->ARMin.NUnaryS.dst->reg);
+ regM = Q ? (qregEnc(i->ARMin.NUnaryS.src->reg) << 1) :
+ dregEnc(i->ARMin.NUnaryS.src->reg);
+ regD = iregEnc(i->ARMin.NUnaryS.dst->reg);
M = regM >> 4;
D = regD >> 4;
regM &= 0xF;
*p++ = insn;
goto done;
case ARMneon_GETELEMS:
- regM = Q ? (qregNo(i->ARMin.NUnaryS.src->reg) << 1) :
- dregNo(i->ARMin.NUnaryS.src->reg);
- regD = iregNo(i->ARMin.NUnaryS.dst->reg);
+ regM = Q ? (qregEnc(i->ARMin.NUnaryS.src->reg) << 1) :
+ dregEnc(i->ARMin.NUnaryS.src->reg);
+ regD = iregEnc(i->ARMin.NUnaryS.dst->reg);
M = regM >> 4;
D = regD >> 4;
regM &= 0xF;
case ARMin_NUnary: {
UInt Q = i->ARMin.NUnary.Q ? 1 : 0;
UInt regD = (hregClass(i->ARMin.NUnary.dst) == HRcVec128)
- ? (qregNo(i->ARMin.NUnary.dst) << 1)
- : dregNo(i->ARMin.NUnary.dst);
+ ? (qregEnc(i->ARMin.NUnary.dst) << 1)
+ : dregEnc(i->ARMin.NUnary.dst);
UInt regM, M;
UInt D = regD >> 4;
UInt sz1 = i->ARMin.NUnary.size >> 1;
UInt F = 0; /* TODO: floating point EQZ ??? */
if (i->ARMin.NUnary.op != ARMneon_DUP) {
regM = (hregClass(i->ARMin.NUnary.src) == HRcVec128)
- ? (qregNo(i->ARMin.NUnary.src) << 1)
- : dregNo(i->ARMin.NUnary.src);
+ ? (qregEnc(i->ARMin.NUnary.src) << 1)
+ : dregEnc(i->ARMin.NUnary.src);
M = regM >> 4;
} else {
- regM = iregNo(i->ARMin.NUnary.src);
+ regM = iregEnc(i->ARMin.NUnary.src);
M = regM >> 4;
}
regD &= 0xF;
case ARMin_NDual: {
UInt Q = i->ARMin.NDual.Q ? 1 : 0;
UInt regD = (hregClass(i->ARMin.NDual.arg1) == HRcVec128)
- ? (qregNo(i->ARMin.NDual.arg1) << 1)
- : dregNo(i->ARMin.NDual.arg1);
+ ? (qregEnc(i->ARMin.NDual.arg1) << 1)
+ : dregEnc(i->ARMin.NDual.arg1);
UInt regM = (hregClass(i->ARMin.NDual.arg2) == HRcVec128)
- ? (qregNo(i->ARMin.NDual.arg2) << 1)
- : dregNo(i->ARMin.NDual.arg2);
+ ? (qregEnc(i->ARMin.NDual.arg2) << 1)
+ : dregEnc(i->ARMin.NDual.arg2);
UInt D = regD >> 4;
UInt M = regM >> 4;
UInt sz1 = i->ARMin.NDual.size >> 1;
case ARMin_NBinary: {
UInt Q = i->ARMin.NBinary.Q ? 1 : 0;
UInt regD = (hregClass(i->ARMin.NBinary.dst) == HRcVec128)
- ? (qregNo(i->ARMin.NBinary.dst) << 1)
- : dregNo(i->ARMin.NBinary.dst);
+ ? (qregEnc(i->ARMin.NBinary.dst) << 1)
+ : dregEnc(i->ARMin.NBinary.dst);
UInt regN = (hregClass(i->ARMin.NBinary.argL) == HRcVec128)
- ? (qregNo(i->ARMin.NBinary.argL) << 1)
- : dregNo(i->ARMin.NBinary.argL);
+ ? (qregEnc(i->ARMin.NBinary.argL) << 1)
+ : dregEnc(i->ARMin.NBinary.argL);
UInt regM = (hregClass(i->ARMin.NBinary.argR) == HRcVec128)
- ? (qregNo(i->ARMin.NBinary.argR) << 1)
- : dregNo(i->ARMin.NBinary.argR);
+ ? (qregEnc(i->ARMin.NBinary.argR) << 1)
+ : dregEnc(i->ARMin.NBinary.argR);
UInt sz1 = i->ARMin.NBinary.size >> 1;
UInt sz2 = i->ARMin.NBinary.size & 1;
UInt D = regD >> 4;
case ARMin_NShift: {
UInt Q = i->ARMin.NShift.Q ? 1 : 0;
UInt regD = (hregClass(i->ARMin.NShift.dst) == HRcVec128)
- ? (qregNo(i->ARMin.NShift.dst) << 1)
- : dregNo(i->ARMin.NShift.dst);
+ ? (qregEnc(i->ARMin.NShift.dst) << 1)
+ : dregEnc(i->ARMin.NShift.dst);
UInt regM = (hregClass(i->ARMin.NShift.argL) == HRcVec128)
- ? (qregNo(i->ARMin.NShift.argL) << 1)
- : dregNo(i->ARMin.NShift.argL);
+ ? (qregEnc(i->ARMin.NShift.argL) << 1)
+ : dregEnc(i->ARMin.NShift.argL);
UInt regN = (hregClass(i->ARMin.NShift.argR) == HRcVec128)
- ? (qregNo(i->ARMin.NShift.argR) << 1)
- : dregNo(i->ARMin.NShift.argR);
+ ? (qregEnc(i->ARMin.NShift.argR) << 1)
+ : dregEnc(i->ARMin.NShift.argR);
UInt sz1 = i->ARMin.NShift.size >> 1;
UInt sz2 = i->ARMin.NShift.size & 1;
UInt D = regD >> 4;
vassert(amt >= 1 && amt <= 63);
vassert(hregClass(regDreg) == HRcFlt64);
vassert(hregClass(regMreg) == HRcFlt64);
- UInt regD = dregNo(regDreg);
- UInt regM = dregNo(regMreg);
+ UInt regD = dregEnc(regDreg);
+ UInt regM = dregEnc(regMreg);
UInt D = (regD >> 4) & 1;
UInt Vd = regD & 0xF;
UInt L = 1;
}
case ARMin_NeonImm: {
UInt Q = (hregClass(i->ARMin.NeonImm.dst) == HRcVec128) ? 1 : 0;
- UInt regD = Q ? (qregNo(i->ARMin.NeonImm.dst) << 1) :
- dregNo(i->ARMin.NeonImm.dst);
+ UInt regD = Q ? (qregEnc(i->ARMin.NeonImm.dst) << 1) :
+ dregEnc(i->ARMin.NeonImm.dst);
UInt D = regD >> 4;
UInt imm = i->ARMin.NeonImm.imm->imm8;
UInt tp = i->ARMin.NeonImm.imm->type;
}
case ARMin_NCMovQ: {
UInt cc = (UInt)i->ARMin.NCMovQ.cond;
- UInt qM = qregNo(i->ARMin.NCMovQ.src) << 1;
- UInt qD = qregNo(i->ARMin.NCMovQ.dst) << 1;
+ UInt qM = qregEnc(i->ARMin.NCMovQ.src) << 1;
+ UInt qD = qregEnc(i->ARMin.NCMovQ.dst) << 1;
UInt vM = qM & 0xF;
UInt vD = qD & 0xF;
UInt M = (qM >> 4) & 1;
goto done;
}
case ARMin_Add32: {
- UInt regD = iregNo(i->ARMin.Add32.rD);
- UInt regN = iregNo(i->ARMin.Add32.rN);
+ UInt regD = iregEnc(i->ARMin.Add32.rD);
+ UInt regN = iregEnc(i->ARMin.Add32.rN);
UInt imm32 = i->ARMin.Add32.imm32;
vassert(regD != regN);
/* MOV regD, imm32 */
- p = imm32_to_iregNo((UInt *)p, regD, imm32);
+ p = imm32_to_ireg((UInt *)p, regD, imm32);
/* ADD regD, regN, regD */
UInt insn = XXXXXXXX(0xE, 0, X1000, regN, regD, 0, 0, regD);
*p++ = insn;
adc r11, r11, #0
str r11, [r12+4]
*/
- p = imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555);
+ p = imm32_to_ireg_EXACTLY2(p, /*r*/12, 0x65556555);
*p++ = 0xE59CB000;
*p++ = 0xE29BB001;
*p++ = 0xE58CB000;
movt r12, hi16(disp_cp_chain_me_to_EXPECTED)
blx r12
viz
- <8 bytes generated by imm32_to_iregNo_EXACTLY2>
+ <8 bytes generated by imm32_to_ireg_EXACTLY2>
E1 2F FF 3C
*/
UInt* p = (UInt*)place_to_chain;
vassert(0 == (3 & (HWord)p));
- vassert(is_imm32_to_iregNo_EXACTLY2(
+ vassert(is_imm32_to_ireg_EXACTLY2(
p, /*r*/12, (UInt)(Addr)disp_cp_chain_me_EXPECTED));
vassert(p[2] == 0xE12FFF3C);
/* And what we want to change it to is either:
movt r12, hi16(place_to_jump_to)
bx r12
viz
- <8 bytes generated by imm32_to_iregNo_EXACTLY2>
+ <8 bytes generated by imm32_to_ireg_EXACTLY2>
E1 2F FF 1C
---OR---
in the case where the displacement falls within 26 bits
p[1] = 0xFF000000;
p[2] = 0xFF000000;
} else {
- (void)imm32_to_iregNo_EXACTLY2(
+ (void)imm32_to_ireg_EXACTLY2(
p, /*r*/12, (UInt)(Addr)place_to_jump_to);
p[2] = 0xE12FFF1C;
}
movt r12, lo16(place_to_jump_to_EXPECTED)
bx r12
viz
- <8 bytes generated by imm32_to_iregNo_EXACTLY2>
+ <8 bytes generated by imm32_to_ireg_EXACTLY2>
E1 2F FF 1C
---OR---
in the case where the displacement falls within 26 bits
vassert(0 == (3 & (HWord)p));
Bool valid = False;
- if (is_imm32_to_iregNo_EXACTLY2(
+ if (is_imm32_to_ireg_EXACTLY2(
p, /*r*/12, (UInt)(Addr)place_to_jump_to_EXPECTED)
&& p[2] == 0xE12FFF1C) {
valid = True; /* it's the long form */
movt r12, hi16(disp_cp_chain_me)
blx r12
viz
- <8 bytes generated by imm32_to_iregNo_EXACTLY2>
+ <8 bytes generated by imm32_to_ireg_EXACTLY2>
E1 2F FF 3C
*/
- (void)imm32_to_iregNo_EXACTLY2(
+ (void)imm32_to_ireg_EXACTLY2(
p, /*r*/12, (UInt)(Addr)disp_cp_chain_me);
p[2] = 0xE12FFF3C;
VexInvalRange vir = {(HWord)p, 12};
vassert(sizeof(ULong*) == 4);
UInt* p = (UInt*)place_to_patch;
vassert(0 == (3 & (HWord)p));
- vassert(is_imm32_to_iregNo_EXACTLY2(p, /*r*/12, 0x65556555));
+ vassert(is_imm32_to_ireg_EXACTLY2(p, /*r*/12, 0x65556555));
vassert(p[2] == 0xE59CB000);
vassert(p[3] == 0xE29BB001);
vassert(p[4] == 0xE58CB000);
vassert(p[5] == 0xE59CB004);
vassert(p[6] == 0xE2ABB000);
vassert(p[7] == 0xE58CB004);
- imm32_to_iregNo_EXACTLY2(p, /*r*/12,
- (UInt)(Addr)location_of_counter);
+ imm32_to_ireg_EXACTLY2(p, /*r*/12, (UInt)(Addr)location_of_counter);
VexInvalRange vir = {(HWord)p, 8};
return vir;
}
/* --------- Registers. --------- */
-/* The usual HReg abstraction.
- There are 16 general purpose regs.
-*/
+#define ST_IN static inline
+ST_IN HReg hregARM_R4 ( void ) { return mkHReg(False, HRcInt32, 4, 0); }
+ST_IN HReg hregARM_R5 ( void ) { return mkHReg(False, HRcInt32, 5, 1); }
+ST_IN HReg hregARM_R6 ( void ) { return mkHReg(False, HRcInt32, 6, 2); }
+ST_IN HReg hregARM_R7 ( void ) { return mkHReg(False, HRcInt32, 7, 3); }
+ST_IN HReg hregARM_R10 ( void ) { return mkHReg(False, HRcInt32, 10, 4); }
+ST_IN HReg hregARM_R11 ( void ) { return mkHReg(False, HRcInt32, 11, 5); }
+
+ST_IN HReg hregARM_R0 ( void ) { return mkHReg(False, HRcInt32, 0, 6); }
+ST_IN HReg hregARM_R1 ( void ) { return mkHReg(False, HRcInt32, 1, 7); }
+ST_IN HReg hregARM_R2 ( void ) { return mkHReg(False, HRcInt32, 2, 8); }
+ST_IN HReg hregARM_R3 ( void ) { return mkHReg(False, HRcInt32, 3, 9); }
+ST_IN HReg hregARM_R9 ( void ) { return mkHReg(False, HRcInt32, 9, 10); }
+
+ST_IN HReg hregARM_D8 ( void ) { return mkHReg(False, HRcFlt64, 8, 11); }
+ST_IN HReg hregARM_D9 ( void ) { return mkHReg(False, HRcFlt64, 9, 12); }
+ST_IN HReg hregARM_D10 ( void ) { return mkHReg(False, HRcFlt64, 10, 13); }
+ST_IN HReg hregARM_D11 ( void ) { return mkHReg(False, HRcFlt64, 11, 14); }
+ST_IN HReg hregARM_D12 ( void ) { return mkHReg(False, HRcFlt64, 12, 15); }
+
+ST_IN HReg hregARM_S26 ( void ) { return mkHReg(False, HRcFlt32, 26, 16); }
+ST_IN HReg hregARM_S27 ( void ) { return mkHReg(False, HRcFlt32, 27, 17); }
+ST_IN HReg hregARM_S28 ( void ) { return mkHReg(False, HRcFlt32, 28, 18); }
+ST_IN HReg hregARM_S29 ( void ) { return mkHReg(False, HRcFlt32, 29, 19); }
+ST_IN HReg hregARM_S30 ( void ) { return mkHReg(False, HRcFlt32, 30, 20); }
+
+ST_IN HReg hregARM_Q8 ( void ) { return mkHReg(False, HRcVec128, 8, 21); }
+ST_IN HReg hregARM_Q9 ( void ) { return mkHReg(False, HRcVec128, 9, 22); }
+ST_IN HReg hregARM_Q10 ( void ) { return mkHReg(False, HRcVec128, 10, 23); }
+ST_IN HReg hregARM_Q11 ( void ) { return mkHReg(False, HRcVec128, 11, 24); }
+ST_IN HReg hregARM_Q12 ( void ) { return mkHReg(False, HRcVec128, 12, 25); }
+
+ST_IN HReg hregARM_R8 ( void ) { return mkHReg(False, HRcInt32, 8, 26); }
+ST_IN HReg hregARM_R12 ( void ) { return mkHReg(False, HRcInt32, 12, 27); }
+ST_IN HReg hregARM_R13 ( void ) { return mkHReg(False, HRcInt32, 13, 28); }
+ST_IN HReg hregARM_R14 ( void ) { return mkHReg(False, HRcInt32, 14, 29); }
+ST_IN HReg hregARM_R15 ( void ) { return mkHReg(False, HRcInt32, 15, 30); }
+ST_IN HReg hregARM_Q13 ( void ) { return mkHReg(False, HRcVec128, 13, 31); }
+ST_IN HReg hregARM_Q14 ( void ) { return mkHReg(False, HRcVec128, 14, 32); }
+ST_IN HReg hregARM_Q15 ( void ) { return mkHReg(False, HRcVec128, 15, 33); }
+#undef ST_IN
extern void ppHRegARM ( HReg );
-extern HReg hregARM_R0 ( void );
-extern HReg hregARM_R1 ( void );
-extern HReg hregARM_R2 ( void );
-extern HReg hregARM_R3 ( void );
-extern HReg hregARM_R4 ( void );
-extern HReg hregARM_R5 ( void );
-extern HReg hregARM_R6 ( void );
-extern HReg hregARM_R7 ( void );
-extern HReg hregARM_R8 ( void );
-extern HReg hregARM_R9 ( void );
-extern HReg hregARM_R10 ( void );
-extern HReg hregARM_R11 ( void );
-extern HReg hregARM_R12 ( void );
-extern HReg hregARM_R13 ( void );
-extern HReg hregARM_R14 ( void );
-extern HReg hregARM_R15 ( void );
-extern HReg hregARM_D8 ( void );
-extern HReg hregARM_D9 ( void );
-extern HReg hregARM_D10 ( void );
-extern HReg hregARM_D11 ( void );
-extern HReg hregARM_D12 ( void );
-extern HReg hregARM_S26 ( void );
-extern HReg hregARM_S27 ( void );
-extern HReg hregARM_S28 ( void );
-extern HReg hregARM_S29 ( void );
-extern HReg hregARM_S30 ( void );
-extern HReg hregARM_Q8 ( void );
-extern HReg hregARM_Q9 ( void );
-extern HReg hregARM_Q10 ( void );
-extern HReg hregARM_Q11 ( void );
-extern HReg hregARM_Q12 ( void );
-extern HReg hregARM_Q13 ( void );
-extern HReg hregARM_Q14 ( void );
-extern HReg hregARM_Q15 ( void );
-
/* Number of registers used arg passing in function calls */
#define ARM_N_ARGREGS 4 /* r0, r1, r2, r3 */
extern void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
-extern void getAllocableRegs_ARM ( Int*, HReg** );
+extern const RRegUniverse* getRRegUniverse_ARM ( void );
+
extern HInstrArray* iselSB_ARM ( const IRSB*,
VexArch,
const VexArchInfo*,
ppARMInstr(instr);
vex_printf("\n");
}
-#if 0
- if (instr->tag == ARMin_NUnary || instr->tag == ARMin_NBinary
- || instr->tag == ARMin_NUnaryS || instr->tag == ARMin_NBinaryS
- || instr->tag == ARMin_NDual || instr->tag == ARMin_NShift) {
- ppARMInstr(instr);
- vex_printf("\n");
- }
-#endif
}
static HReg newVRegI ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcInt32, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegD ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt64, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegF ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt32, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt32, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegV ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
case Ity_I1:
case Ity_I8:
case Ity_I16:
- case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break;
+ case Ity_I32: hreg = mkHReg(True, HRcInt32, 0, j++); break;
case Ity_I64:
if (hwcaps_host & VEX_HWCAPS_ARM_NEON) {
- hreg = mkHReg(j++, HRcFlt64, True);
+ hreg = mkHReg(True, HRcFlt64, 0, j++);
} else {
- hregHI = mkHReg(j++, HRcInt32, True);
- hreg = mkHReg(j++, HRcInt32, True);
+ hregHI = mkHReg(True, HRcInt32, 0, j++);
+ hreg = mkHReg(True, HRcInt32, 0, j++);
}
break;
- case Ity_F32: hreg = mkHReg(j++, HRcFlt32, True); break;
- case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break;
- case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break;
+ case Ity_F32: hreg = mkHReg(True, HRcFlt32, 0, j++); break;
+ case Ity_F64: hreg = mkHReg(True, HRcFlt64, 0, j++); break;
+ case Ity_V128: hreg = mkHReg(True, HRcVec128, 0, j++); break;
default: ppIRType(bb->tyenv->types[i]);
vpanic("iselBB: IRTemp type");
}
/*---------------------------------------------------------------*/
/*--- end host_arm_isel.c ---*/
/*---------------------------------------------------------------*/
+
/* An array of the following structs (rreg_state) comprises the
running state of the allocator. It indicates what the current
disposition of each allocatable real register is. The array gets
- updated as the allocator processes instructions. */
+ updated as the allocator processes instructions. The identity of
+ the register is not recorded here, because the index of this
+ structure in doRegisterAllocation()'s |rreg_state| is the index
+ number of the register, and the register itself can be extracted
+ from the RRegUniverse supplied to doRegisterAllocation(). */
typedef
struct {
/* ------ FIELDS WHICH DO NOT CHANGE ------ */
- /* Which rreg is this for? */
- HReg rreg;
/* Is this involved in any HLRs? (only an optimisation hint) */
Bool has_hlrs;
/* ------ FIELDS WHICH DO CHANGE ------ */
#define IS_VALID_RREGNO(_zz) ((_zz) >= 0 && (_zz) < n_rregs)
-/* Does this instruction mention a particular reg? */
-static Bool instrMentionsReg (
- void (*getRegUsage) (HRegUsage*, const HInstr*, Bool),
- HInstr* instr,
- HReg r,
- Bool mode64
-)
-{
- Int i;
- HRegUsage reg_usage;
- (*getRegUsage)(®_usage, instr, mode64);
- for (i = 0; i < reg_usage.n_used; i++)
- if (sameHReg(reg_usage.hreg[i], r))
- return True;
- return False;
-}
-
-
/* Search forward from some given point in the incoming instruction
sequence. Point is to select a virtual register to spill, by
finding the vreg which is mentioned as far ahead as possible, in
caller to arbitrarily restrict the set of spill candidates to be
considered.
+ To do this we don't actually need to see the incoming instruction
+ stream. Rather, what we need us the HRegUsage records for the
+ incoming instruction stream. Hence that is passed in.
+
Returns an index into the state array indicating the (v,r) pair to
spill, or -1 if none was found. */
static
Int findMostDistantlyMentionedVReg (
- void (*getRegUsage) (HRegUsage*, const HInstr*, Bool),
- HInstrArray* instrs_in,
+ HRegUsage* reg_usages_in,
Int search_from_instr,
+ Int num_instrs,
RRegState* state,
- Int n_state,
- Bool mode64
+ Int n_state
)
{
Int k, m;
if (!state[k].is_spill_cand)
continue;
vassert(state[k].disp == Bound);
- for (m = search_from_instr; m < instrs_in->arr_used; m++) {
- if (instrMentionsReg(getRegUsage,
- instrs_in->arr[m], state[k].vreg, mode64))
+ for (m = search_from_instr; m < num_instrs; m++) {
+ if (HRegUsage__contains(®_usages_in[m], state[k].vreg))
break;
}
if (m > furthest) {
/* Check that this vreg has been assigned a sane spill offset. */
-static inline void sanity_check_spill_offset ( VRegLR* vreg )
+inline
+static void sanity_check_spill_offset ( VRegLR* vreg )
{
switch (vreg->reg_class) {
case HRcVec128: case HRcFlt64:
/* Double the size of the real-reg live-range array, if needed. */
-static void ensureRRLRspace ( RRegLR** info, Int* size, Int used )
+__attribute__((noinline))
+static void ensureRRLRspace_SLOW ( RRegLR** info, Int* size, Int used )
{
Int k;
RRegLR* arr2;
- if (used < *size) return;
if (0)
vex_printf("ensureRRISpace: %d -> %d\n", *size, 2 * *size);
vassert(used == *size);
*size *= 2;
*info = arr2;
}
+inline
+static void ensureRRLRspace ( RRegLR** info, Int* size, Int used )
+{
+ if (LIKELY(used < *size)) return;
+ ensureRRLRspace_SLOW(info, size, used);
+}
/* Sort an array of RRegLR entries by either the .live_after or
}
+/* Compute the index of the highest and lowest 1 in a ULong,
+ respectively. Results are undefined if the argument is zero.
+ Don't pass it zero :) */
+static inline UInt ULong__maxIndex ( ULong w64 ) {
+ return 63 - __builtin_clzll(w64);
+}
+
+static inline UInt ULong__minIndex ( ULong w64 ) {
+ return __builtin_ctzll(w64);
+}
+
+
+/* Vectorised memset, copied from Valgrind's m_libcbase.c. */
+static void* local_memset ( void *destV, Int c, SizeT sz )
+{
+# define IS_4_ALIGNED(aaa_p) (0 == (((HWord)(aaa_p)) & ((HWord)0x3)))
+
+ UInt c4;
+ UChar* d = destV;
+ UChar uc = c;
+
+ while ((!IS_4_ALIGNED(d)) && sz >= 1) {
+ d[0] = uc;
+ d++;
+ sz--;
+ }
+ if (sz == 0)
+ return destV;
+ c4 = uc;
+ c4 |= (c4 << 8);
+ c4 |= (c4 << 16);
+ while (sz >= 16) {
+ ((UInt*)d)[0] = c4;
+ ((UInt*)d)[1] = c4;
+ ((UInt*)d)[2] = c4;
+ ((UInt*)d)[3] = c4;
+ d += 16;
+ sz -= 16;
+ }
+ while (sz >= 4) {
+ ((UInt*)d)[0] = c4;
+ d += 4;
+ sz -= 4;
+ }
+ while (sz >= 1) {
+ d[0] = c;
+ d++;
+ sz--;
+ }
+ return destV;
+
+# undef IS_4_ALIGNED
+}
+
+
/* A target-independent register allocator. Requires various
functions which it uses to deal abstractly with instructions and
registers, since it cannot have any target-specific knowledge.
/* Incoming virtual-registerised code. */
HInstrArray* instrs_in,
- /* An array listing all the real registers the allocator may use,
- in no particular order. */
- HReg* available_real_regs,
- Int n_available_real_regs,
+ /* The real-register universe to use. This contains facts about
+ real registers, one of which is the set of registers available
+ for allocation. */
+ const RRegUniverse* univ,
/* Return True iff the given insn is a reg-reg move, in which
case also return the src and dst regs. */
const Bool eq_spill_opt = True;
- /* Iterators and temporaries. */
- Int ii, j, k, m, spillee, k_suboptimal;
- HReg rreg, vreg, vregS, vregD;
- HRegUsage reg_usage;
-
/* Info on vregs and rregs. Computed once and remains
unchanged. */
Int n_vregs;
Int rreg_lrs_la_next;
Int rreg_lrs_db_next;
+ /* Info on register usage in the incoming instruction array.
+ Computed once and remains unchanged, more or less; updated
+ sometimes by the direct-reload optimisation. */
+ HRegUsage* reg_usage_arr; /* [0 .. instrs_in->arr_used-1] */
+
/* Used when constructing vreg_lrs (for allocating stack
slots). */
- Int ss_busy_until_before[N_SPILL64S];
+ Short ss_busy_until_before[N_SPILL64S];
/* Used when constructing rreg_lrs. */
Int* rreg_live_after;
Int z, q; \
for (z = 0; z < n_rregs; z++) { \
vex_printf(" rreg_state[%2d] = ", z); \
- (*ppReg)(rreg_state[z].rreg); \
+ (*ppReg)(univ->regs[z]); \
vex_printf(" \t"); \
switch (rreg_state[z].disp) { \
case Free: vex_printf("Free\n"); break; \
/* ... and initialise running state. */
/* n_rregs is no more than a short name for n_available_real_regs. */
- n_rregs = n_available_real_regs;
+ n_rregs = univ->allocable;
n_vregs = instrs_in->n_vregs;
/* If this is not so, vreg_state entries will overflow. */
vassert(n_vregs < 32767);
+ /* If this is not so, the universe we have is nonsensical. */
+ vassert(n_rregs > 0);
+
rreg_state = LibVEX_Alloc_inline(n_rregs * sizeof(RRegState));
vreg_state = LibVEX_Alloc_inline(n_vregs * sizeof(Short));
- for (j = 0; j < n_rregs; j++) {
- rreg_state[j].rreg = available_real_regs[j];
+ for (Int j = 0; j < n_rregs; j++) {
rreg_state[j].has_hlrs = False;
rreg_state[j].disp = Free;
rreg_state[j].vreg = INVALID_HREG;
rreg_state[j].eq_spill_slot = False;
}
- for (j = 0; j < n_vregs; j++)
+ for (Int j = 0; j < n_vregs; j++)
vreg_state[j] = INVALID_RREG_NO;
if (n_vregs > 0)
vreg_lrs = LibVEX_Alloc_inline(sizeof(VRegLR) * n_vregs);
- for (j = 0; j < n_vregs; j++) {
+ for (Int j = 0; j < n_vregs; j++) {
vreg_lrs[j].live_after = INVALID_INSTRNO;
vreg_lrs[j].dead_before = INVALID_INSTRNO;
vreg_lrs[j].spill_offset = 0;
vreg_lrs[j].reg_class = HRcINVALID;
}
+ /* An array to hold the reg-usage info for the incoming
+ instructions. */
+ reg_usage_arr
+ = LibVEX_Alloc_inline(sizeof(HRegUsage) * instrs_in->arr_used-1);
+
/* ------ end of SET UP TO COMPUTE VREG LIVE RANGES ------ */
/* ------ start of SET UP TO COMPUTE RREG LIVE RANGES ------ */
/* We'll need to track live range start/end points seperately for
each rreg. Sigh. */
- vassert(n_available_real_regs > 0);
- rreg_live_after = LibVEX_Alloc_inline(n_available_real_regs * sizeof(Int));
- rreg_dead_before = LibVEX_Alloc_inline(n_available_real_regs * sizeof(Int));
+ vassert(n_rregs > 0);
+ rreg_live_after = LibVEX_Alloc_inline(n_rregs * sizeof(Int));
+ rreg_dead_before = LibVEX_Alloc_inline(n_rregs * sizeof(Int));
- for (j = 0; j < n_available_real_regs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
rreg_live_after[j] =
rreg_dead_before[j] = INVALID_INSTRNO;
}
/* ------ start of ITERATE OVER INSNS ------ */
- for (ii = 0; ii < instrs_in->arr_used; ii++) {
+ for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
- (*getRegUsage)( ®_usage, instrs_in->arr[ii], mode64 );
+ (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
-# if 0
- vex_printf("\n%d stage1: ", ii);
- (*ppInstr)(instrs_in->arr[ii], mode64);
- vex_printf("\n");
- ppHRegUsage(®_usage);
-# endif
+ if (0) {
+ vex_printf("\n%d stage1: ", ii);
+ (*ppInstr)(instrs_in->arr[ii], mode64);
+ vex_printf("\n");
+ ppHRegUsage(univ, ®_usage_arr[ii]);
+ }
/* ------ start of DEAL WITH VREG LIVE RANGES ------ */
- /* for each reg mentioned in the insn ... */
- for (j = 0; j < reg_usage.n_used; j++) {
+ /* for each virtual reg mentioned in the insn ... */
+ for (Int j = 0; j < reg_usage_arr[ii].n_vRegs; j++) {
- vreg = reg_usage.hreg[j];
- /* only interested in virtual registers right now. */
- if (!hregIsVirtual(vreg))
- continue;
- k = hregNumber(vreg);
+ HReg vreg = reg_usage_arr[ii].vRegs[j];
+ vassert(hregIsVirtual(vreg));
+
+ Int k = hregIndex(vreg);
if (k < 0 || k >= n_vregs) {
vex_printf("\n");
(*ppInstr)(instrs_in->arr[ii], mode64);
}
/* Now consider live ranges. */
- switch (reg_usage.mode[j]) {
+ switch (reg_usage_arr[ii].vMode[j]) {
case HRmRead:
if (vreg_lrs[k].live_after == INVALID_INSTRNO) {
vex_printf("\n\nOFFENDING VREG = %d\n", k);
vpanic("doRegisterAllocation(1)");
} /* switch */
- } /* iterate over registers */
+ } /* iterate over virtual registers */
/* ------ end of DEAL WITH VREG LIVE RANGES ------ */
/* ------ start of DEAL WITH RREG LIVE RANGES ------ */
- /* for each reg mentioned in the insn ... */
- for (j = 0; j < reg_usage.n_used; j++) {
-
- /* Dummy initialisations of flush_la and flush_db to avoid
- possible bogus uninit-var warnings from gcc. */
- Int flush_la = INVALID_INSTRNO, flush_db = INVALID_INSTRNO;
- Bool flush;
+ /* If this doesn't hold, the following iteration over real registers
+ will fail miserably. */
+ vassert(N_RREGUNIVERSE_REGS == 64);
+
+ const ULong rRead = reg_usage_arr[ii].rRead;
+ const ULong rWritten = reg_usage_arr[ii].rWritten;
+ const ULong rMentioned = rRead | rWritten;
+
+ UInt rReg_minIndex;
+ UInt rReg_maxIndex;
+ if (rMentioned == 0) {
+ /* There are no real register uses in this insn. Set
+ rReg_{min,max}Index so that the following loop doesn't iterate
+ at all, so as to avoid wasting time. */
+ rReg_minIndex = 1;
+ rReg_maxIndex = 0;
+ } else {
+ rReg_minIndex = ULong__minIndex(rMentioned);
+ rReg_maxIndex = ULong__maxIndex(rMentioned);
+ /* Don't bother to look at registers which are not available
+ to the allocator. We asserted above that n_rregs > 0, so
+ n_rregs-1 is safe. */
+ if (rReg_maxIndex >= n_rregs)
+ rReg_maxIndex = n_rregs-1;
+ }
- rreg = reg_usage.hreg[j];
+ /* for each allocator-available real reg mentioned in the insn ... */
+ /* Note. We are allocating only over the real regs available to
+ the allocator. Others, eg the stack or baseblock pointers,
+ are unavailable to allocation and so we never visit them.
+ Hence the iteration is cut off at n_rregs-1, since n_rregs ==
+ univ->allocable. */
+ for (Int j = rReg_minIndex; j <= rReg_maxIndex; j++) {
- /* only interested in real registers right now. */
- if (hregIsVirtual(rreg))
+ const ULong jMask = 1ULL << j;
+ if (LIKELY((rMentioned & jMask) == 0))
continue;
- /* Furthermore, we're not interested in this rreg unless it's
- one of the allocatable ones. For example, it could be a
- stack pointer register, or some other register beyond our
- control, in which case we should just ignore it. */
- for (k = 0; k < n_available_real_regs; k++)
- if (sameHReg(available_real_regs[k], rreg))
- break;
- if (k == n_available_real_regs)
- continue; /* not found -- ignore. */
- flush = False;
- switch (reg_usage.mode[j]) {
- case HRmWrite:
- flush_la = rreg_live_after[k];
- flush_db = rreg_dead_before[k];
- if (flush_la != INVALID_INSTRNO
- && flush_db != INVALID_INSTRNO)
- flush = True;
- rreg_live_after[k] = ii;
- rreg_dead_before[k] = ii+1;
- break;
- case HRmRead:
- if (rreg_live_after[k] == INVALID_INSTRNO) {
- vex_printf("\nOFFENDING RREG = ");
- (*ppReg)(available_real_regs[k]);
- vex_printf("\n");
- vex_printf("\nOFFENDING instr = ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
- vex_printf("\n");
- vpanic("doRegisterAllocation: "
- "first event for rreg is Read");
- }
- rreg_dead_before[k] = ii+1;
- break;
- case HRmModify:
- if (rreg_live_after[k] == INVALID_INSTRNO) {
- vex_printf("\nOFFENDING RREG = ");
- (*ppReg)(available_real_regs[k]);
- vex_printf("\n");
- vex_printf("\nOFFENDING instr = ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
- vex_printf("\n");
- vpanic("doRegisterAllocation: "
- "first event for rreg is Modify");
- }
- rreg_dead_before[k] = ii+1;
- break;
- default:
- vpanic("doRegisterAllocation(2)");
+ const Bool isR = (rRead & jMask) != 0;
+ const Bool isW = (rWritten & jMask) != 0;
+
+ /* Dummy initialisations of flush_la and flush_db to avoid
+ possible bogus uninit-var warnings from gcc. */
+ Int flush_la = INVALID_INSTRNO, flush_db = INVALID_INSTRNO;
+ Bool flush = False;
+
+ if (isW && !isR) {
+ flush_la = rreg_live_after[j];
+ flush_db = rreg_dead_before[j];
+ if (flush_la != INVALID_INSTRNO && flush_db != INVALID_INSTRNO)
+ flush = True;
+ rreg_live_after[j] = ii;
+ rreg_dead_before[j] = ii+1;
+ } else if (!isW && isR) {
+ if (rreg_live_after[j] == INVALID_INSTRNO) {
+ vex_printf("\nOFFENDING RREG = ");
+ (*ppReg)(univ->regs[j]);
+ vex_printf("\n");
+ vex_printf("\nOFFENDING instr = ");
+ (*ppInstr)(instrs_in->arr[ii], mode64);
+ vex_printf("\n");
+ vpanic("doRegisterAllocation: "
+ "first event for rreg is Read");
+ }
+ rreg_dead_before[j] = ii+1;
+ } else {
+ vassert(isR && isW);
+ if (rreg_live_after[j] == INVALID_INSTRNO) {
+ vex_printf("\nOFFENDING RREG = ");
+ (*ppReg)(univ->regs[j]);
+ vex_printf("\n");
+ vex_printf("\nOFFENDING instr = ");
+ (*ppInstr)(instrs_in->arr[ii], mode64);
+ vex_printf("\n");
+ vpanic("doRegisterAllocation: "
+ "first event for rreg is Modify");
+ }
+ rreg_dead_before[j] = ii+1;
}
if (flush) {
ensureRRLRspace(&rreg_lrs_la, &rreg_lrs_size, rreg_lrs_used);
if (0)
vex_printf("FLUSH 1 (%d,%d)\n", flush_la, flush_db);
- rreg_lrs_la[rreg_lrs_used].rreg = rreg;
+ rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
rreg_lrs_la[rreg_lrs_used].live_after = toShort(flush_la);
rreg_lrs_la[rreg_lrs_used].dead_before = toShort(flush_db);
rreg_lrs_used++;
}
- } /* iterate over regs in the instr */
+ } /* iterate over rregs in the instr */
/* ------ end of DEAL WITH RREG LIVE RANGES ------ */
/* ------ start of FINALISE RREG LIVE RANGES ------ */
/* Now finish up any live ranges left over. */
- for (j = 0; j < n_available_real_regs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
-# if 0
- vex_printf("residual %d: %d %d\n", j, rreg_live_after[j],
- rreg_dead_before[j]);
-# endif
+ if (0) {
+ vex_printf("residual %d: %d %d\n", j, rreg_live_after[j],
+ rreg_dead_before[j]);
+ }
vassert( (rreg_live_after[j] == INVALID_INSTRNO
- && rreg_dead_before[j] == INVALID_INSTRNO)
+ && rreg_dead_before[j] == INVALID_INSTRNO)
||
- (rreg_live_after[j] != INVALID_INSTRNO
- && rreg_dead_before[j] != INVALID_INSTRNO)
+ (rreg_live_after[j] != INVALID_INSTRNO
+ && rreg_dead_before[j] != INVALID_INSTRNO)
);
if (rreg_live_after[j] == INVALID_INSTRNO)
if (0)
vex_printf("FLUSH 2 (%d,%d)\n",
rreg_live_after[j], rreg_dead_before[j]);
- rreg_lrs_la[rreg_lrs_used].rreg = available_real_regs[j];
+ rreg_lrs_la[rreg_lrs_used].rreg = univ->regs[j];
rreg_lrs_la[rreg_lrs_used].live_after = toShort(rreg_live_after[j]);
rreg_lrs_la[rreg_lrs_used].dead_before = toShort(rreg_dead_before[j]);
rreg_lrs_used++;
their HLRs. Correctness of final assignment is unaffected by
this mechanism -- it is only an optimisation. */
- for (j = 0; j < rreg_lrs_used; j++) {
- rreg = rreg_lrs_la[j].rreg;
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ HReg rreg = rreg_lrs_la[j].rreg;
vassert(!hregIsVirtual(rreg));
/* rreg is involved in a HLR. Record this info in the array, if
there is space. */
- for (k = 0; k < n_rregs; k++)
- if (sameHReg(rreg_state[k].rreg, rreg))
- break;
- vassert(k < n_rregs); /* else rreg was not found in rreg_state?! */
- rreg_state[k].has_hlrs = True;
+ UInt ix = hregIndex(rreg);
+ vassert(ix < n_rregs);
+ rreg_state[ix].has_hlrs = True;
}
if (0) {
- for (j = 0; j < n_rregs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
if (!rreg_state[j].has_hlrs)
continue;
- ppReg(rreg_state[j].rreg);
+ ppReg(univ->regs[j]);
vex_printf(" hinted\n");
}
}
/* Finally, copy the _la variant into the _db variant and
sort both by their respective fields. */
rreg_lrs_db = LibVEX_Alloc_inline(rreg_lrs_used * sizeof(RRegLR));
- for (j = 0; j < rreg_lrs_used; j++)
+ for (Int j = 0; j < rreg_lrs_used; j++)
rreg_lrs_db[j] = rreg_lrs_la[j];
sortRRLRarray( rreg_lrs_la, rreg_lrs_used, True /* by .live_after*/ );
rreg_lrs_la_next = 0;
rreg_lrs_db_next = 0;
- for (j = 1; j < rreg_lrs_used; j++) {
+ for (Int j = 1; j < rreg_lrs_used; j++) {
vassert(rreg_lrs_la[j-1].live_after <= rreg_lrs_la[j].live_after);
vassert(rreg_lrs_db[j-1].dead_before <= rreg_lrs_db[j].dead_before);
}
/* ------ end of FINALISE RREG LIVE RANGES ------ */
-# if DEBUG_REGALLOC
- for (j = 0; j < n_vregs; j++) {
- vex_printf("vreg %d: la = %d, db = %d\n",
- j, vreg_lrs[j].live_after, vreg_lrs[j].dead_before );
- }
-# endif
-
-# if DEBUG_REGALLOC
- vex_printf("RRegLRs by LA:\n");
- for (j = 0; j < rreg_lrs_used; j++) {
- vex_printf(" ");
- (*ppReg)(rreg_lrs_la[j].rreg);
- vex_printf(" la = %d, db = %d\n",
- rreg_lrs_la[j].live_after, rreg_lrs_la[j].dead_before );
+ if (DEBUG_REGALLOC) {
+ for (Int j = 0; j < n_vregs; j++) {
+ vex_printf("vreg %d: la = %d, db = %d\n",
+ j, vreg_lrs[j].live_after, vreg_lrs[j].dead_before );
+ }
}
- vex_printf("RRegLRs by DB:\n");
- for (j = 0; j < rreg_lrs_used; j++) {
- vex_printf(" ");
- (*ppReg)(rreg_lrs_db[j].rreg);
- vex_printf(" la = %d, db = %d\n",
- rreg_lrs_db[j].live_after, rreg_lrs_db[j].dead_before );
+
+ if (DEBUG_REGALLOC) {
+ vex_printf("RRegLRs by LA:\n");
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ vex_printf(" ");
+ (*ppReg)(rreg_lrs_la[j].rreg);
+ vex_printf(" la = %d, db = %d\n",
+ rreg_lrs_la[j].live_after, rreg_lrs_la[j].dead_before );
+ }
+ vex_printf("RRegLRs by DB:\n");
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ vex_printf(" ");
+ (*ppReg)(rreg_lrs_db[j].rreg);
+ vex_printf(" la = %d, db = %d\n",
+ rreg_lrs_db[j].live_after, rreg_lrs_db[j].dead_before );
+ }
}
-# endif
/* --------- Stage 3: allocate spill slots. --------- */
Vec128-class values we must allocated a spill slot number which
is zero mod 2.
- Similarly, for Vec256 calss on amd64, find a spill slot number
+ Similarly, for Vec256 class on amd64, find a spill slot number
which is zero mod 4. This guarantees it will be 32 byte
aligned, which isn't actually necessary on amd64 (we use movUpd
etc to spill), but seems like good practice.
put as few values as possible in spill slots, but nevertheless
need to have a spill slot available for all vregs, just in case.
*/
- /* max_ss_no = -1; */
+ /* Int max_ss_no = -1; */
- for (j = 0; j < N_SPILL64S; j++)
- ss_busy_until_before[j] = 0;
+ local_memset(ss_busy_until_before, 0, sizeof(ss_busy_until_before));
- for (j = 0; j < n_vregs; j++) {
+ for (Int j = 0; j < n_vregs; j++) {
/* True iff this vreg is unused. In which case we also expect
that the reg_class field for it has not been set. */
find four adjacent slots to use. Note, this logic needs to
kept in sync with the size info on the definition of
HRegClass. */
+ Int ss_no = -1;
switch (vreg_lrs[j].reg_class) {
case HRcVec128: case HRcFlt64:
provide up to 128 bits in which to spill the vreg.
Since we are trying to find an even:odd pair, move
along in steps of 2 (slots). */
- for (k = 0; k < N_SPILL64S-1; k += 2)
- if (ss_busy_until_before[k+0] <= vreg_lrs[j].live_after
- && ss_busy_until_before[k+1] <= vreg_lrs[j].live_after)
+ for (ss_no = 0; ss_no < N_SPILL64S-1; ss_no += 2)
+ if (ss_busy_until_before[ss_no+0] <= vreg_lrs[j].live_after
+ && ss_busy_until_before[ss_no+1] <= vreg_lrs[j].live_after)
break;
- if (k >= N_SPILL64S-1) {
+ if (ss_no >= N_SPILL64S-1) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- if (0) vex_printf("16-byte spill offset in spill slot %d\n",
- (Int)k);
- ss_busy_until_before[k+0] = vreg_lrs[j].dead_before;
- ss_busy_until_before[k+1] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+0] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no+1] = vreg_lrs[j].dead_before;
break;
default:
/* Find the lowest-numbered spill slot which is available
at the start point of this interval, and assign the
interval to it. */
- for (k = 0; k < N_SPILL64S; k++)
- if (ss_busy_until_before[k] <= vreg_lrs[j].live_after)
+ for (ss_no = 0; ss_no < N_SPILL64S; ss_no++)
+ if (ss_busy_until_before[ss_no] <= vreg_lrs[j].live_after)
break;
- if (k == N_SPILL64S) {
+ if (ss_no == N_SPILL64S) {
vpanic("LibVEX_N_SPILL_BYTES is too low. "
"Increase and recompile.");
}
- ss_busy_until_before[k] = vreg_lrs[j].dead_before;
+ ss_busy_until_before[ss_no] = vreg_lrs[j].dead_before;
break;
- } /* switch (vreg_lrs[j].reg_class) { */
+ } /* switch (vreg_lrs[j].reg_class) */
/* This reflects LibVEX's hard-wired knowledge of the baseBlock
layout: the guest state, then two equal sized areas following
it for two sets of shadow state, and then the spill area. */
- vreg_lrs[j].spill_offset = toShort(guest_sizeB * 3 + k * 8);
+ vreg_lrs[j].spill_offset = toShort(guest_sizeB * 3 + ss_no * 8);
/* Independent check that we've made a sane choice of slot */
sanity_check_spill_offset( &vreg_lrs[j] );
/* max_ss_no = j; */
}
-# if 0
- vex_printf("\n\n");
- for (j = 0; j < n_vregs; j++)
- vex_printf("vreg %d --> spill offset %d\n",
- j, vreg_lrs[j].spill_offset);
-# endif
+ if (0) {
+ vex_printf("\n\n");
+ for (Int j = 0; j < n_vregs; j++)
+ vex_printf("vreg %d --> spill offset %d\n",
+ j, vreg_lrs[j].spill_offset);
+ }
/* --------- Stage 4: establish rreg preferences --------- */
/* ------ BEGIN: Process each insn in turn. ------ */
- for (ii = 0; ii < instrs_in->arr_used; ii++) {
+ for (Int ii = 0; ii < instrs_in->arr_used; ii++) {
-# if DEBUG_REGALLOC
- vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
- vex_printf("---- ");
- (*ppInstr)(instrs_in->arr[ii], mode64);
- vex_printf("\n\nInitial state:\n");
- PRINT_STATE;
- vex_printf("\n");
-# endif
+ if (DEBUG_REGALLOC) {
+ vex_printf("\n====----====---- Insn %d ----====----====\n", ii);
+ vex_printf("---- ");
+ (*ppInstr)(instrs_in->arr[ii], mode64);
+ vex_printf("\n\nInitial state:\n");
+ PRINT_STATE;
+ vex_printf("\n");
+ }
/* ------------ Sanity checks ------------ */
/* Sanity checks are expensive. So they are done only once
- every 7 instructions, and just before the last
+ every 13 instructions, and just before the last
instruction. */
do_sanity_check
= toBool(
- False /* Set to True for sanity checking of all insns. */
+ False /* Set to True for sanity checking of all insns. */
|| ii == instrs_in->arr_used-1
- || (ii > 0 && (ii % 7) == 0)
+ || (ii > 0 && (ii % 13) == 0)
);
if (do_sanity_check) {
/* Sanity check 1: all rregs with a hard live range crossing
this insn must be marked as unavailable in the running
state. */
- for (j = 0; j < rreg_lrs_used; j++) {
- if (rreg_lrs_la[j].live_after < ii
+ for (Int j = 0; j < rreg_lrs_used; j++) {
+ if (rreg_lrs_la[j].live_after < ii
&& ii < rreg_lrs_la[j].dead_before) {
/* ii is the middle of a hard live range for some real
reg. Check it's marked as such in the running
state. */
+ HReg reg = rreg_lrs_la[j].rreg;
-# if 0
- vex_printf("considering la %d .. db %d reg = ",
- rreg_lrs[j].live_after,
- rreg_lrs[j].dead_before);
- (*ppReg)(rreg_lrs[j].rreg);
- vex_printf("\n");
-# endif
-
- /* find the state entry for this rreg */
- for (k = 0; k < n_rregs; k++)
- if (sameHReg(rreg_state[k].rreg, rreg_lrs_la[j].rreg))
- break;
+ if (0) {
+ vex_printf("considering la %d .. db %d reg = ",
+ rreg_lrs_la[j].live_after,
+ rreg_lrs_la[j].dead_before);
+ (*ppReg)(reg);
+ vex_printf("\n");
+ }
- /* and assert that this rreg is marked as unavailable */
- vassert(rreg_state[k].disp == Unavail);
+ /* assert that this rreg is marked as unavailable */
+ vassert(!hregIsVirtual(reg));
+ vassert(rreg_state[hregIndex(reg)].disp == Unavail);
}
}
unavailable in the running rreg_state must have a
corresponding hard live range entry in the rreg_lrs
array. */
- for (j = 0; j < n_available_real_regs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
vassert(rreg_state[j].disp == Bound
|| rreg_state[j].disp == Free
|| rreg_state[j].disp == Unavail);
if (rreg_state[j].disp != Unavail)
continue;
- for (k = 0; k < rreg_lrs_used; k++)
- if (sameHReg(rreg_lrs_la[k].rreg, rreg_state[j].rreg)
+ Int k;
+ for (k = 0; k < rreg_lrs_used; k++) {
+ HReg reg = rreg_lrs_la[k].rreg;
+ vassert(!hregIsVirtual(reg));
+ if (hregIndex(reg) == j
&& rreg_lrs_la[k].live_after < ii
&& ii < rreg_lrs_la[k].dead_before)
break;
+ }
/* If this vassertion fails, we couldn't find a
corresponding HLR. */
vassert(k < rreg_lrs_used);
/* Sanity check 3: all vreg-rreg bindings must bind registers
of the same class. */
- for (j = 0; j < n_rregs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
if (rreg_state[j].disp != Bound) {
vassert(rreg_state[j].eq_spill_slot == False);
continue;
}
- vassert(hregClass(rreg_state[j].rreg)
+ vassert(hregClass(univ->regs[j])
== hregClass(rreg_state[j].vreg));
vassert( hregIsVirtual(rreg_state[j].vreg));
- vassert(!hregIsVirtual(rreg_state[j].rreg));
}
/* Sanity check 4: the vreg_state and rreg_state
rreg_state[j].vreg points at some vreg_state entry then
that vreg_state entry should point back at
rreg_state[j]. */
- for (j = 0; j < n_rregs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
if (rreg_state[j].disp != Bound)
continue;
- k = hregNumber(rreg_state[j].vreg);
+ Int k = hregIndex(rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(k));
vassert(vreg_state[k] == j);
}
- for (j = 0; j < n_vregs; j++) {
- k = vreg_state[j];
+ for (Int j = 0; j < n_vregs; j++) {
+ Int k = vreg_state[j];
if (k == INVALID_RREG_NO)
continue;
vassert(IS_VALID_RREGNO(k));
vassert(rreg_state[k].disp == Bound);
- vassert(hregNumber(rreg_state[k].vreg) == j);
+ vassert(hregIndex(rreg_state[k].vreg) == j);
}
} /* if (do_sanity_check) */
/* If doing a reg-reg move between two vregs, and the src's live
range ends here and the dst's live range starts here, bind
the dst to the src's rreg, and that's all. */
+ HReg vregS = INVALID_HREG;
+ HReg vregD = INVALID_HREG;
if ( (*isMove)( instrs_in->arr[ii], &vregS, &vregD ) ) {
if (!hregIsVirtual(vregS)) goto cannot_coalesce;
if (!hregIsVirtual(vregD)) goto cannot_coalesce;
/* Check that *isMove is not telling us a bunch of lies ... */
vassert(hregClass(vregS) == hregClass(vregD));
- k = hregNumber(vregS);
- m = hregNumber(vregD);
+ Int k = hregIndex(vregS);
+ Int m = hregIndex(vregD);
vassert(IS_VALID_VREGNO(k));
vassert(IS_VALID_VREGNO(m));
if (vreg_lrs[k].dead_before != ii + 1) goto cannot_coalesce;
if (vreg_lrs[m].live_after != ii) goto cannot_coalesce;
-# if DEBUG_REGALLOC
+ if (DEBUG_REGALLOC) {
vex_printf("COALESCE ");
- (*ppReg)(vregS);
- vex_printf(" -> ");
- (*ppReg)(vregD);
- vex_printf("\n\n");
-# endif
+ (*ppReg)(vregS);
+ vex_printf(" -> ");
+ (*ppReg)(vregD);
+ vex_printf("\n\n");
+ }
/* Find the state entry for vregS. */
- for (m = 0; m < n_rregs; m++)
- if (rreg_state[m].disp == Bound
- && sameHReg(rreg_state[m].vreg, vregS))
- break;
- if (m == n_rregs)
- /* We failed to find a binding for vregS, which means it's
- currently not in a register. So we can't do the
- coalescing. Give up. */
+ Int n = vreg_state[k]; /* k is the index of vregS */
+ if (n == INVALID_RREG_NO) {
+ /* vregS is not currently in a real register. So we can't
+ do the coalescing. Give up. */
goto cannot_coalesce;
+ }
+ vassert(IS_VALID_RREGNO(n));
/* Finally, we can do the coalescing. It's trivial -- merely
claim vregS's register for vregD. */
- rreg_state[m].vreg = vregD;
- vassert(IS_VALID_VREGNO(hregNumber(vregD)));
- vassert(IS_VALID_VREGNO(hregNumber(vregS)));
- vreg_state[hregNumber(vregD)] = toShort(m);
- vreg_state[hregNumber(vregS)] = INVALID_RREG_NO;
+ rreg_state[n].vreg = vregD;
+ vassert(IS_VALID_VREGNO(hregIndex(vregD)));
+ vassert(IS_VALID_VREGNO(hregIndex(vregS)));
+ vreg_state[hregIndex(vregD)] = toShort(n);
+ vreg_state[hregIndex(vregS)] = INVALID_RREG_NO;
/* This rreg has become associated with a different vreg and
hence with a different spill slot. Play safe. */
- rreg_state[m].eq_spill_slot = False;
+ rreg_state[n].eq_spill_slot = False;
/* Move on to the next insn. We skip the post-insn stuff for
fixed registers, since this move should not interact with
/* Look for vregs whose live range has just ended, and
mark the associated rreg as free. */
- for (j = 0; j < n_rregs; j++) {
+ for (Int j = 0; j < n_rregs; j++) {
if (rreg_state[j].disp != Bound)
continue;
- UInt vregno = hregNumber(rreg_state[j].vreg);
+ UInt vregno = hregIndex(rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(vregno));
if (vreg_lrs[vregno].dead_before <= ii) {
rreg_state[j].disp = Free;
rreg_state[j].eq_spill_slot = False;
- m = hregNumber(rreg_state[j].vreg);
+ Int m = hregIndex(rreg_state[j].vreg);
vassert(IS_VALID_VREGNO(m));
vreg_state[m] = INVALID_RREG_NO;
if (DEBUG_REGALLOC) {
vex_printf("free up ");
- (*ppReg)(rreg_state[j].rreg);
+ (*ppReg)(univ->regs[j]);
vex_printf("\n");
}
}
rreg_lrs_la[rreg_lrs_la_next].live_after == ii, that is,
whether the reg becomes live after this insn -- rather
than before it. */
-# if DEBUG_REGALLOC
- vex_printf("need to free up rreg: ");
- (*ppReg)(rreg_lrs_la[rreg_lrs_la_next].rreg);
- vex_printf("\n\n");
-# endif
- for (k = 0; k < n_rregs; k++)
- if (sameHReg(rreg_state[k].rreg, rreg_lrs_la[rreg_lrs_la_next].rreg))
- break;
+ if (DEBUG_REGALLOC) {
+ vex_printf("need to free up rreg: ");
+ (*ppReg)(rreg_lrs_la[rreg_lrs_la_next].rreg);
+ vex_printf("\n\n");
+ }
+ Int k = hregIndex(rreg_lrs_la[rreg_lrs_la_next].rreg);
+
/* If this fails, we don't have an entry for this rreg.
Which we should. */
vassert(IS_VALID_RREGNO(k));
- m = hregNumber(rreg_state[k].vreg);
+ Int m = hregIndex(rreg_state[k].vreg);
if (rreg_state[k].disp == Bound) {
/* Yes, there is an associated vreg. Spill it if it's
still live. */
if ((!eq_spill_opt) || !rreg_state[k].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
- (*genSpill)( &spill1, &spill2, rreg_state[k].rreg,
+ (*genSpill)( &spill1, &spill2, univ->regs[k],
vreg_lrs[m].spill_offset, mode64 );
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
rreg_lrs_la_next++;
}
-
-# if DEBUG_REGALLOC
- vex_printf("After pre-insn actions for fixed regs:\n");
- PRINT_STATE;
- vex_printf("\n");
-# endif
-
+ if (DEBUG_REGALLOC) {
+ vex_printf("After pre-insn actions for fixed regs:\n");
+ PRINT_STATE;
+ vex_printf("\n");
+ }
/* ------ Deal with the current instruction. ------ */
some vregs currently in rregs. Also generates spill loads.
We also build up the final vreg->rreg mapping to be applied
to the insn. */
-
- (*getRegUsage)( ®_usage, instrs_in->arr[ii], mode64 );
initHRegRemap(&remap);
/* If the instruction reads exactly one vreg which is currently
in a spill slot, and this is last use of that vreg, see if we
- can convert the instruction into one reads directly from the
- spill slot. This is clearly only possible for x86 and amd64
- targets, since ppc and arm load-store architectures. If
- successful, replace instrs_in->arr[ii] with this new
- instruction, and recompute its reg usage, so that the change
- is invisible to the standard-case handling that follows. */
+ can convert the instruction into one that reads directly from
+ the spill slot. This is clearly only possible for x86 and
+ amd64 targets, since ppc and arm are load-store
+ architectures. If successful, replace instrs_in->arr[ii]
+ with this new instruction, and recompute its reg usage, so
+ that the change is invisible to the standard-case handling
+ that follows. */
- if (directReload && reg_usage.n_used <= 2) {
- Bool debug_direct_reload = True && False;
+ if (directReload && reg_usage_arr[ii].n_vRegs <= 2) {
+ Bool debug_direct_reload = False;
HReg cand = INVALID_HREG;
Bool nreads = 0;
Short spilloff = 0;
- for (j = 0; j < reg_usage.n_used; j++) {
-
- vreg = reg_usage.hreg[j];
+ for (Int j = 0; j < reg_usage_arr[ii].n_vRegs; j++) {
- if (!hregIsVirtual(vreg))
- continue;
+ HReg vreg = reg_usage_arr[ii].vRegs[j];
+ vassert(hregIsVirtual(vreg));
- if (reg_usage.mode[j] == HRmRead) {
+ if (reg_usage_arr[ii].vMode[j] == HRmRead) {
nreads++;
- m = hregNumber(vreg);
+ Int m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- k = vreg_state[m];
+ Int k = vreg_state[m];
if (!IS_VALID_RREGNO(k)) {
/* ok, it is spilled. Now, is this its last use? */
vassert(vreg_lrs[m].dead_before >= ii+1);
if (nreads == 1 && ! hregIsInvalid(cand)) {
HInstr* reloaded;
- if (reg_usage.n_used == 2)
- vassert(! sameHReg(reg_usage.hreg[0], reg_usage.hreg[1]));
+ if (reg_usage_arr[ii].n_vRegs == 2)
+ vassert(! sameHReg(reg_usage_arr[ii].vRegs[0],
+ reg_usage_arr[ii].vRegs[1]));
reloaded = directReload ( instrs_in->arr[ii], cand, spilloff );
if (debug_direct_reload && !reloaded) {
/* Update info about the insn, so it looks as if it had
been in this form all along. */
instrs_in->arr[ii] = reloaded;
- (*getRegUsage)( ®_usage, instrs_in->arr[ii], mode64 );
+ (*getRegUsage)( ®_usage_arr[ii], instrs_in->arr[ii], mode64 );
if (debug_direct_reload && !reloaded) {
vex_printf(" --> ");
ppInstr(reloaded, mode64);
/* ------------ END directReload optimisation ------------ */
- /* for each reg mentioned in the insn ... */
- for (j = 0; j < reg_usage.n_used; j++) {
-
- vreg = reg_usage.hreg[j];
+ /* for each virtual reg mentioned in the insn ... */
+ for (Int j = 0; j < reg_usage_arr[ii].n_vRegs; j++) {
- /* only interested in virtual registers right now. */
- if (!hregIsVirtual(vreg))
- continue;
+ HReg vreg = reg_usage_arr[ii].vRegs[j];
+ vassert(hregIsVirtual(vreg));
-# if 0
- vex_printf("considering "); (*ppReg)(vreg); vex_printf("\n");
-# endif
+ if (0) {
+ vex_printf("considering "); (*ppReg)(vreg); vex_printf("\n");
+ }
/* Now we're trying to find a rreg for "vreg". First of all,
if it already has an rreg assigned, we don't need to do
- anything more. Search the current state to find out. */
- m = hregNumber(vreg);
+ anything more. Inspect the current state to find out. */
+ Int m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
- k = vreg_state[m];
- if (IS_VALID_RREGNO(k)) {
- vassert(rreg_state[k].disp == Bound);
- addToHRegRemap(&remap, vreg, rreg_state[k].rreg);
+ Int n = vreg_state[m];
+ if (IS_VALID_RREGNO(n)) {
+ vassert(rreg_state[n].disp == Bound);
+ addToHRegRemap(&remap, vreg, univ->regs[n]);
/* If this rreg is written or modified, mark it as different
from any spill slot value. */
- if (reg_usage.mode[j] != HRmRead)
- rreg_state[k].eq_spill_slot = False;
+ if (reg_usage_arr[ii].vMode[j] != HRmRead)
+ rreg_state[n].eq_spill_slot = False;
continue;
} else {
- vassert(k == INVALID_RREG_NO);
+ vassert(n == INVALID_RREG_NO);
}
/* No luck. The next thing to do is see if there is a
so, bag it. NOTE, we could improve this by selecting an
rreg for which the next live-range event is as far ahead
as possible. */
- k_suboptimal = -1;
+ Int k_suboptimal = -1;
+ Int k;
for (k = 0; k < n_rregs; k++) {
if (rreg_state[k].disp != Free
- || hregClass(rreg_state[k].rreg) != hregClass(vreg))
+ || hregClass(univ->regs[k]) != hregClass(vreg))
continue;
if (rreg_state[k].has_hlrs) {
/* Well, at least we can use k_suboptimal if we really
if (k < n_rregs) {
rreg_state[k].disp = Bound;
rreg_state[k].vreg = vreg;
- m = hregNumber(vreg);
- vassert(IS_VALID_VREGNO(m));
- vreg_state[m] = toShort(k);
- addToHRegRemap(&remap, vreg, rreg_state[k].rreg);
+ Int p = hregIndex(vreg);
+ vassert(IS_VALID_VREGNO(p));
+ vreg_state[p] = toShort(k);
+ addToHRegRemap(&remap, vreg, univ->regs[k]);
/* Generate a reload if needed. This only creates needed
reloads because the live range builder for vregs will
guarantee that the first event for a vreg is a write.
Hence, if this reference is not a write, it cannot be
the first reference for this vreg, and so a reload is
indeed needed. */
- if (reg_usage.mode[j] != HRmWrite) {
- vassert(vreg_lrs[m].reg_class != HRcINVALID);
+ if (reg_usage_arr[ii].vMode[j] != HRmWrite) {
+ vassert(vreg_lrs[p].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
- (*genReload)( &reload1, &reload2, rreg_state[k].rreg,
- vreg_lrs[m].spill_offset, mode64 );
+ (*genReload)( &reload1, &reload2, univ->regs[k],
+ vreg_lrs[p].spill_offset, mode64 );
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
EMIT_INSTR(reload1);
/* This rreg is read or modified by the instruction.
If it's merely read we can claim it now equals the
spill slot, but not so if it is modified. */
- if (reg_usage.mode[j] == HRmRead) {
+ if (reg_usage_arr[ii].vMode[j] == HRmRead) {
rreg_state[k].eq_spill_slot = True;
} else {
- vassert(reg_usage.mode[j] == HRmModify);
+ vassert(reg_usage_arr[ii].vMode[j] == HRmModify);
rreg_state[k].eq_spill_slot = False;
}
} else {
rreg_state[k].is_spill_cand = False;
if (rreg_state[k].disp != Bound)
continue;
- if (hregClass(rreg_state[k].rreg) != hregClass(vreg))
+ if (hregClass(univ->regs[k]) != hregClass(vreg))
continue;
rreg_state[k].is_spill_cand = True;
- for (m = 0; m < reg_usage.n_used; m++) {
- if (sameHReg(rreg_state[k].vreg, reg_usage.hreg[m])) {
+ /* Note, the following loop visits only the virtual regs
+ mentioned by the instruction. */
+ for (m = 0; m < reg_usage_arr[ii].n_vRegs; m++) {
+ if (sameHReg(rreg_state[k].vreg, reg_usage_arr[ii].vRegs[m])) {
rreg_state[k].is_spill_cand = False;
break;
}
the next use of its associated vreg is as far ahead as
possible, in the hope that this will minimise the number
of consequent reloads required. */
- spillee
+ Int spillee
= findMostDistantlyMentionedVReg (
- getRegUsage, instrs_in, ii+1, rreg_state, n_rregs, mode64 );
+ reg_usage_arr, ii+1, instrs_in->arr_used, rreg_state, n_rregs );
if (spillee == -1) {
/* Hmmmmm. There don't appear to be any spill candidates.
vassert(IS_VALID_RREGNO(spillee));
vassert(rreg_state[spillee].disp == Bound);
/* check it's the right class */
- vassert(hregClass(rreg_state[spillee].rreg) == hregClass(vreg));
+ vassert(hregClass(univ->regs[spillee]) == hregClass(vreg));
/* check we're not ejecting the vreg for which we are trying
to free up a register. */
vassert(! sameHReg(rreg_state[spillee].vreg, vreg));
- m = hregNumber(rreg_state[spillee].vreg);
+ m = hregIndex(rreg_state[spillee].vreg);
vassert(IS_VALID_VREGNO(m));
/* So here's the spill store. Assert that we're spilling a
if ((!eq_spill_opt) || !rreg_state[spillee].eq_spill_slot) {
HInstr* spill1 = NULL;
HInstr* spill2 = NULL;
- (*genSpill)( &spill1, &spill2, rreg_state[spillee].rreg,
+ (*genSpill)( &spill1, &spill2, univ->regs[spillee],
vreg_lrs[m].spill_offset, mode64 );
vassert(spill1 || spill2); /* can't both be NULL */
if (spill1)
rreg_state[spillee].eq_spill_slot = False; /* be safe */
- m = hregNumber(vreg);
+ m = hregIndex(vreg);
vassert(IS_VALID_VREGNO(m));
vreg_state[m] = toShort(spillee);
/* Now, if this vreg is being read or modified (as opposed to
written), we have to generate a reload for it. */
- if (reg_usage.mode[j] != HRmWrite) {
+ if (reg_usage_arr[ii].vMode[j] != HRmWrite) {
vassert(vreg_lrs[m].reg_class != HRcINVALID);
HInstr* reload1 = NULL;
HInstr* reload2 = NULL;
- (*genReload)( &reload1, &reload2, rreg_state[spillee].rreg,
+ (*genReload)( &reload1, &reload2, univ->regs[spillee],
vreg_lrs[m].spill_offset, mode64 );
vassert(reload1 || reload2); /* can't both be NULL */
if (reload1)
/* This rreg is read or modified by the instruction.
If it's merely read we can claim it now equals the
spill slot, but not so if it is modified. */
- if (reg_usage.mode[j] == HRmRead) {
+ if (reg_usage_arr[ii].vMode[j] == HRmRead) {
rreg_state[spillee].eq_spill_slot = True;
} else {
- vassert(reg_usage.mode[j] == HRmModify);
+ vassert(reg_usage_arr[ii].vMode[j] == HRmModify);
rreg_state[spillee].eq_spill_slot = False;
}
}
/* So after much twisting and turning, we have vreg mapped to
rreg_state[spillee].rreg. Note that in the map. */
- addToHRegRemap(&remap, vreg, rreg_state[spillee].rreg);
+ addToHRegRemap(&remap, vreg, univ->regs[spillee]);
- } /* iterate over registers in this instruction. */
+ } /* iterate over virtual registers in this instruction. */
/* We've finished clowning around with registers in this instruction.
Three results:
(*mapRegs)( &remap, instrs_in->arr[ii], mode64 );
EMIT_INSTR( instrs_in->arr[ii] );
-# if DEBUG_REGALLOC
- vex_printf("After dealing with current insn:\n");
- PRINT_STATE;
- vex_printf("\n");
-# endif
+ if (DEBUG_REGALLOC) {
+ vex_printf("After dealing with current insn:\n");
+ PRINT_STATE;
+ vex_printf("\n");
+ }
/* ------ Post-instruction actions for fixed rreg uses ------ */
vassert(ii+1 == rreg_lrs_db[rreg_lrs_db_next].dead_before);
/* rreg_lrs_db[[rreg_lrs_db_next].rreg is exiting a hard live
range. Mark it as such in the main rreg_state array. */
- for (k = 0; k < n_rregs; k++)
- if (sameHReg(rreg_state[k].rreg, rreg_lrs_db[rreg_lrs_db_next].rreg))
- break;
- /* If this vassertion fails, we don't have an entry for
- this rreg. Which we should. */
- vassert(k < n_rregs);
+ HReg reg = rreg_lrs_db[rreg_lrs_db_next].rreg;
+ vassert(!hregIsVirtual(reg));
+ Int k = hregIndex(reg);
+ vassert(IS_VALID_RREGNO(k));
vassert(rreg_state[k].disp == Unavail);
rreg_state[k].disp = Free;
rreg_state[k].vreg = INVALID_HREG;
rreg_lrs_db_next++;
}
-# if DEBUG_REGALLOC
- vex_printf("After post-insn actions for fixed regs:\n");
- PRINT_STATE;
- vex_printf("\n");
-# endif
+ if (DEBUG_REGALLOC) {
+ vex_printf("After post-insn actions for fixed regs:\n");
+ PRINT_STATE;
+ vex_printf("\n");
+ }
} /* iterate over insns */
/* if (vreg_lrs) free(vreg_lrs); */
/* Paranoia */
- for (j = 0; j < n_rregs; j++)
- vassert(sameHReg(rreg_state[j].rreg, available_real_regs[j]));
-
vassert(rreg_lrs_la_next == rreg_lrs_used);
vassert(rreg_lrs_db_next == rreg_lrs_used);
#include "host_generic_regs.h"
+/*---------------------------------------------------------*/
+/*--- Representing HOST REGISTERS ---*/
+/*---------------------------------------------------------*/
+
void ppHRegClass ( HRegClass hrc )
{
switch (hrc) {
/* Generic printing for registers. */
void ppHReg ( HReg r )
{
- const HChar* maybe_v = hregIsVirtual(r) ? "v" : "";
- Int regNo = hregNumber(r);
+ if (hregIsInvalid(r)) {
+ vex_printf("HReg_INVALID");
+ return;
+ }
+ const Bool isV = hregIsVirtual(r);
+ const HChar* maybe_v = isV ? "v" : "";
+ const UInt regNN = isV ? hregIndex(r) : hregEncoding(r);
+ /* For real registers, we show the encoding. But the encoding is
+ always zero for virtual registers, so that's pointless -- hence
+ show the index number instead. */
switch (hregClass(r)) {
- case HRcInt32: vex_printf("%%%sr%d", maybe_v, regNo); return;
- case HRcInt64: vex_printf("%%%sR%d", maybe_v, regNo); return;
- case HRcFlt32: vex_printf("%%%sF%d", maybe_v, regNo); return;
- case HRcFlt64: vex_printf("%%%sD%d", maybe_v, regNo); return;
- case HRcVec64: vex_printf("%%%sv%d", maybe_v, regNo); return;
- case HRcVec128: vex_printf("%%%sV%d", maybe_v, regNo); return;
+ case HRcInt32: vex_printf("%%%sr%u", maybe_v, regNN); return;
+ case HRcInt64: vex_printf("%%%sR%u", maybe_v, regNN); return;
+ case HRcFlt32: vex_printf("%%%sF%u", maybe_v, regNN); return;
+ case HRcFlt64: vex_printf("%%%sD%u", maybe_v, regNN); return;
+ case HRcVec64: vex_printf("%%%sv%u", maybe_v, regNN); return;
+ case HRcVec128: vex_printf("%%%sV%u", maybe_v, regNN); return;
default: vpanic("ppHReg");
}
}
+/*---------------------------------------------------------*/
+/*--- Real register Universes. ---*/
+/*---------------------------------------------------------*/
+
+void RRegUniverse__init ( /*OUT*/RRegUniverse* univ )
+{
+ *univ = (RRegUniverse){};
+ univ->size = 0;
+ univ->allocable = 0;
+ for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
+ univ->regs[i] = INVALID_HREG;
+ }
+}
+
+void RRegUniverse__check_is_sane ( const RRegUniverse* univ )
+{
+ /* Check Real-Register-Universe invariants. All of these are
+ important. */
+ vassert(univ->size > 0);
+ vassert(univ->size <= N_RREGUNIVERSE_REGS);
+ vassert(univ->allocable <= univ->size);
+ for (UInt i = 0; i < univ->size; i++) {
+ HReg reg = univ->regs[i];
+ vassert(!hregIsInvalid(reg));
+ vassert(!hregIsVirtual(reg));
+ vassert(hregIndex(reg) == i);
+ }
+ for (UInt i = univ->size; i < N_RREGUNIVERSE_REGS; i++) {
+ HReg reg = univ->regs[i];
+ vassert(hregIsInvalid(reg));
+ }
+}
+
+
/*---------------------------------------------------------*/
/*--- Helpers for recording reg usage (for reg-alloc) ---*/
/*---------------------------------------------------------*/
-void ppHRegUsage ( HRegUsage* tab )
+void ppHRegUsage ( const RRegUniverse* univ, HRegUsage* tab )
{
- Int i;
- const HChar* str;
+ /* This is going to fail miserably if N_RREGUNIVERSE_REGS exceeds
+ 64. So let's cause it to fail in an obvious way. */
+ vassert(N_RREGUNIVERSE_REGS == 64);
+
vex_printf("HRegUsage {\n");
- for (i = 0; i < tab->n_used; i++) {
- switch (tab->mode[i]) {
+ /* First print the real regs */
+ for (UInt i = 0; i < N_RREGUNIVERSE_REGS; i++) {
+ Bool rRd = (tab->rRead & (1ULL << i)) != 0;
+ Bool rWr = (tab->rWritten & (1ULL << i)) != 0;
+ const HChar* str = "Modify ";
+ /**/ if (!rRd && !rWr) { continue; }
+ else if ( rRd && !rWr) { str = "Read "; }
+ else if (!rRd && rWr) { str = "Write "; }
+ /* else "Modify" is correct */
+ vex_printf(" %s ", str);
+ ppHReg(univ->regs[i]);
+ vex_printf("\n");
+ }
+ /* and now the virtual registers */
+ for (UInt i = 0; i < tab->n_vRegs; i++) {
+ const HChar* str = NULL;
+ switch (tab->vMode[i]) {
case HRmRead: str = "Read "; break;
case HRmWrite: str = "Write "; break;
case HRmModify: str = "Modify "; break;
default: vpanic("ppHRegUsage");
}
vex_printf(" %s ", str);
- ppHReg(tab->hreg[i]);
+ ppHReg(tab->vRegs[i]);
vex_printf("\n");
}
vex_printf("}\n");
}
-/* Add a register to a usage table. Combine incoming read uses with
- existing write uses into a modify use, and vice versa. Do not
- create duplicate entries -- each reg should only be mentioned once.
+/* Add a register to a usage table. Combines incoming read uses with
+ existing write uses into a modify use, and vice versa. Does not
+ create duplicate entries -- each reg is only mentioned once.
*/
void addHRegUse ( HRegUsage* tab, HRegMode mode, HReg reg )
{
- Int i;
- /* Find it ... */
- for (i = 0; i < tab->n_used; i++)
- if (sameHReg(tab->hreg[i], reg))
- break;
- if (i == tab->n_used) {
- /* Not found, add new entry. */
- vassert(tab->n_used < N_HREG_USAGE);
- tab->hreg[tab->n_used] = reg;
- tab->mode[tab->n_used] = mode;
- tab->n_used++;
- } else {
- /* Found: combine or ignore. */
- /* This is a greatest-lower-bound operation in the poset:
-
- R W
- \ /
- M
-
- Need to do: tab->mode[i] = GLB(tab->mode, mode). In this
- case very simple -- if tab->mode[i] != mode then result must
- be M.
- */
- if (tab->mode[i] == mode) {
- /* duplicate, ignore */
+ /* Because real and virtual registers are represented differently,
+ they have completely different paths here. */
+ if (LIKELY(hregIsVirtual(reg))) {
+ /* Virtual register */
+ UInt i;
+ /* Find it ... */
+ for (i = 0; i < tab->n_vRegs; i++)
+ if (sameHReg(tab->vRegs[i], reg))
+ break;
+ if (i == tab->n_vRegs) {
+ /* Not found, add new entry. */
+ vassert(tab->n_vRegs < N_HREGUSAGE_VREGS);
+ tab->vRegs[tab->n_vRegs] = reg;
+ tab->vMode[tab->n_vRegs] = mode;
+ tab->n_vRegs++;
} else {
- tab->mode[i] = HRmModify;
+ /* Found: combine or ignore. */
+ /* This is a greatest-lower-bound operation in the poset:
+
+ R W
+ \ /
+ M
+
+ Need to do: tab->mode[i] = GLB(tab->mode, mode). In this
+ case very simple -- if tab->mode[i] != mode then result must
+ be M.
+ */
+ if (tab->vMode[i] == mode) {
+ /* duplicate, ignore */
+ } else {
+ tab->vMode[i] = HRmModify;
+ }
+ }
+ } else {
+ /* Real register */
+ UInt ix = hregIndex(reg);
+ vassert(ix < N_RREGUNIVERSE_REGS);
+ ULong mask = 1ULL << ix;
+ switch (mode) {
+ case HRmRead: tab->rRead |= mask; break;
+ case HRmWrite: tab->rWritten |= mask; break;
+ case HRmModify: tab->rRead |= mask; tab->rWritten |= mask; break;
+ default: vassert(0);
+ }
+ }
+}
+
+Bool HRegUsage__contains ( const HRegUsage* tab, HReg reg )
+{
+ vassert(!hregIsInvalid(reg));
+ if (hregIsVirtual(reg)) {
+ for (UInt i = 0; i < tab->n_vRegs; i++) {
+ if (sameHReg(reg, tab->vRegs[i]))
+ return True;
}
+ return False;
+ } else {
+ UInt ix = hregIndex(reg);
+ vassert(ix < N_RREGUNIVERSE_REGS);
+ ULong mentioned = tab->rRead | tab->rWritten;
+ return (mentioned & (1ULL << ix)) != 0;
}
+ /*NOTREACHED*/
}
}
-void initHRegRemap ( HRegRemap* map )
-{
- map->n_used = 0;
-}
-
-
void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
{
Int i;
vpanic("lookupHRegRemap: not found");
}
+
/*---------------------------------------------------------*/
/*--- Abstract instructions ---*/
/*---------------------------------------------------------*/
return ha;
}
-void addHInstr ( HInstrArray* ha, HInstr* instr )
+__attribute__((noinline))
+void addHInstr_SLOW ( HInstrArray* ha, HInstr* instr )
{
- vassert(ha->arr_used <= ha->arr_size);
- if (ha->arr_used < ha->arr_size) {
- ha->arr[ha->arr_used] = instr;
- ha->arr_used++;
- } else {
- Int i;
- HInstr** arr2 = LibVEX_Alloc_inline(ha->arr_size * 2 * sizeof(HInstr*));
- for (i = 0; i < ha->arr_size; i++)
- arr2[i] = ha->arr[i];
- ha->arr_size *= 2;
- ha->arr = arr2;
- addHInstr(ha, instr);
+ vassert(ha->arr_used == ha->arr_size);
+ Int i;
+ HInstr** arr2 = LibVEX_Alloc_inline(ha->arr_size * 2 * sizeof(HInstr*));
+ for (i = 0; i < ha->arr_size; i++) {
+ arr2[i] = ha->arr[i];
}
+ ha->arr_size *= 2;
+ ha->arr = arr2;
+ addHInstr(ha, instr);
}
/* Host registers. Stuff to represent:
- - The register number
- - The register class
- - Whether or not the register is a virtual reg.
+ - The register index. This is a zero-based, sequential index that
+ facilitates indexing into arrays or virtual or real registers.
+ Virtual and real registers both have indices starting at zero.
+ Interpreting a real register index requires having the host's
+ RRegUniverse to hand.
- Registers are a 32-bit Int, thusly:
+ - The register's hardware encoding. This applies only for real
+ registers and should be zero for virtual registers. This is the
+ number as used in a target architecture encoding.
- bits 31-28 are the register class.
- bits 27-23 are 0000b for real register, 0001b for virtual register
- bits 23-0 register number
+ - The register class
- Note (importantly) that by arranging that the class field is never
- 0000b, any valid register looks like an extremely large int -- at
- least 2^28 -- and so there is little chance of confusing it with an
- integer array index in the register allocator.
+ - Whether or not the register is a virtual reg.
- Note further that since the class field is never 1111b, no valid
- register can have the value INVALID_HREG.
+ Registers are sized so as to fit into 32 bits.
+
+ Note that since the class field is never 1111b, no valid register
+ can have the value INVALID_HREG.
There are currently 6 register classes:
int32 int64 float32 float64 simd64 simd128
*/
-typedef
- struct {
- UInt reg;
- }
- HReg;
+/* Registers are represented as 32 bit integers, with the following layout:
+
+ 31 30..27 26..20 19..0
+ isV:1 rc:4 enc:7 ix:20
+
+ where
+ UInt ix:20; // Zero based index
+ UInt enc:7; // Hardware encoding number
+ HRegClass rc:4; // the register's HRegClass
+ Bool isV:1; // is it a virtual register?
+
+ The obvious thing to do here would be to use bitfields. But gcc
+ seems to have problems constant folding calls to mkHReg() with all
+ 4 parameters constant to a 32 bit number, when using bitfields.
+ Hence the use of the traditional shift-and-mask by-hand bitfields
+ instead.
+*/
+typedef struct { UInt u32; } HReg;
-/* When extending this, do not use any value > 14 or < 0. */
/* HRegClass describes host register classes which the instruction
selectors can speak about. We would not expect all of them to be
available on any specific host. For example on x86, the available
HRcVec128 128 bits
If you add another regclass, you must remember to update
- host_generic_reg_alloc2.c accordingly.
+ host_generic_reg_alloc2.c accordingly.
+
+ When adding entries to enum HRegClass, do not use any value > 14 or < 1.
*/
typedef
enum {
/* Print an HReg in a generic (non-target-specific) way. */
extern void ppHReg ( HReg );
-/* Construct/destruct. */
-static inline HReg mkHReg ( UInt regno, HRegClass rc, Bool virtual ) {
- UInt r24 = regno & 0x00FFFFFF;
- /* This is critical. The register number field may only
- occupy 24 bits. */
- if (r24 != regno)
- vpanic("mkHReg: regno exceeds 2^24");
+/* Construct. The goal here is that compiler can fold this down to a
+ constant in the case where the four arguments are constants, which
+ is often the case. */
+static inline HReg mkHReg ( Bool virtual, HRegClass rc, UInt enc, UInt ix )
+{
+ vassert(ix <= 0xFFFFF);
+ vassert(enc <= 0x7F);
+ vassert(((UInt)rc) <= 0xF);
+ vassert(((UInt)virtual) <= 1);
+ if (virtual) vassert(enc == 0);
HReg r;
- r.reg = regno | (((UInt)rc) << 28) | (virtual ? (1<<24) : 0);
+ r.u32 = ((((UInt)virtual) & 1) << 31) |
+ ((((UInt)rc) & 0xF) << 27) |
+ ((((UInt)enc) & 0x7F) << 20) |
+ ((((UInt)ix) & 0xFFFFF) << 0);
return r;
}
-static inline HRegClass hregClass ( HReg r ) {
- UInt rc = r.reg;
- rc = (rc >> 28) & 0x0F;
+static inline HRegClass hregClass ( HReg r )
+{
+ HRegClass rc = (HRegClass)((r.u32 >> 27) & 0xF);
vassert(rc >= HRcInt32 && rc <= HRcVec128);
- return (HRegClass)rc;
+ return rc;
}
-static inline UInt hregNumber ( HReg r ) {
- return r.reg & 0x00FFFFFF;
+static inline UInt hregIndex ( HReg r )
+{
+ return r.u32 & 0xFFFFF;
}
-static inline Bool hregIsVirtual ( HReg r ) {
- return toBool(r.reg & (1<<24));
+static inline UInt hregEncoding ( HReg r )
+{
+ return (r.u32 >> 20) & 0x7F;
+}
+
+static inline Bool hregIsVirtual ( HReg r )
+{
+ return toBool((r.u32 >> 31) & 1);
}
static inline Bool sameHReg ( HReg r1, HReg r2 )
{
- return toBool(r1.reg == r2.reg);
+ return toBool(r1.u32 == r2.u32);
}
-static const HReg INVALID_HREG = { 0xFFFFFFFF };
+static const HReg INVALID_HREG = { .u32 = 0xFFFFFFFF };
static inline Bool hregIsInvalid ( HReg r )
{
return sameHReg(r, INVALID_HREG);
}
+
+/*---------------------------------------------------------*/
+/*--- Real register Universes. ---*/
+/*---------------------------------------------------------*/
+
+/* A "Real Register Universe" is a read-only structure that contains
+ all information about real registers on a given host. It serves
+ several purposes:
+
+ * defines the mapping from real register indices to the registers
+ themselves
+
+ * defines the size of the initial section of that mapping that is
+ available to the register allocator for use, so that the register
+ allocator can treat the registers under its control as a zero
+ based, contiguous array. This is important for its efficiency.
+
+ * gives meaning to RRegSets, which otherwise would merely be a
+ bunch of bits.
+
+ This is a big structure, but it's readonly, and we expect to
+ allocate only one instance for each run of Valgrind. It is sized
+ so as to be able to deal with up to 64 real registers. AFAICS none
+ of the back ends actually mention more than 64, despite the fact
+ that many of the host architectures have more than 64 registers
+ when all classes are taken into consideration.
+*/
+
+#define N_RREGUNIVERSE_REGS 64
+
+typedef
+ struct {
+ /* Total number of registers in this universe .. */
+ UInt size;
+ /* .. of which the first |allocable| are available to regalloc. */
+ UInt allocable;
+ /* The registers themselves. All must be real registers, and
+ all must have their index number (.s.ix) equal to the array
+ index here, since this is the only place where we map index
+ numbers to actual registers. */
+ HReg regs[N_RREGUNIVERSE_REGS];
+ }
+ RRegUniverse;
+
+/* Nominally initialise (zero out) an RRegUniverse. */
+void RRegUniverse__init ( /*OUT*/RRegUniverse* );
+
+/* Check an RRegUniverse is valid, and assert if not.*/
+void RRegUniverse__check_is_sane ( const RRegUniverse* );
+
+/* Print an RRegUniverse, for debugging. */
+void RRegUniverse__show ( const RRegUniverse* );
+
+
+/*---------------------------------------------------------*/
+/*--- Real register sets. ---*/
+/*---------------------------------------------------------*/
+
+/* Represents sets of real registers. |bitset| is interpreted in the
+ context of |univ|. That is, each bit index |i| in |bitset|
+ corresponds to the register |univ->regs[i]|. This relies
+ entirely on the fact that N_RREGUNIVERSE_REGS <= 64. */
+typedef
+ struct {
+ ULong bitset;
+ RRegUniverse* univ;
+ }
+ RRegSet;
+
+
/*---------------------------------------------------------*/
/*--- Recording register usage (for reg-alloc) ---*/
/*---------------------------------------------------------*/
HRegMode;
-/* A struct for recording the usage of registers in instructions.
- This can get quite large, but we don't expect to allocate them
- dynamically, so there's no problem.
+/* This isn't entirely general, and is specialised towards being fast,
+ for the reg-alloc. It represents real registers using a bitmask
+ and can also represent up to four virtual registers, in an
+ unordered array. This is based on the observation that no
+ instruction that we generate can mention more than four registers
+ at once.
*/
-#define N_HREG_USAGE 25
+#define N_HREGUSAGE_VREGS 5
typedef
struct {
- HReg hreg[N_HREG_USAGE];
- HRegMode mode[N_HREG_USAGE];
- Int n_used;
+ /* The real registers. The associated universe is not stored
+ here -- callers will have to pass it around separately, as
+ needed. */
+ ULong rRead; /* real regs that are read */
+ ULong rWritten; /* real regs that are written */
+ /* The virtual registers. */
+ HReg vRegs[N_HREGUSAGE_VREGS];
+ HRegMode vMode[N_HREGUSAGE_VREGS];
+ UInt n_vRegs;
}
HRegUsage;
-extern void ppHRegUsage ( HRegUsage* );
+extern void ppHRegUsage ( const RRegUniverse*, HRegUsage* );
-static inline void initHRegUsage ( HRegUsage* tab ) {
- tab->n_used = 0;
+static inline void initHRegUsage ( HRegUsage* tab )
+{
+ tab->rRead = 0;
+ tab->rWritten = 0;
+ tab->n_vRegs = 0;
}
/* Add a register to a usage table. Combine incoming read uses with
*/
extern void addHRegUse ( HRegUsage*, HRegMode, HReg );
+extern Bool HRegUsage__contains ( const HRegUsage*, HReg );
/*---------------------------------------------------------*/
HRegRemap;
extern void ppHRegRemap ( HRegRemap* );
-extern void initHRegRemap ( HRegRemap* );
extern void addToHRegRemap ( HRegRemap*, HReg, HReg );
extern HReg lookupHRegRemap ( HRegRemap*, HReg );
+static inline void initHRegRemap ( HRegRemap* map )
+{
+ map->n_used = 0;
+}
+
/*---------------------------------------------------------*/
/*--- Abstract instructions ---*/
HInstrArray;
extern HInstrArray* newHInstrArray ( void );
-extern void addHInstr ( HInstrArray*, HInstr* );
+
+/* Never call this directly. It's the slow and incomplete path for
+ addHInstr. */
+__attribute__((noinline))
+extern void addHInstr_SLOW ( HInstrArray*, HInstr* );
+
+static inline void addHInstr ( HInstrArray* ha, HInstr* instr )
+{
+ if (LIKELY(ha->arr_used < ha->arr_size)) {
+ ha->arr[ha->arr_used] = instr;
+ ha->arr_used++;
+ } else {
+ addHInstr_SLOW(ha, instr);
+ }
+}
/*---------------------------------------------------------*/
/* Incoming virtual-registerised code. */
HInstrArray* instrs_in,
- /* An array listing all the real registers the allocator may use,
- in no particular order. */
- HReg* available_real_regs,
- Int n_available_real_regs,
+ /* The real-register universe to use. This contains facts about
+ real registers, one of which is the set of registers available
+ for allocation. */
+ const RRegUniverse* univ,
/* Return True iff the given insn is a reg-reg move, in which
case also return the src and dst regs. */
/* Register number for guest state pointer in host code. */
#define GuestSP 23
-#define MkHRegGPR(_n, _mode64) \
- mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
-
-#define MkHRegFPR(_n, _mode64) \
- mkHReg(_n, _mode64 ? HRcFlt64 : HRcFlt32, False)
/*---------------- Registers ----------------*/
+const RRegUniverse* getRRegUniverse_MIPS ( Bool mode64 )
+{
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. rRegUniverse_MIPS_initted values: 0=not initted,
+ 1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
+ static RRegUniverse rRegUniverse_MIPS;
+ static UInt rRegUniverse_MIPS_initted = 0;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_MIPS;
+
+ /* This isn't thread-safe. Sigh. */
+ UInt howNeeded = mode64 ? 2 : 1;
+ if (LIKELY(rRegUniverse_MIPS_initted == howNeeded))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+ ru->regs[ru->size++] = hregMIPS_GPR16(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR17(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR18(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR19(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR20(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR21(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR22(mode64);
+
+ ru->regs[ru->size++] = hregMIPS_GPR12(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR13(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR14(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR15(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR24(mode64);
+ /* s7 (=guest_state) */
+ ru->regs[ru->size++] = hregMIPS_F16(mode64);
+ ru->regs[ru->size++] = hregMIPS_F18(mode64);
+ ru->regs[ru->size++] = hregMIPS_F20(mode64);
+ ru->regs[ru->size++] = hregMIPS_F22(mode64);
+ ru->regs[ru->size++] = hregMIPS_F24(mode64);
+ ru->regs[ru->size++] = hregMIPS_F26(mode64);
+ ru->regs[ru->size++] = hregMIPS_F28(mode64);
+ ru->regs[ru->size++] = hregMIPS_F30(mode64);
+ if (!mode64) {
+ /* Fake double floating point */
+ ru->regs[ru->size++] = hregMIPS_D0(mode64);
+ ru->regs[ru->size++] = hregMIPS_D1(mode64);
+ ru->regs[ru->size++] = hregMIPS_D2(mode64);
+ ru->regs[ru->size++] = hregMIPS_D3(mode64);
+ ru->regs[ru->size++] = hregMIPS_D4(mode64);
+ ru->regs[ru->size++] = hregMIPS_D5(mode64);
+ ru->regs[ru->size++] = hregMIPS_D6(mode64);
+ ru->regs[ru->size++] = hregMIPS_D7(mode64);
+ }
+
+ ru->allocable = ru->size;
+ /* And other regs, not available to the allocator. */
+
+ ru->regs[ru->size++] = hregMIPS_HI(mode64);
+ ru->regs[ru->size++] = hregMIPS_LO(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR0(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR1(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR2(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR3(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR4(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR5(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR6(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR7(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR8(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR9(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR10(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR11(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR23(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR25(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR29(mode64);
+ ru->regs[ru->size++] = hregMIPS_GPR31(mode64);
+
+ rRegUniverse_MIPS_initted = howNeeded;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
+
void ppHRegMIPS(HReg reg, Bool mode64)
{
Int r;
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%s", ireg32_names[r]);
return;
case HRcInt64:
- r = hregNumber (reg);
+ r = hregEncoding (reg);
vassert (r >= 0 && r < 32);
vex_printf ("%s", ireg32_names[r]);
return;
case HRcFlt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%s", freg32_names[r]);
return;
case HRcFlt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%s", freg64_names[r]);
return;
return;
}
-HReg hregMIPS_GPR0(Bool mode64)
-{
- return MkHRegGPR(0, mode64);
-}
-
-HReg hregMIPS_GPR1(Bool mode64)
-{
- return MkHRegGPR(1, mode64);
-}
-
-HReg hregMIPS_GPR2(Bool mode64)
-{
- return MkHRegGPR(2, mode64);
-}
-
-HReg hregMIPS_GPR3(Bool mode64)
-{
- return MkHRegGPR(3, mode64);
-}
-
-HReg hregMIPS_GPR4(Bool mode64)
-{
- return MkHRegGPR(4, mode64);
-}
-
-HReg hregMIPS_GPR5(Bool mode64)
-{
- return MkHRegGPR(5, mode64);
-}
-
-HReg hregMIPS_GPR6(Bool mode64)
-{
- return MkHRegGPR(6, mode64);
-}
-
-HReg hregMIPS_GPR7(Bool mode64)
-{
- return MkHRegGPR(7, mode64);
-}
-
-HReg hregMIPS_GPR8(Bool mode64)
-{
- return MkHRegGPR(8, mode64);
-}
-
-HReg hregMIPS_GPR9(Bool mode64)
-{
- return MkHRegGPR(9, mode64);
-}
-
-HReg hregMIPS_GPR10(Bool mode64)
-{
- return MkHRegGPR(10, mode64);
-}
-
-HReg hregMIPS_GPR11(Bool mode64)
-{
- return MkHRegGPR(11, mode64);
-}
-
-HReg hregMIPS_GPR12(Bool mode64)
-{
- return MkHRegGPR(12, mode64);
-}
-
-HReg hregMIPS_GPR13(Bool mode64)
-{
- return MkHRegGPR(13, mode64);
-}
-
-HReg hregMIPS_GPR14(Bool mode64)
-{
- return MkHRegGPR(14, mode64);
-}
-
-HReg hregMIPS_GPR15(Bool mode64)
-{
- return MkHRegGPR(15, mode64);
-}
-
-HReg hregMIPS_GPR16(Bool mode64)
-{
- return MkHRegGPR(16, mode64);
-}
-
-HReg hregMIPS_GPR17(Bool mode64)
-{
- return MkHRegGPR(17, mode64);
-}
-
-HReg hregMIPS_GPR18(Bool mode64)
-{
- return MkHRegGPR(18, mode64);
-}
-
-HReg hregMIPS_GPR19(Bool mode64)
-{
- return MkHRegGPR(19, mode64);
-}
-
-HReg hregMIPS_GPR20(Bool mode64)
-{
- return MkHRegGPR(20, mode64);
-}
-
-HReg hregMIPS_GPR21(Bool mode64)
-{
- return MkHRegGPR(21, mode64);
-}
-
-HReg hregMIPS_GPR22(Bool mode64)
-{
- return MkHRegGPR(22, mode64);
-}
-
-HReg hregMIPS_GPR23(Bool mode64)
-{
- return MkHRegGPR(23, mode64);
-}
-
-HReg hregMIPS_GPR24(Bool mode64)
-{
- return MkHRegGPR(24, mode64);
-}
-
-HReg hregMIPS_GPR25(Bool mode64)
-{
- return MkHRegGPR(25, mode64);
-}
-
-HReg hregMIPS_GPR26(Bool mode64)
-{
- return MkHRegGPR(26, mode64);
-}
-
-HReg hregMIPS_GPR27(Bool mode64)
-{
- return MkHRegGPR(27, mode64);
-}
-
-HReg hregMIPS_GPR28(Bool mode64)
-{
- return MkHRegGPR(28, mode64);
-}
-
-HReg hregMIPS_GPR29(Bool mode64)
-{
- return MkHRegGPR(29, mode64);
-}
-
-HReg hregMIPS_GPR30(Bool mode64)
-{
- return MkHRegGPR(30, mode64);
-}
-
-HReg hregMIPS_GPR31(Bool mode64)
-{
- return MkHRegGPR(31, mode64);
-}
-
-HReg hregMIPS_F0(Bool mode64)
-{
- return MkHRegFPR(0, mode64);
-}
-
-HReg hregMIPS_F1(Bool mode64)
-{
- return MkHRegFPR(1, mode64);
-}
-
-HReg hregMIPS_F2(Bool mode64)
-{
- return MkHRegFPR(2, mode64);
-}
-
-HReg hregMIPS_F3(Bool mode64)
-{
- return MkHRegFPR(3, mode64);
-}
-
-HReg hregMIPS_F4(Bool mode64)
-{
- return MkHRegFPR(4, mode64);
-}
-
-HReg hregMIPS_F5(Bool mode64)
-{
- return MkHRegFPR(5, mode64);
-}
-
-HReg hregMIPS_F6(Bool mode64)
-{
- return MkHRegFPR(6, mode64);
-}
-
-HReg hregMIPS_F7(Bool mode64)
-{
- return MkHRegFPR(7, mode64);
-}
-
-HReg hregMIPS_F8(Bool mode64)
-{
- return MkHRegFPR(8, mode64);
-}
-
-HReg hregMIPS_F9(Bool mode64)
-{
- return MkHRegFPR(9, mode64);
-}
-
-HReg hregMIPS_F10(Bool mode64)
-{
- return MkHRegFPR(10, mode64);
-}
-
-HReg hregMIPS_F11(Bool mode64)
-{
- return MkHRegFPR(11, mode64);
-}
-
-HReg hregMIPS_F12(Bool mode64)
-{
- return MkHRegFPR(12, mode64);
-}
-
-HReg hregMIPS_F13(Bool mode64)
-{
- return MkHRegFPR(13, mode64);
-}
-
-HReg hregMIPS_F14(Bool mode64)
-{
- return MkHRegFPR(14, mode64);
-}
-
-HReg hregMIPS_F15(Bool mode64)
-{
- return MkHRegFPR(15, mode64);
-}
-
-HReg hregMIPS_F16(Bool mode64)
-{
- return MkHRegFPR(16, mode64);
-}
-
-HReg hregMIPS_F17(Bool mode64)
-{
- return MkHRegFPR(17, mode64);
-}
-
-HReg hregMIPS_F18(Bool mode64)
-{
- return MkHRegFPR(18, mode64);
-}
-
-HReg hregMIPS_F19(Bool mode64)
-{
- return MkHRegFPR(19, mode64);
-}
-
-HReg hregMIPS_F20(Bool mode64)
-{
- return MkHRegFPR(20, mode64);
-}
-
-HReg hregMIPS_F21(Bool mode64)
-{
- return MkHRegFPR(21, mode64);
-}
-
-HReg hregMIPS_F22(Bool mode64)
-{
- return MkHRegFPR(22, mode64);
-}
-
-HReg hregMIPS_F23(Bool mode64)
-{
- return MkHRegFPR(23, mode64);
-}
-
-HReg hregMIPS_F24(Bool mode64)
-{
- return MkHRegFPR(24, mode64);
-}
-
-HReg hregMIPS_F25(Bool mode64)
-{
- return MkHRegFPR(25, mode64);
-}
-
-HReg hregMIPS_F26(Bool mode64)
-{
- return MkHRegFPR(26, mode64);
-}
-
-HReg hregMIPS_F27(Bool mode64)
-{
- return MkHRegFPR(27, mode64);
-}
-
-HReg hregMIPS_F28(Bool mode64)
-{
- return MkHRegFPR(28, mode64);
-}
-
-HReg hregMIPS_F29(Bool mode64)
-{
- return MkHRegFPR(29, mode64);
-}
-
-HReg hregMIPS_F30(Bool mode64)
-{
- return MkHRegFPR(30, mode64);
-}
-
-HReg hregMIPS_F31(Bool mode64)
-{
- return MkHRegFPR(31, mode64);
-}
-
-HReg hregMIPS_PC(Bool mode64)
-{
- return mkHReg(32, mode64 ? HRcFlt64 : HRcFlt32, False);
-}
-
-HReg hregMIPS_HI(Bool mode64)
-{
- return mkHReg(33, mode64 ? HRcFlt64 : HRcFlt32, False);
-}
-
-HReg hregMIPS_LO(Bool mode64)
-{
- return mkHReg(34, mode64 ? HRcFlt64 : HRcFlt32, False);
-}
-
-HReg hregMIPS_D0(void)
-{
- return mkHReg(0, HRcFlt64, False);
-}
-
-HReg hregMIPS_D1(void)
-{
- return mkHReg(2, HRcFlt64, False);
-}
-
-HReg hregMIPS_D2(void)
-{
- return mkHReg(4, HRcFlt64, False);
-}
-
-HReg hregMIPS_D3(void)
-{
- return mkHReg(6, HRcFlt64, False);
-}
-
-HReg hregMIPS_D4(void)
-{
- return mkHReg(8, HRcFlt64, False);
-}
-
-HReg hregMIPS_D5(void)
-{
- return mkHReg(10, HRcFlt64, False);
-}
-
-HReg hregMIPS_D6(void)
-{
- return mkHReg(12, HRcFlt64, False);
-}
-
-HReg hregMIPS_D7(void)
-{
- return mkHReg(14, HRcFlt64, False);
-}
-
-HReg hregMIPS_D8(void)
-{
- return mkHReg(16, HRcFlt64, False);
-}
-
-HReg hregMIPS_D9(void)
-{
- return mkHReg(18, HRcFlt64, False);
-}
-
-HReg hregMIPS_D10(void)
-{
- return mkHReg(20, HRcFlt64, False);
-}
-
-HReg hregMIPS_D11(void)
-{
- return mkHReg(22, HRcFlt64, False);
-}
-
-HReg hregMIPS_D12(void)
-{
- return mkHReg(24, HRcFlt64, False);
-}
-
-HReg hregMIPS_D13(void)
-{
- return mkHReg(26, HRcFlt64, False);
-}
-
-HReg hregMIPS_D14(void)
-{
- return mkHReg(28, HRcFlt64, False);
-}
-
-HReg hregMIPS_D15(void)
-{
- return mkHReg(30, HRcFlt64, False);
-}
-
-HReg hregMIPS_FIR(void)
-{
- return mkHReg(35, HRcInt32, False);
-}
-
-HReg hregMIPS_FCCR(void)
-{
- return mkHReg(36, HRcInt32, False);
-}
-
-HReg hregMIPS_FEXR(void)
-{
- return mkHReg(37, HRcInt32, False);
-}
-
-HReg hregMIPS_FENR(void)
-{
- return mkHReg(38, HRcInt32, False);
-}
-
-HReg hregMIPS_FCSR(void)
-{
- return mkHReg(39, HRcInt32, False);
-}
-
-HReg hregMIPS_COND(void)
-{
- return mkHReg(47, HRcInt32, False);
-}
-
-void getAllocableRegs_MIPS(Int * nregs, HReg ** arr, Bool mode64)
-{
- /* The list of allocable registers is shorten to fit MIPS32 mode on Loongson.
- More precisely, we workaround Loongson MIPS32 issues by avoiding usage of
- odd single precision FP registers. */
- if (mode64)
- *nregs = 20;
- else
- *nregs = 28;
- UInt i = 0;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
-
- /* ZERO = constant 0
- AT = assembler temporary
- callee saves ones are listed first, since we prefer them
- if they're available */
- (*arr)[i++] = hregMIPS_GPR16(mode64);
- (*arr)[i++] = hregMIPS_GPR17(mode64);
- (*arr)[i++] = hregMIPS_GPR18(mode64);
- (*arr)[i++] = hregMIPS_GPR19(mode64);
- (*arr)[i++] = hregMIPS_GPR20(mode64);
- (*arr)[i++] = hregMIPS_GPR21(mode64);
- (*arr)[i++] = hregMIPS_GPR22(mode64);
-
- (*arr)[i++] = hregMIPS_GPR12(mode64);
- (*arr)[i++] = hregMIPS_GPR13(mode64);
- (*arr)[i++] = hregMIPS_GPR14(mode64);
- (*arr)[i++] = hregMIPS_GPR15(mode64);
- (*arr)[i++] = hregMIPS_GPR24(mode64);
- /* s7 (=guest_state) */
- (*arr)[i++] = hregMIPS_F16(mode64);
- (*arr)[i++] = hregMIPS_F18(mode64);
- (*arr)[i++] = hregMIPS_F20(mode64);
- (*arr)[i++] = hregMIPS_F22(mode64);
- (*arr)[i++] = hregMIPS_F24(mode64);
- (*arr)[i++] = hregMIPS_F26(mode64);
- (*arr)[i++] = hregMIPS_F28(mode64);
- (*arr)[i++] = hregMIPS_F30(mode64);
- if (!mode64) {
- /* Fake double floating point */
- (*arr)[i++] = hregMIPS_D0();
- (*arr)[i++] = hregMIPS_D1();
- (*arr)[i++] = hregMIPS_D2();
- (*arr)[i++] = hregMIPS_D3();
- (*arr)[i++] = hregMIPS_D4();
- (*arr)[i++] = hregMIPS_D5();
- (*arr)[i++] = hregMIPS_D6();
- (*arr)[i++] = hregMIPS_D7();
- }
- vassert(i == *nregs);
-
-}
/*----------------- Condition Codes ----------------------*/
ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
break;
case Mam_RR:
- ret = MIPSAMode_RR(mkHReg(hregNumber(am->Mam.RR.index) + 1,
- hregClass(am->Mam.RR.index),
- hregIsVirtual(am->Mam.RR.index)),
- am->Mam.RR.base);
- break;
+ /* We can't do anything with the RR case, so if it appears
+ we simply have to give up. */
+ /* fallthrough */
default:
- vpanic("dopyMIPSAMode");
+ vpanic("nextMIPSAModeFloat");
break;
}
return ret;
ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
break;
case Mam_RR:
- ret = MIPSAMode_RR(mkHReg(hregNumber(am->Mam.RR.index) + 1,
- hregClass(am->Mam.RR.index),
- hregIsVirtual(am->Mam.RR.index)),
- am->Mam.RR.base);
- break;
+ /* We can't do anything with the RR case, so if it appears
+ we simply have to give up. */
+ /* fallthrough */
default:
- vpanic("dopyMIPSAMode");
+ vpanic("nextMIPSAModeInt");
break;
}
return ret;
return False;
if (i->Min.Alu.srcR->tag != Mrh_Reg)
return False;
- if (hregNumber(i->Min.Alu.srcR->Mrh.Reg.reg)
- != hregNumber(i->Min.Alu.srcL))
+ if (!sameHReg(i->Min.Alu.srcR->Mrh.Reg.reg, i->Min.Alu.srcL))
return False;
*src = i->Min.Alu.srcL;
*dst = i->Min.Alu.dst;
/* --------- The mips assembler --------- */
-static UInt iregNo(HReg r, Bool mode64)
+inline static UInt iregNo(HReg r, Bool mode64)
{
UInt n;
vassert(hregClass(r) == (mode64 ? HRcInt64 : HRcInt32));
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 32);
return n;
}
-static UChar fregNo(HReg r, Bool mode64)
+inline static UInt fregNo(HReg r, Bool mode64)
{
UInt n;
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
return n;
}
-static UChar dregNo(HReg r)
+inline static UInt dregNo(HReg r)
{
UInt n;
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 31);
return n;
}
#include "libvex.h" /* VexArch */
#include "host_generic_regs.h" /* HReg */
-/* Num registers used for function calls */
-#if defined(VGP_mips32_linux)
-/* a0, a1, a2, a3 */
-#define MIPS_N_REGPARMS 4
-#else
-/* a0, a1, a2, a3, a4, a5, a6, a7 */
-#define MIPS_N_REGPARMS 8
-#endif
-/* --------- Registers. --------- */
-/* The usual HReg abstraction.
- There are 32 general purpose regs.
-*/
+/* --------- Registers. --------- */
-extern void ppHRegMIPS(HReg, Bool);
-
-extern HReg hregMIPS_GPR0(Bool mode64); /* scratch reg / zero reg */
-extern HReg hregMIPS_GPR1(Bool mode64);
-extern HReg hregMIPS_GPR2(Bool mode64);
-extern HReg hregMIPS_GPR3(Bool mode64);
-extern HReg hregMIPS_GPR4(Bool mode64);
-extern HReg hregMIPS_GPR5(Bool mode64);
-extern HReg hregMIPS_GPR6(Bool mode64);
-extern HReg hregMIPS_GPR7(Bool mode64);
-extern HReg hregMIPS_GPR8(Bool mode64);
-extern HReg hregMIPS_GPR9(Bool mode64);
-extern HReg hregMIPS_GPR10(Bool mode64);
-extern HReg hregMIPS_GPR11(Bool mode64);
-extern HReg hregMIPS_GPR12(Bool mode64);
-extern HReg hregMIPS_GPR13(Bool mode64);
-extern HReg hregMIPS_GPR14(Bool mode64);
-extern HReg hregMIPS_GPR15(Bool mode64);
-extern HReg hregMIPS_GPR16(Bool mode64);
-extern HReg hregMIPS_GPR17(Bool mode64);
-extern HReg hregMIPS_GPR18(Bool mode64);
-extern HReg hregMIPS_GPR19(Bool mode64);
-extern HReg hregMIPS_GPR20(Bool mode64);
-extern HReg hregMIPS_GPR21(Bool mode64);
-extern HReg hregMIPS_GPR22(Bool mode64);
-extern HReg hregMIPS_GPR23(Bool mode64); /* GuestStatePtr */
-extern HReg hregMIPS_GPR24(Bool mode64);
-extern HReg hregMIPS_GPR25(Bool mode64);
-extern HReg hregMIPS_GPR26(Bool mode64);
-extern HReg hregMIPS_GPR27(Bool mode64);
-extern HReg hregMIPS_GPR28(Bool mode64);
-extern HReg hregMIPS_GPR29(Bool mode64);
-extern HReg hregMIPS_GPR30(Bool mode64);
-extern HReg hregMIPS_GPR31(Bool mode64);
-extern HReg hregMIPS_PC(Bool mode64);
-
-extern HReg hregMIPS_HI(Bool mode64);
-extern HReg hregMIPS_LO(Bool mode64);
-
-extern HReg hregMIPS_F0(Bool mode64);
-extern HReg hregMIPS_F1(Bool mode64);
-extern HReg hregMIPS_F2(Bool mode64);
-extern HReg hregMIPS_F3(Bool mode64);
-extern HReg hregMIPS_F4(Bool mode64);
-extern HReg hregMIPS_F5(Bool mode64);
-extern HReg hregMIPS_F6(Bool mode64);
-extern HReg hregMIPS_F7(Bool mode64);
-extern HReg hregMIPS_F8(Bool mode64);
-extern HReg hregMIPS_F9(Bool mode64);
-extern HReg hregMIPS_F10(Bool mode64);
-extern HReg hregMIPS_F11(Bool mode64);
-extern HReg hregMIPS_F12(Bool mode64);
-extern HReg hregMIPS_F13(Bool mode64);
-extern HReg hregMIPS_F14(Bool mode64);
-extern HReg hregMIPS_F15(Bool mode64);
-extern HReg hregMIPS_F16(Bool mode64);
-extern HReg hregMIPS_F17(Bool mode64);
-extern HReg hregMIPS_F18(Bool mode64);
-extern HReg hregMIPS_F19(Bool mode64);
-extern HReg hregMIPS_F20(Bool mode64);
-extern HReg hregMIPS_F21(Bool mode64);
-extern HReg hregMIPS_F22(Bool mode64);
-extern HReg hregMIPS_F23(Bool mode64);
-extern HReg hregMIPS_F24(Bool mode64);
-extern HReg hregMIPS_F25(Bool mode64);
-extern HReg hregMIPS_F26(Bool mode64);
-extern HReg hregMIPS_F27(Bool mode64);
-extern HReg hregMIPS_F28(Bool mode64);
-extern HReg hregMIPS_F29(Bool mode64);
-extern HReg hregMIPS_F30(Bool mode64);
-extern HReg hregMIPS_F31(Bool mode64);
-extern HReg hregMIPS_FIR(void);
-extern HReg hregMIPS_FCCR(void);
-extern HReg hregMIPS_FEXR(void);
-extern HReg hregMIPS_FENR(void);
-extern HReg hregMIPS_FCSR(void);
-extern HReg hregMIPS_COND(void);
-
-extern HReg hregMIPS_D0(void);
-extern HReg hregMIPS_D1(void);
-extern HReg hregMIPS_D2(void);
-extern HReg hregMIPS_D3(void);
-extern HReg hregMIPS_D4(void);
-extern HReg hregMIPS_D5(void);
-extern HReg hregMIPS_D6(void);
-extern HReg hregMIPS_D7(void);
-extern HReg hregMIPS_D8(void);
-extern HReg hregMIPS_D9(void);
-extern HReg hregMIPS_D10(void);
-extern HReg hregMIPS_D11(void);
-extern HReg hregMIPS_D12(void);
-extern HReg hregMIPS_D13(void);
-extern HReg hregMIPS_D14(void);
-extern HReg hregMIPS_D15(void);
+#define ST_IN static inline
+
+#define GPR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, (_mode64) ? HRcInt64 : HRcInt32, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+#define FR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, (_mode64) ? HRcFlt64 : HRcFlt32, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+#define DR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, HRcFlt64, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+ST_IN HReg hregMIPS_GPR16 ( Bool mode64 ) { return GPR(mode64, 16, 0, 0); }
+ST_IN HReg hregMIPS_GPR17 ( Bool mode64 ) { return GPR(mode64, 17, 1, 1); }
+ST_IN HReg hregMIPS_GPR18 ( Bool mode64 ) { return GPR(mode64, 18, 2, 2); }
+ST_IN HReg hregMIPS_GPR19 ( Bool mode64 ) { return GPR(mode64, 19, 3, 3); }
+ST_IN HReg hregMIPS_GPR20 ( Bool mode64 ) { return GPR(mode64, 20, 4, 4); }
+ST_IN HReg hregMIPS_GPR21 ( Bool mode64 ) { return GPR(mode64, 21, 5, 5); }
+ST_IN HReg hregMIPS_GPR22 ( Bool mode64 ) { return GPR(mode64, 22, 6, 6); }
+
+ST_IN HReg hregMIPS_GPR12 ( Bool mode64 ) { return GPR(mode64, 12, 7, 7); }
+ST_IN HReg hregMIPS_GPR13 ( Bool mode64 ) { return GPR(mode64, 13, 8, 8); }
+ST_IN HReg hregMIPS_GPR14 ( Bool mode64 ) { return GPR(mode64, 14, 9, 9); }
+ST_IN HReg hregMIPS_GPR15 ( Bool mode64 ) { return GPR(mode64, 15, 10, 10); }
+ST_IN HReg hregMIPS_GPR24 ( Bool mode64 ) { return GPR(mode64, 24, 11, 11); }
+
+ST_IN HReg hregMIPS_F16 ( Bool mode64 ) { return FR (mode64, 16, 12, 12); }
+ST_IN HReg hregMIPS_F18 ( Bool mode64 ) { return FR (mode64, 18, 13, 13); }
+ST_IN HReg hregMIPS_F20 ( Bool mode64 ) { return FR (mode64, 20, 14, 14); }
+ST_IN HReg hregMIPS_F22 ( Bool mode64 ) { return FR (mode64, 22, 15, 15); }
+ST_IN HReg hregMIPS_F24 ( Bool mode64 ) { return FR (mode64, 24, 16, 16); }
+ST_IN HReg hregMIPS_F26 ( Bool mode64 ) { return FR (mode64, 26, 17, 17); }
+ST_IN HReg hregMIPS_F28 ( Bool mode64 ) { return FR (mode64, 28, 18, 18); }
+ST_IN HReg hregMIPS_F30 ( Bool mode64 ) { return FR (mode64, 30, 19, 19); }
+
+// DRs are only allocatable in 32-bit mode, so the 64-bit index numbering
+// doesn't advance here.
+ST_IN HReg hregMIPS_D0 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 0, 0, 20); }
+ST_IN HReg hregMIPS_D1 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 2, 0, 21); }
+ST_IN HReg hregMIPS_D2 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 4, 0, 22); }
+ST_IN HReg hregMIPS_D3 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 6, 0, 23); }
+ST_IN HReg hregMIPS_D4 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 8, 0, 24); }
+ST_IN HReg hregMIPS_D5 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 10, 0, 25); }
+ST_IN HReg hregMIPS_D6 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 12, 0, 26); }
+ST_IN HReg hregMIPS_D7 ( Bool mode64 ) { vassert(!mode64);
+ return DR (mode64, 14, 0, 27); }
+
+ST_IN HReg hregMIPS_HI ( Bool mode64 ) { return FR (mode64, 33, 20, 28); }
+ST_IN HReg hregMIPS_LO ( Bool mode64 ) { return FR (mode64, 34, 21, 29); }
+
+ST_IN HReg hregMIPS_GPR0 ( Bool mode64 ) { return GPR(mode64, 0, 22, 30); }
+ST_IN HReg hregMIPS_GPR1 ( Bool mode64 ) { return GPR(mode64, 1, 23, 31); }
+ST_IN HReg hregMIPS_GPR2 ( Bool mode64 ) { return GPR(mode64, 2, 24, 32); }
+ST_IN HReg hregMIPS_GPR3 ( Bool mode64 ) { return GPR(mode64, 3, 25, 33); }
+ST_IN HReg hregMIPS_GPR4 ( Bool mode64 ) { return GPR(mode64, 4, 26, 34); }
+ST_IN HReg hregMIPS_GPR5 ( Bool mode64 ) { return GPR(mode64, 5, 27, 35); }
+ST_IN HReg hregMIPS_GPR6 ( Bool mode64 ) { return GPR(mode64, 6, 28, 36); }
+ST_IN HReg hregMIPS_GPR7 ( Bool mode64 ) { return GPR(mode64, 7, 29, 37); }
+ST_IN HReg hregMIPS_GPR8 ( Bool mode64 ) { return GPR(mode64, 8, 30, 38); }
+ST_IN HReg hregMIPS_GPR9 ( Bool mode64 ) { return GPR(mode64, 9, 31, 39); }
+ST_IN HReg hregMIPS_GPR10 ( Bool mode64 ) { return GPR(mode64, 10, 32, 40); }
+ST_IN HReg hregMIPS_GPR11 ( Bool mode64 ) { return GPR(mode64, 11, 33, 41); }
+ST_IN HReg hregMIPS_GPR23 ( Bool mode64 ) { return GPR(mode64, 23, 34, 42); }
+ST_IN HReg hregMIPS_GPR25 ( Bool mode64 ) { return GPR(mode64, 25, 35, 43); }
+ST_IN HReg hregMIPS_GPR29 ( Bool mode64 ) { return GPR(mode64, 29, 36, 44); }
+ST_IN HReg hregMIPS_GPR31 ( Bool mode64 ) { return GPR(mode64, 31, 37, 45); }
+
+#undef ST_IN
+#undef GPR
+#undef FR
+#undef DR
#define GuestStatePointer(_mode64) hregMIPS_GPR23(_mode64)
-
#define StackFramePointer(_mode64) hregMIPS_GPR30(_mode64)
-#define LinkRegister(_mode64) hregMIPS_GPR31(_mode64)
#define StackPointer(_mode64) hregMIPS_GPR29(_mode64)
-#define FCSR() hregMIPS_FCSR()
-#define COND() hregMIPS_COND()
-
-#define HIRegister(_mode64) hregMIPS_HI(_mode64)
-#define LORegister(_mode64) hregMIPS_LO(_mode64)
-
-#if defined(VGP_mips64_linux)
-/* a0, a1, a2, a3, a4, a5, a6, a7 */
-#define MIPS_N_ARGREGS 8
-#elif defined(VGP_mips32_linux)
-/* a0, a1, a2, a3 */
-#define MIPS_N_ARGREGS 4
+
+/* Num registers used for function calls */
+#if defined(VGP_mips32_linux)
+ /* a0, a1, a2, a3 */
+# define MIPS_N_REGPARMS 4
+#else
+ /* a0, a1, a2, a3, a4, a5, a6, a7 */
+# define MIPS_N_REGPARMS 8
#endif
+extern void ppHRegMIPS ( HReg, Bool );
+
+
/* --------- Condition codes, Intel encoding. --------- */
typedef enum {
MIPScc_EQ = 0, /* equal */
extern void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2,
HReg rreg, Int offset, Bool);
-extern void getAllocableRegs_MIPS (Int *, HReg **, Bool mode64);
+extern const RRegUniverse* getRRegUniverse_MIPS ( Bool mode64 );
+
extern HInstrArray *iselSB_MIPS ( const IRSB*,
VexArch,
const VexArchInfo*,
static Bool fp_mode64 = False;
/* GPR register class for mips32/64 */
-#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
+#define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
/* FPR register class for mips32/64 */
-#define HRcFPR(__mode64) (__mode64 ? HRcFlt64 : HRcFlt32)
+#define HRcFPR(_mode64) ((_mode64) ? HRcFlt64 : HRcFlt32)
/* guest_COND offset */
-#define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
+#define COND_OFFSET(_mode64) ((_mode64) ? 612 : 448)
/*---------------------------------------------------------*/
/*--- ISelEnv ---*/
static HReg newVRegI(ISelEnv * env)
{
- HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
- True /*virtual reg */ );
+ HReg reg = mkHReg(True/*virtual reg*/,
+ HRcGPR(env->mode64), 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegD(ISelEnv * env)
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /*virtual reg */ );
+ HReg reg = mkHReg(True/*virtual reg*/,
+ HRcFlt64, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegF(ISelEnv * env)
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->fp_mode64),
- True /*virtual reg */ );
+ HReg reg = mkHReg(True/*virtual reg*/,
+ HRcFPR(env->mode64), 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
case Ity_I16:
case Ity_I32:
if (mode64) {
- hreg = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
break;
} else {
- hreg = mkHReg(j++, HRcInt32, True);
+ hreg = mkHReg(True, HRcInt32, 0, j++);
break;
}
case Ity_I64:
if (mode64) {
- hreg = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
break;
} else {
- hreg = mkHReg(j++, HRcInt32, True);
- hregHI = mkHReg(j++, HRcInt32, True);
+ hreg = mkHReg(True, HRcInt32, 0, j++);
+ hregHI = mkHReg(True, HRcInt32, 0, j++);
break;
}
case Ity_I128:
vassert(mode64);
- hreg = mkHReg(j++, HRcInt64, True);
- hregHI = mkHReg(j++, HRcInt64, True);
+ hreg = mkHReg(True, HRcInt64, 0, j++);
+ hregHI = mkHReg(True, HRcInt64, 0, j++);
break;
case Ity_F32:
if (mode64) {
- hreg = mkHReg(j++, HRcFlt64, True);
+ hreg = mkHReg(True, HRcFlt64, 0, j++);
break;
} else {
- hreg = mkHReg(j++, HRcFlt32, True);
+ hreg = mkHReg(True, HRcFlt32, 0, j++);
break;
}
case Ity_F64:
- hreg = mkHReg(j++, HRcFlt64, True);
+ hreg = mkHReg(True, HRcFlt64, 0, j++);
break;
default:
ppIRType(bb->tyenv->types[i]);
/* --------- Registers. --------- */
+const RRegUniverse* getRRegUniverse_PPC ( Bool mode64 )
+{
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. rRegUniverse_PPC_initted values: 0=not initted,
+ 1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
+ static RRegUniverse rRegUniverse_PPC;
+ static UInt rRegUniverse_PPC_initted = 0;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_PPC;
+
+ /* This isn't thread-safe. Sigh. */
+ UInt howNeeded = mode64 ? 2 : 1;
+ if (LIKELY(rRegUniverse_PPC_initted == howNeeded))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+ // GPR0 = scratch reg where poss. - some ops interpret as value zero
+ // GPR1 = stack pointer
+ // GPR2 = TOC pointer
+ ru->regs[ru->size++] = hregPPC_GPR3(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR4(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR5(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR6(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR7(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR8(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR9(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR10(mode64);
+ if (!mode64) {
+ /* in mode64:
+ r11 used for calls by ptr / env ptr for some langs
+ r12 used for exception handling and global linkage code */
+ ru->regs[ru->size++] = hregPPC_GPR11(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR12(mode64);
+ }
+ // GPR13 = thread specific pointer
+ // GPR14 and above are callee save. Yay.
+ ru->regs[ru->size++] = hregPPC_GPR14(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR15(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR16(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR17(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR18(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR19(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR20(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR21(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR22(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR23(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR24(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR25(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR26(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR27(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR28(mode64);
+ // GPR29 is reserved for the dispatcher
+ // GPR30 is reserved as AltiVec spill reg temporary
+ // GPR31 is reserved for the GuestStatePtr
+
+ /* Don't waste the reg-allocs's time trawling through zillions of
+ FP registers - they mostly will never be used. We'll tolerate
+ the occasional extra spill instead. */
+ /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
+ So use them. */
+ ru->regs[ru->size++] = hregPPC_FPR14(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR15(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR16(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR17(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR18(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR19(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR20(mode64);
+ ru->regs[ru->size++] = hregPPC_FPR21(mode64);
+
+ /* Same deal re Altivec */
+ /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
+ So use them. */
+ /* NB, vr29 is used as a scratch temporary -- do not allocate */
+ ru->regs[ru->size++] = hregPPC_VR20(mode64);
+ ru->regs[ru->size++] = hregPPC_VR21(mode64);
+ ru->regs[ru->size++] = hregPPC_VR22(mode64);
+ ru->regs[ru->size++] = hregPPC_VR23(mode64);
+ ru->regs[ru->size++] = hregPPC_VR24(mode64);
+ ru->regs[ru->size++] = hregPPC_VR25(mode64);
+ ru->regs[ru->size++] = hregPPC_VR26(mode64);
+ ru->regs[ru->size++] = hregPPC_VR27(mode64);
+ ru->allocable = ru->size;
+
+ /* And other regs, not available to the allocator. */
+ ru->regs[ru->size++] = hregPPC_GPR1(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR29(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR30(mode64);
+ ru->regs[ru->size++] = hregPPC_GPR31(mode64);
+ ru->regs[ru->size++] = hregPPC_VR29(mode64);
+
+ rRegUniverse_PPC_initted = howNeeded;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
+
void ppHRegPPC ( HReg reg )
{
Int r;
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%s", ireg32_names[r]);
return;
case HRcInt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%s", ireg32_names[r]);
return;
case HRcFlt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%%fr%d", r);
return;
case HRcVec128:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 32);
vex_printf("%%v%d", r);
return;
}
-#define MkHRegGPR(_n, _mode64) \
- mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
-
-HReg hregPPC_GPR0 ( Bool mode64 ) { return MkHRegGPR( 0, mode64); }
-HReg hregPPC_GPR1 ( Bool mode64 ) { return MkHRegGPR( 1, mode64); }
-HReg hregPPC_GPR2 ( Bool mode64 ) { return MkHRegGPR( 2, mode64); }
-HReg hregPPC_GPR3 ( Bool mode64 ) { return MkHRegGPR( 3, mode64); }
-HReg hregPPC_GPR4 ( Bool mode64 ) { return MkHRegGPR( 4, mode64); }
-HReg hregPPC_GPR5 ( Bool mode64 ) { return MkHRegGPR( 5, mode64); }
-HReg hregPPC_GPR6 ( Bool mode64 ) { return MkHRegGPR( 6, mode64); }
-HReg hregPPC_GPR7 ( Bool mode64 ) { return MkHRegGPR( 7, mode64); }
-HReg hregPPC_GPR8 ( Bool mode64 ) { return MkHRegGPR( 8, mode64); }
-HReg hregPPC_GPR9 ( Bool mode64 ) { return MkHRegGPR( 9, mode64); }
-HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); }
-HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); }
-HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); }
-HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); }
-HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); }
-HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); }
-HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); }
-HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); }
-HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); }
-HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); }
-HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); }
-HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); }
-HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); }
-HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); }
-HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); }
-HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); }
-HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); }
-HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); }
-HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); }
-HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); }
-HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); }
-HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); }
-
-#undef MK_INT_HREG
-
-HReg hregPPC_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
-HReg hregPPC_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
-HReg hregPPC_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
-HReg hregPPC_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
-HReg hregPPC_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
-HReg hregPPC_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
-HReg hregPPC_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
-HReg hregPPC_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
-HReg hregPPC_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
-HReg hregPPC_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
-HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
-HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
-HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
-HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
-HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
-HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
-HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
-HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
-HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
-HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
-HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
-HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
-HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
-HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
-HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
-HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
-HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
-HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
-HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
-HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
-HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
-HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
-
-HReg hregPPC_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
-HReg hregPPC_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
-HReg hregPPC_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
-HReg hregPPC_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
-HReg hregPPC_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
-HReg hregPPC_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
-HReg hregPPC_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
-HReg hregPPC_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
-HReg hregPPC_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
-HReg hregPPC_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
-HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
-HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
-HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
-HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
-HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
-HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
-HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
-HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
-HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
-HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
-HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
-HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
-HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
-HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
-HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
-HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
-HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
-HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
-HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
-HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
-HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
-HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
-
-void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 )
-{
- UInt i=0;
- if (mode64)
- *nregs = (32-9) + (32-24) + (32-24);
- else
- *nregs = (32-7) + (32-24) + (32-24);
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
- // GPR0 = scratch reg where poss. - some ops interpret as value zero
- // GPR1 = stack pointer
- // GPR2 = TOC pointer
- (*arr)[i++] = hregPPC_GPR3(mode64);
- (*arr)[i++] = hregPPC_GPR4(mode64);
- (*arr)[i++] = hregPPC_GPR5(mode64);
- (*arr)[i++] = hregPPC_GPR6(mode64);
- (*arr)[i++] = hregPPC_GPR7(mode64);
- (*arr)[i++] = hregPPC_GPR8(mode64);
- (*arr)[i++] = hregPPC_GPR9(mode64);
- (*arr)[i++] = hregPPC_GPR10(mode64);
- if (!mode64) {
- /* in mode64:
- r11 used for calls by ptr / env ptr for some langs
- r12 used for exception handling and global linkage code */
- (*arr)[i++] = hregPPC_GPR11(mode64);
- (*arr)[i++] = hregPPC_GPR12(mode64);
- }
- // GPR13 = thread specific pointer
- // GPR14 and above are callee save. Yay.
- (*arr)[i++] = hregPPC_GPR14(mode64);
- (*arr)[i++] = hregPPC_GPR15(mode64);
- (*arr)[i++] = hregPPC_GPR16(mode64);
- (*arr)[i++] = hregPPC_GPR17(mode64);
- (*arr)[i++] = hregPPC_GPR18(mode64);
- (*arr)[i++] = hregPPC_GPR19(mode64);
- (*arr)[i++] = hregPPC_GPR20(mode64);
- (*arr)[i++] = hregPPC_GPR21(mode64);
- (*arr)[i++] = hregPPC_GPR22(mode64);
- (*arr)[i++] = hregPPC_GPR23(mode64);
- (*arr)[i++] = hregPPC_GPR24(mode64);
- (*arr)[i++] = hregPPC_GPR25(mode64);
- (*arr)[i++] = hregPPC_GPR26(mode64);
- (*arr)[i++] = hregPPC_GPR27(mode64);
- (*arr)[i++] = hregPPC_GPR28(mode64);
- // GPR29 is reserved for the dispatcher
- // GPR30 is reserved as AltiVec spill reg temporary
- // GPR31 is reserved for the GuestStatePtr
-
- /* Don't waste the reg-allocs's time trawling through zillions of
- FP registers - they mostly will never be used. We'll tolerate
- the occasional extra spill instead. */
- /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
- So use them. */
- (*arr)[i++] = hregPPC_FPR14();
- (*arr)[i++] = hregPPC_FPR15();
- (*arr)[i++] = hregPPC_FPR16();
- (*arr)[i++] = hregPPC_FPR17();
- (*arr)[i++] = hregPPC_FPR18();
- (*arr)[i++] = hregPPC_FPR19();
- (*arr)[i++] = hregPPC_FPR20();
- (*arr)[i++] = hregPPC_FPR21();
-
- /* Same deal re Altivec */
- /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
- So use them. */
- /* NB, vr29 is used as a scratch temporary -- do not allocate */
- (*arr)[i++] = hregPPC_VR20();
- (*arr)[i++] = hregPPC_VR21();
- (*arr)[i++] = hregPPC_VR22();
- (*arr)[i++] = hregPPC_VR23();
- (*arr)[i++] = hregPPC_VR24();
- (*arr)[i++] = hregPPC_VR25();
- (*arr)[i++] = hregPPC_VR26();
- (*arr)[i++] = hregPPC_VR27();
-
- vassert(i == *nregs);
-}
-
-
/* --------- Condition codes, Intel encoding. --------- */
const HChar* showPPCCondCode ( PPCCondCode cond )
}
static void ppMovReg ( HReg dst, HReg src ) {
- if (hregNumber(dst) != hregNumber(src)) {
+ if (!sameHReg(dst, src)) {
vex_printf("mr ");
ppHRegPPC(dst);
vex_printf(",");
/* special-case "li" */
if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
rh_srcR->tag == Prh_Imm &&
- hregNumber(r_srcL) == 0) {
+ hregEncoding(r_srcL) == 0) {
vex_printf("li ");
ppHRegPPC(i->Pin.Alu.dst);
vex_printf(",");
addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
- addHRegUse(u, HRmWrite, hregPPC_VR29());
+ addHRegUse(u, HRmWrite, hregPPC_VR29(mode64));
return;
case Pin_AvUn32Fx4:
addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
/* --------- The ppc assembler (bleh.) --------- */
-static UInt iregNo ( HReg r, Bool mode64 )
+inline static UInt iregEnc ( HReg r, Bool mode64 )
{
UInt n;
- vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
+ vassert(hregClass(r) == (mode64 ? HRcInt64 : HRcInt32));
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 32);
return n;
}
-static UInt fregNo ( HReg fr )
+inline static UInt fregEnc ( HReg fr )
{
UInt n;
vassert(hregClass(fr) == HRcFlt64);
vassert(!hregIsVirtual(fr));
- n = hregNumber(fr);
+ n = hregEncoding(fr);
vassert(n <= 32);
return n;
}
-static UInt vregNo ( HReg v )
+inline static UInt vregEnc ( HReg v )
{
UInt n;
vassert(hregClass(v) == HRcVec128);
vassert(!hregIsVirtual(v));
- n = hregNumber(v);
+ n = hregEncoding(v);
vassert(n <= 32);
return n;
}
vassert(am->tag == Pam_IR);
vassert(am->Pam.IR.index < 0x10000);
- rA = iregNo(am->Pam.IR.base, mode64);
+ rA = iregEnc(am->Pam.IR.base, mode64);
idx = am->Pam.IR.index;
if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
UInt rA, rB;
vassert(am->tag == Pam_RR);
- rA = iregNo(am->Pam.RR.base, mode64);
- rB = iregNo(am->Pam.RR.index, mode64);
+ rA = iregEnc(am->Pam.RR.base, mode64);
+ rB = iregEnc(am->Pam.RR.index, mode64);
p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0, endness_host);
return p;
switch (i->tag) {
case Pin_LI:
- p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
+ p = mkLoadImm(p, iregEnc(i->Pin.LI.dst, mode64),
i->Pin.LI.imm64, mode64, endness_host);
goto done;
case Pin_Alu: {
PPCRH* srcR = i->Pin.Alu.srcR;
Bool immR = toBool(srcR->tag == Prh_Imm);
- UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
- UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
+ UInt r_dst = iregEnc(i->Pin.Alu.dst, mode64);
+ UInt r_srcL = iregEnc(i->Pin.Alu.srcL, mode64);
UInt r_srcR = immR ? (-1)/*bogus*/ :
- iregNo(srcR->Prh.Reg.reg, mode64);
+ iregEnc(srcR->Prh.Reg.reg, mode64);
switch (i->Pin.Alu.op) {
case Palu_ADD:
PPCRH* srcR = i->Pin.Shft.srcR;
Bool sz32 = i->Pin.Shft.sz32;
Bool immR = toBool(srcR->tag == Prh_Imm);
- UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
- UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
+ UInt r_dst = iregEnc(i->Pin.Shft.dst, mode64);
+ UInt r_srcL = iregEnc(i->Pin.Shft.srcL, mode64);
UInt r_srcR = immR ? (-1)/*bogus*/ :
- iregNo(srcR->Prh.Reg.reg, mode64);
+ iregEnc(srcR->Prh.Reg.reg, mode64);
if (!mode64)
vassert(sz32);
case Pin_AddSubC: {
Bool isAdd = i->Pin.AddSubC.isAdd;
Bool setC = i->Pin.AddSubC.setC;
- UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
- UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
- UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
+ UInt r_srcL = iregEnc(i->Pin.AddSubC.srcL, mode64);
+ UInt r_srcR = iregEnc(i->Pin.AddSubC.srcR, mode64);
+ UInt r_dst = iregEnc(i->Pin.AddSubC.dst, mode64);
if (isAdd) {
if (setC) /* addc (PPC32 p348) */
Bool syned = i->Pin.Cmp.syned;
Bool sz32 = i->Pin.Cmp.sz32;
UInt fld1 = i->Pin.Cmp.crfD << 2;
- UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
+ UInt r_srcL = iregEnc(i->Pin.Cmp.srcL, mode64);
UInt r_srcR, imm_srcR;
PPCRH* srcR = i->Pin.Cmp.srcR;
}
break;
case Prh_Reg:
- r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
+ r_srcR = iregEnc(srcR->Prh.Reg.reg, mode64);
if (syned) // cmpwi (signed) (PPC32 p367)
p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0, endness_host);
else // cmplwi (unsigned) (PPC32 p379)
}
case Pin_Unary: {
- UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
- UInt r_src = iregNo(i->Pin.Unary.src, mode64);
+ UInt r_dst = iregEnc(i->Pin.Unary.dst, mode64);
+ UInt r_src = iregEnc(i->Pin.Unary.src, mode64);
switch (i->Pin.Unary.op) {
case Pun_NOT: // nor r_dst,r_src,r_src
case Pin_MulL: {
Bool syned = i->Pin.MulL.syned;
Bool sz32 = i->Pin.MulL.sz32;
- UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
- UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
- UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
+ UInt r_dst = iregEnc(i->Pin.MulL.dst, mode64);
+ UInt r_srcL = iregEnc(i->Pin.MulL.srcL, mode64);
+ UInt r_srcR = iregEnc(i->Pin.MulL.srcR, mode64);
if (!mode64)
vassert(sz32);
case Pin_Div: {
Bool syned = i->Pin.Div.syned;
Bool sz32 = i->Pin.Div.sz32;
- UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
- UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
- UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
+ UInt r_dst = iregEnc(i->Pin.Div.dst, mode64);
+ UInt r_srcL = iregEnc(i->Pin.Div.srcL, mode64);
+ UInt r_srcR = iregEnc(i->Pin.Div.srcR, mode64);
if (!mode64)
vassert(sz32);
/* stw/std r-dstGA, amCIA */
p = do_load_or_store_machine_word(
p, False/*!isLoad*/,
- iregNo(i->Pin.XIndir.dstGA, mode64),
+ iregEnc(i->Pin.XIndir.dstGA, mode64),
i->Pin.XIndir.amCIA, mode64, endness_host
);
/* stw/std r-dstGA, amCIA */
p = do_load_or_store_machine_word(
p, False/*!isLoad*/,
- iregNo(i->Pin.XIndir.dstGA, mode64),
+ iregEnc(i->Pin.XIndir.dstGA, mode64),
i->Pin.XIndir.amCIA, mode64, endness_host
);
PPCCondCode cond;
vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
- r_dst = iregNo(i->Pin.CMov.dst, mode64);
+ r_dst = iregEnc(i->Pin.CMov.dst, mode64);
cond = i->Pin.CMov.cond;
/* branch (if cond fails) over move instrs */
p = mkLoadImm(p, r_dst, imm_src, mode64, endness_host); // p += 4|8|20
break;
case Pri_Reg:
- r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
+ r_src = iregEnc(i->Pin.CMov.src->Pri.Reg, mode64);
p = mkMoveReg(p, r_dst, r_src, endness_host); // p += 4
break;
default: goto bad;
case Pin_Load: {
PPCAMode* am_addr = i->Pin.Load.src;
- UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
+ UInt r_dst = iregEnc(i->Pin.Load.dst, mode64);
UInt opc1, opc2, sz = i->Pin.Load.sz;
switch (am_addr->tag) {
case Pam_IR:
case Pin_LoadL: {
if (i->Pin.LoadL.sz == 4) {
- p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
- 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0, endness_host);
+ p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
+ 0, iregEnc(i->Pin.LoadL.src, mode64), 20, 0, endness_host);
goto done;
}
if (i->Pin.LoadL.sz == 8 && mode64) {
- p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
- 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0, endness_host);
+ p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
+ 0, iregEnc(i->Pin.LoadL.src, mode64), 84, 0, endness_host);
goto done;
}
goto bad;
case Pin_Set: {
/* Make the destination register be 1 or 0, depending on whether
the relevant condition holds. */
- UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
+ UInt r_dst = iregEnc(i->Pin.Set.dst, mode64);
PPCCondCode cond = i->Pin.Set.cond;
UInt rot_imm, r_tmp;
case Pin_MfCR:
// mfcr dst
- p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0,
+ p = mkFormX(p, 31, iregEnc(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0,
endness_host);
goto done;
case Pin_Store: {
PPCAMode* am_addr = i->Pin.Store.dst;
- UInt r_src = iregNo(i->Pin.Store.src, mode64);
+ UInt r_src = iregEnc(i->Pin.Store.src, mode64);
UInt opc1, opc2, sz = i->Pin.Store.sz;
switch (i->Pin.Store.dst->tag) {
case Pam_IR:
case Pin_StoreC: {
if (i->Pin.StoreC.sz == 4) {
- p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
- 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1, endness_host);
+ p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
+ 0, iregEnc(i->Pin.StoreC.dst, mode64), 150, 1, endness_host);
goto done;
}
if (i->Pin.StoreC.sz == 8 && mode64) {
- p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
- 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1, endness_host);
+ p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
+ 0, iregEnc(i->Pin.StoreC.dst, mode64), 214, 1, endness_host);
goto done;
}
goto bad;
}
case Pin_FpUnary: {
- UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
- UInt fr_src = fregNo(i->Pin.FpUnary.src);
+ UInt fr_dst = fregEnc(i->Pin.FpUnary.dst);
+ UInt fr_src = fregEnc(i->Pin.FpUnary.src);
switch (i->Pin.FpUnary.op) {
case Pfp_RSQRTE: // frsqrtre, PPC32 p424
p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0, endness_host );
}
case Pin_FpBinary: {
- UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
- UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
- UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
+ UInt fr_dst = fregEnc(i->Pin.FpBinary.dst);
+ UInt fr_srcL = fregEnc(i->Pin.FpBinary.srcL);
+ UInt fr_srcR = fregEnc(i->Pin.FpBinary.srcR);
switch (i->Pin.FpBinary.op) {
case Pfp_ADDD: // fadd, PPC32 p400
p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0, endness_host );
}
case Pin_FpMulAcc: {
- UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
- UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
- UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
- UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
+ UInt fr_dst = fregEnc(i->Pin.FpMulAcc.dst);
+ UInt fr_srcML = fregEnc(i->Pin.FpMulAcc.srcML);
+ UInt fr_srcMR = fregEnc(i->Pin.FpMulAcc.srcMR);
+ UInt fr_srcAcc = fregEnc(i->Pin.FpMulAcc.srcAcc);
switch (i->Pin.FpMulAcc.op) {
case Pfp_MADDD: // fmadd, PPC32 p408
p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0,
case Pin_FpLdSt: {
PPCAMode* am_addr = i->Pin.FpLdSt.addr;
- UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
+ UInt f_reg = fregEnc(i->Pin.FpLdSt.reg);
Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
UChar sz = i->Pin.FpLdSt.sz;
UInt opc;
}
case Pin_FpSTFIW: {
- UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
- UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
+ UInt ir_addr = iregEnc(i->Pin.FpSTFIW.addr, mode64);
+ UInt fr_data = fregEnc(i->Pin.FpSTFIW.data);
// stfiwx (store fp64[lo32] as int32), PPC32 p517
// Use rA==0, so that EA == rB == ir_addr
p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0, endness_host);
}
case Pin_FpRSP: {
- UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
- UInt fr_src = fregNo(i->Pin.FpRSP.src);
+ UInt fr_dst = fregEnc(i->Pin.FpRSP.dst);
+ UInt fr_src = fregEnc(i->Pin.FpRSP.src);
// frsp, PPC32 p423
p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0, endness_host);
goto done;
}
case Pin_FpCftI: {
- UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
- UInt fr_src = fregNo(i->Pin.FpCftI.src);
+ UInt fr_dst = fregEnc(i->Pin.FpCftI.dst);
+ UInt fr_src = fregEnc(i->Pin.FpCftI.src);
if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
if (i->Pin.FpCftI.syned == True) {
// fctiw (conv f64 to i32), PPC32 p404
}
case Pin_FpCMov: {
- UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
- UInt fr_src = fregNo(i->Pin.FpCMov.src);
+ UInt fr_dst = fregEnc(i->Pin.FpCMov.dst);
+ UInt fr_src = fregEnc(i->Pin.FpCMov.src);
PPCCondCode cc = i->Pin.FpCMov.cond;
if (fr_dst == fr_src) goto done;
}
case Pin_FpLdFPSCR: {
- UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
+ UInt fr_src = fregEnc(i->Pin.FpLdFPSCR.src);
p = mkFormXFL(p, 0xFF, fr_src, i->Pin.FpLdFPSCR.dfp_rm, endness_host); // mtfsf, PPC32 p480
goto done;
}
case Pin_FpCmp: {
UChar crfD = 1;
- UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
- UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
- UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
+ UInt r_dst = iregEnc(i->Pin.FpCmp.dst, mode64);
+ UInt fr_srcL = fregEnc(i->Pin.FpCmp.srcL);
+ UInt fr_srcR = fregEnc(i->Pin.FpCmp.srcR);
vassert(crfD < 8);
// fcmpo, PPC32 p402
p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0, endness_host);
}
case Pin_RdWrLR: {
- UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
+ UInt reg = iregEnc(i->Pin.RdWrLR.gpr, mode64);
/* wrLR==True ? mtlr r4 : mflr r4 */
p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339,
endness_host);
Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
- v_reg = vregNo(i->Pin.AvLdSt.reg);
- r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
+ v_reg = vregEnc(i->Pin.AvLdSt.reg);
+ r_base = iregEnc(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
// Only have AltiVec AMode_RR: kludge AMode_IR
if (!idxd) {
p = mkLoadImm(p, r_idx,
i->Pin.AvLdSt.addr->Pam.IR.index, mode64, endness_host);
} else {
- r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
+ r_idx = iregEnc(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
}
if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
}
case Pin_AvUnary: {
- UInt v_dst = vregNo(i->Pin.AvUnary.dst);
- UInt v_src = vregNo(i->Pin.AvUnary.src);
+ UInt v_dst = vregEnc(i->Pin.AvUnary.dst);
+ UInt v_src = vregEnc(i->Pin.AvUnary.src);
UInt opc2;
switch (i->Pin.AvUnary.op) {
case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
}
case Pin_AvBinary: {
- UInt v_dst = vregNo(i->Pin.AvBinary.dst);
- UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBinary.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBinary.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBinary.srcR);
UInt opc2;
if (i->Pin.AvBinary.op == Pav_SHL) {
p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036, endness_host ); // vslo
}
case Pin_AvBin8x16: {
- UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
- UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBin8x16.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBin8x16.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBin8x16.srcR);
UInt opc2;
switch (i->Pin.AvBin8x16.op) {
}
case Pin_AvBin16x8: {
- UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
- UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBin16x8.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBin16x8.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBin16x8.srcR);
UInt opc2;
switch (i->Pin.AvBin16x8.op) {
}
case Pin_AvBin32x4: {
- UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
- UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBin32x4.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBin32x4.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBin32x4.srcR);
UInt opc2;
switch (i->Pin.AvBin32x4.op) {
}
case Pin_AvBin64x2: {
- UInt v_dst = vregNo(i->Pin.AvBin64x2.dst);
- UInt v_srcL = vregNo(i->Pin.AvBin64x2.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBin64x2.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBin64x2.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBin64x2.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBin64x2.srcR);
UInt opc2;
switch (i->Pin.AvBin64x2.op) {
case Pav_ADDU: opc2 = 192; break; // vaddudm vector double add
goto done;
}
case Pin_AvCipherV128Unary: {
- UInt v_dst = vregNo(i->Pin.AvCipherV128Unary.dst);
- UInt v_src = vregNo(i->Pin.AvCipherV128Unary.src);
+ UInt v_dst = vregEnc(i->Pin.AvCipherV128Unary.dst);
+ UInt v_src = vregEnc(i->Pin.AvCipherV128Unary.src);
UInt opc2;
switch (i->Pin.AvCipherV128Unary.op) {
case Pav_CIPHERSUBV128: opc2 = 1480; break; // vsbox
goto done;
}
case Pin_AvCipherV128Binary: {
- UInt v_dst = vregNo(i->Pin.AvCipherV128Binary.dst);
- UInt v_srcL = vregNo(i->Pin.AvCipherV128Binary.srcL);
- UInt v_srcR = vregNo(i->Pin.AvCipherV128Binary.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvCipherV128Binary.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvCipherV128Binary.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvCipherV128Binary.srcR);
UInt opc2;
switch (i->Pin.AvCipherV128Binary.op) {
case Pav_CIPHERV128: opc2 = 1288; break; // vcipher
goto done;
}
case Pin_AvHashV128Binary: {
- UInt v_dst = vregNo(i->Pin.AvHashV128Binary.dst);
- UInt v_src = vregNo(i->Pin.AvHashV128Binary.src);
+ UInt v_dst = vregEnc(i->Pin.AvHashV128Binary.dst);
+ UInt v_src = vregEnc(i->Pin.AvHashV128Binary.src);
PPCRI* s_field = i->Pin.AvHashV128Binary.s_field;
UInt opc2;
switch (i->Pin.AvHashV128Binary.op) {
goto done;
}
case Pin_AvBCDV128Trinary: {
- UInt v_dst = vregNo(i->Pin.AvBCDV128Trinary.dst);
- UInt v_src1 = vregNo(i->Pin.AvBCDV128Trinary.src1);
- UInt v_src2 = vregNo(i->Pin.AvBCDV128Trinary.src2);
+ UInt v_dst = vregEnc(i->Pin.AvBCDV128Trinary.dst);
+ UInt v_src1 = vregEnc(i->Pin.AvBCDV128Trinary.src1);
+ UInt v_src2 = vregEnc(i->Pin.AvBCDV128Trinary.src2);
PPCRI* ps = i->Pin.AvBCDV128Trinary.ps;
UInt opc2;
switch (i->Pin.AvBCDV128Trinary.op) {
goto done;
}
case Pin_AvBin32Fx4: {
- UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
- UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
- UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvBin32Fx4.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvBin32Fx4.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvBin32Fx4.srcR);
switch (i->Pin.AvBin32Fx4.op) {
case Pavfp_ADDF:
}
case Pin_AvUn32Fx4: {
- UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
- UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
+ UInt v_dst = vregEnc(i->Pin.AvUn32Fx4.dst);
+ UInt v_src = vregEnc(i->Pin.AvUn32Fx4.src);
UInt opc2;
switch (i->Pin.AvUn32Fx4.op) {
case Pavfp_RCPF: opc2 = 266; break; // vrefp
}
case Pin_AvPerm: { // vperm
- UInt v_dst = vregNo(i->Pin.AvPerm.dst);
- UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
- UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
- UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
+ UInt v_dst = vregEnc(i->Pin.AvPerm.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvPerm.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvPerm.srcR);
+ UInt v_ctl = vregEnc(i->Pin.AvPerm.ctl);
p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43, endness_host );
goto done;
}
case Pin_AvSel: { // vsel
- UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
- UInt v_dst = vregNo(i->Pin.AvSel.dst);
- UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
- UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
+ UInt v_ctl = vregEnc(i->Pin.AvSel.ctl);
+ UInt v_dst = vregEnc(i->Pin.AvSel.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvSel.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvSel.srcR);
p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42, endness_host );
goto done;
}
case Pin_AvSh: { // vsl or vsr
- UInt v_dst = vregNo(i->Pin.AvSh.dst);
+ UInt v_dst = vregEnc(i->Pin.AvSh.dst);
Bool idxd = toBool(i->Pin.AvSh.addr->tag == Pam_RR);
UInt r_idx, r_base;
- r_base = iregNo(i->Pin.AvSh.addr->Pam.RR.base, mode64);
+ r_base = iregEnc(i->Pin.AvSh.addr->Pam.RR.base, mode64);
if (!idxd) {
r_idx = 30; // XXX: Using r30 as temp
p = mkLoadImm(p, r_idx,
i->Pin.AvSh.addr->Pam.IR.index, mode64, endness_host);
} else {
- r_idx = iregNo(i->Pin.AvSh.addr->Pam.RR.index, mode64);
+ r_idx = iregEnc(i->Pin.AvSh.addr->Pam.RR.index, mode64);
}
if (i->Pin.AvSh.shLeft)
case Pin_AvShlDbl: { // vsldoi
UInt shift = i->Pin.AvShlDbl.shift;
- UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
- UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
- UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
+ UInt v_dst = vregEnc(i->Pin.AvShlDbl.dst);
+ UInt v_srcL = vregEnc(i->Pin.AvShlDbl.srcL);
+ UInt v_srcR = vregEnc(i->Pin.AvShlDbl.srcR);
vassert(shift <= 0xF);
p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44, endness_host );
goto done;
}
case Pin_AvSplat: { // vsplt(is)(b,h,w)
- UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
+ UInt v_dst = vregEnc(i->Pin.AvShlDbl.dst);
UChar sz = i->Pin.AvSplat.sz;
UInt v_src, opc2;
vassert(sz == 8 || sz == 16 || sz == 32);
UInt lowest_lane;
opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
- v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
+ v_src = vregEnc(i->Pin.AvSplat.src->Pvi.Reg);
lowest_lane = (128/sz)-1;
p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2, endness_host );
}
}
case Pin_AvCMov: {
- UInt v_dst = vregNo(i->Pin.AvCMov.dst);
- UInt v_src = vregNo(i->Pin.AvCMov.src);
+ UInt v_dst = vregEnc(i->Pin.AvCMov.dst);
+ UInt v_src = vregEnc(i->Pin.AvCMov.src);
PPCCondCode cc = i->Pin.AvCMov.cond;
if (v_dst == v_src) goto done;
}
case Pin_AvLdVSCR: { // mtvscr
- UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
+ UInt v_src = vregEnc(i->Pin.AvLdVSCR.src);
p = mkFormVX( p, 4, 0, 0, v_src, 1604, endness_host );
goto done;
}
case Pin_Dfp64Unary: {
- UInt fr_dst = fregNo( i->Pin.FpUnary.dst );
- UInt fr_src = fregNo( i->Pin.FpUnary.src );
+ UInt fr_dst = fregEnc( i->Pin.FpUnary.dst );
+ UInt fr_src = fregEnc( i->Pin.FpUnary.src );
switch (i->Pin.Dfp64Unary.op) {
case Pfp_MOV: // fmr, PPC32 p410
}
case Pin_Dfp64Binary: {
- UInt fr_dst = fregNo( i->Pin.Dfp64Binary.dst );
- UInt fr_srcL = fregNo( i->Pin.Dfp64Binary.srcL );
- UInt fr_srcR = fregNo( i->Pin.Dfp64Binary.srcR );
+ UInt fr_dst = fregEnc( i->Pin.Dfp64Binary.dst );
+ UInt fr_srcL = fregEnc( i->Pin.Dfp64Binary.srcL );
+ UInt fr_srcR = fregEnc( i->Pin.Dfp64Binary.srcR );
switch (i->Pin.Dfp64Binary.op) {
case Pfp_DFPADD: /* dadd, dfp add, use default RM from reg ignore mode
* from the Iop instruction. */
}
case Pin_DfpShift: {
- UInt fr_src = fregNo(i->Pin.DfpShift.src);
- UInt fr_dst = fregNo(i->Pin.DfpShift.dst);
+ UInt fr_src = fregEnc(i->Pin.DfpShift.src);
+ UInt fr_dst = fregEnc(i->Pin.DfpShift.dst);
UInt shift;
shift = i->Pin.DfpShift.shift->Pri.Imm;
}
case Pin_ExtractExpD128: {
- UInt fr_dst = fregNo(i->Pin.ExtractExpD128.dst);
- UInt fr_srcHi = fregNo(i->Pin.ExtractExpD128.src_hi);
- UInt fr_srcLo = fregNo(i->Pin.ExtractExpD128.src_lo);
+ UInt fr_dst = fregEnc(i->Pin.ExtractExpD128.dst);
+ UInt fr_srcHi = fregEnc(i->Pin.ExtractExpD128.src_hi);
+ UInt fr_srcLo = fregEnc(i->Pin.ExtractExpD128.src_lo);
switch (i->Pin.ExtractExpD128.op) {
case Pfp_DXEXQ:
goto done;
}
case Pin_Dfp128Unary: {
- UInt fr_dstHi = fregNo(i->Pin.Dfp128Unary.dst_hi);
- UInt fr_dstLo = fregNo(i->Pin.Dfp128Unary.dst_lo);
- UInt fr_srcLo = fregNo(i->Pin.Dfp128Unary.src_lo);
+ UInt fr_dstHi = fregEnc(i->Pin.Dfp128Unary.dst_hi);
+ UInt fr_dstLo = fregEnc(i->Pin.Dfp128Unary.dst_lo);
+ UInt fr_srcLo = fregEnc(i->Pin.Dfp128Unary.src_lo);
/* Do instruction with 128-bit source operands in registers (10,11)
* and (12,13).
/* dst is used to supply the left source operand and return
* the result.
*/
- UInt fr_dstHi = fregNo( i->Pin.Dfp128Binary.dst_hi );
- UInt fr_dstLo = fregNo( i->Pin.Dfp128Binary.dst_lo );
- UInt fr_srcRHi = fregNo( i->Pin.Dfp128Binary.srcR_hi );
- UInt fr_srcRLo = fregNo( i->Pin.Dfp128Binary.srcR_lo );
+ UInt fr_dstHi = fregEnc( i->Pin.Dfp128Binary.dst_hi );
+ UInt fr_dstLo = fregEnc( i->Pin.Dfp128Binary.dst_lo );
+ UInt fr_srcRHi = fregEnc( i->Pin.Dfp128Binary.srcR_hi );
+ UInt fr_srcRLo = fregEnc( i->Pin.Dfp128Binary.srcR_lo );
/* Setup the upper and lower registers of the source operand
* register pair.
}
case Pin_DfpShift128: {
- UInt fr_src_hi = fregNo(i->Pin.DfpShift128.src_hi);
- UInt fr_src_lo = fregNo(i->Pin.DfpShift128.src_lo);
- UInt fr_dst_hi = fregNo(i->Pin.DfpShift128.dst_hi);
- UInt fr_dst_lo = fregNo(i->Pin.DfpShift128.dst_lo);
+ UInt fr_src_hi = fregEnc(i->Pin.DfpShift128.src_hi);
+ UInt fr_src_lo = fregEnc(i->Pin.DfpShift128.src_lo);
+ UInt fr_dst_hi = fregEnc(i->Pin.DfpShift128.dst_hi);
+ UInt fr_dst_lo = fregEnc(i->Pin.DfpShift128.dst_lo);
UInt shift;
shift = i->Pin.DfpShift128.shift->Pri.Imm;
}
case Pin_DfpRound: {
- UInt fr_dst = fregNo(i->Pin.DfpRound.dst);
- UInt fr_src = fregNo(i->Pin.DfpRound.src);
+ UInt fr_dst = fregEnc(i->Pin.DfpRound.dst);
+ UInt fr_src = fregEnc(i->Pin.DfpRound.src);
UInt r_rmc, r, rmc;
r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
}
case Pin_DfpRound128: {
- UInt fr_dstHi = fregNo(i->Pin.DfpRound128.dst_hi);
- UInt fr_dstLo = fregNo(i->Pin.DfpRound128.dst_lo);
- UInt fr_srcHi = fregNo(i->Pin.DfpRound128.src_hi);
- UInt fr_srcLo = fregNo(i->Pin.DfpRound128.src_lo);
+ UInt fr_dstHi = fregEnc(i->Pin.DfpRound128.dst_hi);
+ UInt fr_dstLo = fregEnc(i->Pin.DfpRound128.dst_lo);
+ UInt fr_srcHi = fregEnc(i->Pin.DfpRound128.src_hi);
+ UInt fr_srcLo = fregEnc(i->Pin.DfpRound128.src_lo);
UInt r_rmc, r, rmc;
r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
}
case Pin_DfpQuantize: {
- UInt fr_dst = fregNo(i->Pin.DfpQuantize.dst);
- UInt fr_srcL = fregNo(i->Pin.DfpQuantize.srcL);
- UInt fr_srcR = fregNo(i->Pin.DfpQuantize.srcR);
+ UInt fr_dst = fregEnc(i->Pin.DfpQuantize.dst);
+ UInt fr_srcL = fregEnc(i->Pin.DfpQuantize.srcL);
+ UInt fr_srcR = fregEnc(i->Pin.DfpQuantize.srcR);
UInt rmc;
rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
}
case Pin_DfpQuantize128: {
- UInt fr_dst_hi = fregNo(i->Pin.DfpQuantize128.dst_hi);
- UInt fr_dst_lo = fregNo(i->Pin.DfpQuantize128.dst_lo);
- UInt fr_src_hi = fregNo(i->Pin.DfpQuantize128.src_hi);
- UInt fr_src_lo = fregNo(i->Pin.DfpQuantize128.src_lo);
+ UInt fr_dst_hi = fregEnc(i->Pin.DfpQuantize128.dst_hi);
+ UInt fr_dst_lo = fregEnc(i->Pin.DfpQuantize128.dst_lo);
+ UInt fr_src_hi = fregEnc(i->Pin.DfpQuantize128.src_hi);
+ UInt fr_src_lo = fregEnc(i->Pin.DfpQuantize128.src_lo);
UInt rmc;
rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
}
case Pin_DfpD128toD64: {
- UInt fr_dst = fregNo( i->Pin.DfpD128toD64.dst );
- UInt fr_srcHi = fregNo( i->Pin.DfpD128toD64.src_hi );
- UInt fr_srcLo = fregNo( i->Pin.DfpD128toD64.src_lo );
+ UInt fr_dst = fregEnc( i->Pin.DfpD128toD64.dst );
+ UInt fr_srcHi = fregEnc( i->Pin.DfpD128toD64.src_hi );
+ UInt fr_srcLo = fregEnc( i->Pin.DfpD128toD64.src_lo );
/* Setup the upper and lower registers of the source operand
* register pair.
}
case Pin_DfpI64StoD128: {
- UInt fr_dstHi = fregNo( i->Pin.DfpI64StoD128.dst_hi );
- UInt fr_dstLo = fregNo( i->Pin.DfpI64StoD128.dst_lo );
- UInt fr_src = fregNo( i->Pin.DfpI64StoD128.src );
+ UInt fr_dstHi = fregEnc( i->Pin.DfpI64StoD128.dst_hi );
+ UInt fr_dstLo = fregEnc( i->Pin.DfpI64StoD128.dst_lo );
+ UInt fr_src = fregEnc( i->Pin.DfpI64StoD128.src );
switch (i->Pin.Dfp128Binary.op) {
case Pfp_DCFFIXQ:
}
case Pin_InsertExpD128: {
- UInt fr_dstHi = fregNo(i->Pin.InsertExpD128.dst_hi);
- UInt fr_dstLo = fregNo(i->Pin.InsertExpD128.dst_lo);
- UInt fr_srcL = fregNo(i->Pin.InsertExpD128.srcL);
- UInt fr_srcRHi = fregNo(i->Pin.InsertExpD128.srcR_hi);
- UInt fr_srcRLo = fregNo(i->Pin.InsertExpD128.srcR_lo);
+ UInt fr_dstHi = fregEnc(i->Pin.InsertExpD128.dst_hi);
+ UInt fr_dstLo = fregEnc(i->Pin.InsertExpD128.dst_lo);
+ UInt fr_srcL = fregEnc(i->Pin.InsertExpD128.srcL);
+ UInt fr_srcRHi = fregEnc(i->Pin.InsertExpD128.srcR_hi);
+ UInt fr_srcRLo = fregEnc(i->Pin.InsertExpD128.srcR_lo);
/* The left operand is a single F64 value, the right is an F128
* register pair.
case Pin_Dfp64Cmp:{
UChar crfD = 1;
- UInt r_dst = iregNo(i->Pin.Dfp64Cmp.dst, mode64);
- UInt fr_srcL = fregNo(i->Pin.Dfp64Cmp.srcL);
- UInt fr_srcR = fregNo(i->Pin.Dfp64Cmp.srcR);
+ UInt r_dst = iregEnc(i->Pin.Dfp64Cmp.dst, mode64);
+ UInt fr_srcL = fregEnc(i->Pin.Dfp64Cmp.srcL);
+ UInt fr_srcR = fregEnc(i->Pin.Dfp64Cmp.srcR);
vassert(crfD < 8);
// dcmpo, dcmpu
p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0, endness_host);
case Pin_Dfp128Cmp: {
UChar crfD = 1;
- UInt r_dst = iregNo(i->Pin.Dfp128Cmp.dst, mode64);
- UInt fr_srcL_hi = fregNo(i->Pin.Dfp128Cmp.srcL_hi);
- UInt fr_srcL_lo = fregNo(i->Pin.Dfp128Cmp.srcL_lo);
- UInt fr_srcR_hi = fregNo(i->Pin.Dfp128Cmp.srcR_hi);
- UInt fr_srcR_lo = fregNo(i->Pin.Dfp128Cmp.srcR_lo);
+ UInt r_dst = iregEnc(i->Pin.Dfp128Cmp.dst, mode64);
+ UInt fr_srcL_hi = fregEnc(i->Pin.Dfp128Cmp.srcL_hi);
+ UInt fr_srcL_lo = fregEnc(i->Pin.Dfp128Cmp.srcL_lo);
+ UInt fr_srcR_hi = fregEnc(i->Pin.Dfp128Cmp.srcR_hi);
+ UInt fr_srcR_lo = fregEnc(i->Pin.Dfp128Cmp.srcR_lo);
vassert(crfD < 8);
// dcmpoq, dcmpuq
/* Setup the upper and lower registers of the source operand
#include "libvex.h" // VexArch
#include "host_generic_regs.h" // HReg
-/* Num registers used for function calls */
-#define PPC_N_REGPARMS 8
-
/* --------- Registers. --------- */
-/* The usual HReg abstraction. There are 32 real int regs,
- 32 real float regs, and 32 real vector regs.
-*/
-
-extern void ppHRegPPC ( HReg );
-
-extern HReg hregPPC_GPR0 ( Bool mode64 ); // scratch reg / zero reg
-extern HReg hregPPC_GPR1 ( Bool mode64 ); // Stack Frame Pointer
-extern HReg hregPPC_GPR2 ( Bool mode64 ); // not used: TOC pointer
-extern HReg hregPPC_GPR3 ( Bool mode64 );
-extern HReg hregPPC_GPR4 ( Bool mode64 );
-extern HReg hregPPC_GPR5 ( Bool mode64 );
-extern HReg hregPPC_GPR6 ( Bool mode64 );
-extern HReg hregPPC_GPR7 ( Bool mode64 );
-extern HReg hregPPC_GPR8 ( Bool mode64 );
-extern HReg hregPPC_GPR9 ( Bool mode64 );
-extern HReg hregPPC_GPR10 ( Bool mode64 );
-extern HReg hregPPC_GPR11 ( Bool mode64 );
-extern HReg hregPPC_GPR12 ( Bool mode64 );
-extern HReg hregPPC_GPR13 ( Bool mode64 );
-extern HReg hregPPC_GPR14 ( Bool mode64 );
-extern HReg hregPPC_GPR15 ( Bool mode64 );
-extern HReg hregPPC_GPR16 ( Bool mode64 );
-extern HReg hregPPC_GPR17 ( Bool mode64 );
-extern HReg hregPPC_GPR18 ( Bool mode64 );
-extern HReg hregPPC_GPR19 ( Bool mode64 );
-extern HReg hregPPC_GPR20 ( Bool mode64 );
-extern HReg hregPPC_GPR21 ( Bool mode64 );
-extern HReg hregPPC_GPR22 ( Bool mode64 );
-extern HReg hregPPC_GPR23 ( Bool mode64 );
-extern HReg hregPPC_GPR24 ( Bool mode64 );
-extern HReg hregPPC_GPR25 ( Bool mode64 );
-extern HReg hregPPC_GPR26 ( Bool mode64 );
-extern HReg hregPPC_GPR27 ( Bool mode64 );
-extern HReg hregPPC_GPR28 ( Bool mode64 );
-extern HReg hregPPC_GPR29 ( Bool mode64 ); // reserved for dispatcher
-extern HReg hregPPC_GPR30 ( Bool mode64 ); // used as VMX spill temp
-extern HReg hregPPC_GPR31 ( Bool mode64 ); // GuestStatePtr (callee-saved)
-
-extern HReg hregPPC_FPR0 ( void );
-extern HReg hregPPC_FPR1 ( void );
-extern HReg hregPPC_FPR2 ( void );
-extern HReg hregPPC_FPR3 ( void );
-extern HReg hregPPC_FPR4 ( void );
-extern HReg hregPPC_FPR5 ( void );
-extern HReg hregPPC_FPR6 ( void );
-extern HReg hregPPC_FPR7 ( void );
-extern HReg hregPPC_FPR8 ( void );
-extern HReg hregPPC_FPR9 ( void );
-extern HReg hregPPC_FPR10 ( void );
-extern HReg hregPPC_FPR11 ( void );
-extern HReg hregPPC_FPR12 ( void );
-extern HReg hregPPC_FPR13 ( void );
-extern HReg hregPPC_FPR14 ( void );
-extern HReg hregPPC_FPR15 ( void );
-extern HReg hregPPC_FPR16 ( void );
-extern HReg hregPPC_FPR17 ( void );
-extern HReg hregPPC_FPR18 ( void );
-extern HReg hregPPC_FPR19 ( void );
-extern HReg hregPPC_FPR20 ( void );
-extern HReg hregPPC_FPR21 ( void );
-extern HReg hregPPC_FPR22 ( void );
-extern HReg hregPPC_FPR23 ( void );
-extern HReg hregPPC_FPR24 ( void );
-extern HReg hregPPC_FPR25 ( void );
-extern HReg hregPPC_FPR26 ( void );
-extern HReg hregPPC_FPR27 ( void );
-extern HReg hregPPC_FPR28 ( void );
-extern HReg hregPPC_FPR29 ( void );
-extern HReg hregPPC_FPR30 ( void );
-extern HReg hregPPC_FPR31 ( void );
-
-extern HReg hregPPC_VR0 ( void );
-extern HReg hregPPC_VR1 ( void );
-extern HReg hregPPC_VR2 ( void );
-extern HReg hregPPC_VR3 ( void );
-extern HReg hregPPC_VR4 ( void );
-extern HReg hregPPC_VR5 ( void );
-extern HReg hregPPC_VR6 ( void );
-extern HReg hregPPC_VR7 ( void );
-extern HReg hregPPC_VR8 ( void );
-extern HReg hregPPC_VR9 ( void );
-extern HReg hregPPC_VR10 ( void );
-extern HReg hregPPC_VR11 ( void );
-extern HReg hregPPC_VR12 ( void );
-extern HReg hregPPC_VR13 ( void );
-extern HReg hregPPC_VR14 ( void );
-extern HReg hregPPC_VR15 ( void );
-extern HReg hregPPC_VR16 ( void );
-extern HReg hregPPC_VR17 ( void );
-extern HReg hregPPC_VR18 ( void );
-extern HReg hregPPC_VR19 ( void );
-extern HReg hregPPC_VR20 ( void );
-extern HReg hregPPC_VR21 ( void );
-extern HReg hregPPC_VR22 ( void );
-extern HReg hregPPC_VR23 ( void );
-extern HReg hregPPC_VR24 ( void );
-extern HReg hregPPC_VR25 ( void );
-extern HReg hregPPC_VR26 ( void );
-extern HReg hregPPC_VR27 ( void );
-extern HReg hregPPC_VR28 ( void );
-extern HReg hregPPC_VR29 ( void );
-extern HReg hregPPC_VR30 ( void );
-extern HReg hregPPC_VR31 ( void );
+#define ST_IN static inline
+
+#define GPR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, (_mode64) ? HRcInt64 : HRcInt32, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+#define FPR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, HRcFlt64, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+#define VR(_mode64, _enc, _ix64, _ix32) \
+ mkHReg(False, HRcVec128, \
+ (_enc), (_mode64) ? (_ix64) : (_ix32))
+
+ST_IN HReg hregPPC_GPR3 ( Bool mode64 ) { return GPR(mode64, 3, 0, 0); }
+ST_IN HReg hregPPC_GPR4 ( Bool mode64 ) { return GPR(mode64, 4, 1, 1); }
+ST_IN HReg hregPPC_GPR5 ( Bool mode64 ) { return GPR(mode64, 5, 2, 2); }
+ST_IN HReg hregPPC_GPR6 ( Bool mode64 ) { return GPR(mode64, 6, 3, 3); }
+ST_IN HReg hregPPC_GPR7 ( Bool mode64 ) { return GPR(mode64, 7, 4, 4); }
+ST_IN HReg hregPPC_GPR8 ( Bool mode64 ) { return GPR(mode64, 8, 5, 5); }
+ST_IN HReg hregPPC_GPR9 ( Bool mode64 ) { return GPR(mode64, 9, 6, 6); }
+ST_IN HReg hregPPC_GPR10 ( Bool mode64 ) { return GPR(mode64, 10, 7, 7); }
+
+// r11 and r12 are only allocatable in 32-bit mode. Hence the 64-bit
+// index numbering doesn't advance for these two.
+ST_IN HReg hregPPC_GPR11 ( Bool mode64 ) { return GPR(mode64, 11, 0, 8); }
+ST_IN HReg hregPPC_GPR12 ( Bool mode64 ) { return GPR(mode64, 12, 0, 9); }
+
+ST_IN HReg hregPPC_GPR14 ( Bool mode64 ) { return GPR(mode64, 14, 8, 10); }
+ST_IN HReg hregPPC_GPR15 ( Bool mode64 ) { return GPR(mode64, 15, 9, 11); }
+ST_IN HReg hregPPC_GPR16 ( Bool mode64 ) { return GPR(mode64, 16, 10, 12); }
+ST_IN HReg hregPPC_GPR17 ( Bool mode64 ) { return GPR(mode64, 17, 11, 13); }
+ST_IN HReg hregPPC_GPR18 ( Bool mode64 ) { return GPR(mode64, 18, 12, 14); }
+ST_IN HReg hregPPC_GPR19 ( Bool mode64 ) { return GPR(mode64, 19, 13, 15); }
+ST_IN HReg hregPPC_GPR20 ( Bool mode64 ) { return GPR(mode64, 20, 14, 16); }
+ST_IN HReg hregPPC_GPR21 ( Bool mode64 ) { return GPR(mode64, 21, 15, 17); }
+ST_IN HReg hregPPC_GPR22 ( Bool mode64 ) { return GPR(mode64, 22, 16, 18); }
+ST_IN HReg hregPPC_GPR23 ( Bool mode64 ) { return GPR(mode64, 23, 17, 19); }
+ST_IN HReg hregPPC_GPR24 ( Bool mode64 ) { return GPR(mode64, 24, 18, 20); }
+ST_IN HReg hregPPC_GPR25 ( Bool mode64 ) { return GPR(mode64, 25, 19, 21); }
+ST_IN HReg hregPPC_GPR26 ( Bool mode64 ) { return GPR(mode64, 26, 20, 22); }
+ST_IN HReg hregPPC_GPR27 ( Bool mode64 ) { return GPR(mode64, 27, 21, 23); }
+ST_IN HReg hregPPC_GPR28 ( Bool mode64 ) { return GPR(mode64, 28, 22, 24); }
+
+ST_IN HReg hregPPC_FPR14 ( Bool mode64 ) { return FPR(mode64, 14, 23, 25); }
+ST_IN HReg hregPPC_FPR15 ( Bool mode64 ) { return FPR(mode64, 15, 24, 26); }
+ST_IN HReg hregPPC_FPR16 ( Bool mode64 ) { return FPR(mode64, 16, 25, 27); }
+ST_IN HReg hregPPC_FPR17 ( Bool mode64 ) { return FPR(mode64, 17, 26, 28); }
+ST_IN HReg hregPPC_FPR18 ( Bool mode64 ) { return FPR(mode64, 18, 27, 29); }
+ST_IN HReg hregPPC_FPR19 ( Bool mode64 ) { return FPR(mode64, 19, 28, 30); }
+ST_IN HReg hregPPC_FPR20 ( Bool mode64 ) { return FPR(mode64, 20, 29, 31); }
+ST_IN HReg hregPPC_FPR21 ( Bool mode64 ) { return FPR(mode64, 21, 30, 32); }
+
+ST_IN HReg hregPPC_VR20 ( Bool mode64 ) { return VR (mode64, 20, 31, 33); }
+ST_IN HReg hregPPC_VR21 ( Bool mode64 ) { return VR (mode64, 21, 32, 34); }
+ST_IN HReg hregPPC_VR22 ( Bool mode64 ) { return VR (mode64, 22, 33, 35); }
+ST_IN HReg hregPPC_VR23 ( Bool mode64 ) { return VR (mode64, 23, 34, 36); }
+ST_IN HReg hregPPC_VR24 ( Bool mode64 ) { return VR (mode64, 24, 35, 37); }
+ST_IN HReg hregPPC_VR25 ( Bool mode64 ) { return VR (mode64, 25, 36, 38); }
+ST_IN HReg hregPPC_VR26 ( Bool mode64 ) { return VR (mode64, 26, 37, 39); }
+ST_IN HReg hregPPC_VR27 ( Bool mode64 ) { return VR (mode64, 27, 38, 40); }
+
+ST_IN HReg hregPPC_GPR1 ( Bool mode64 ) { return GPR(mode64, 1, 39, 41); }
+ST_IN HReg hregPPC_GPR29 ( Bool mode64 ) { return GPR(mode64, 29, 40, 42); }
+ST_IN HReg hregPPC_GPR30 ( Bool mode64 ) { return GPR(mode64, 30, 41, 43); }
+ST_IN HReg hregPPC_GPR31 ( Bool mode64 ) { return GPR(mode64, 31, 42, 44); }
+ST_IN HReg hregPPC_VR29 ( Bool mode64 ) { return VR (mode64, 29, 43, 45); }
+
+#undef ST_IN
+#undef GPR
+#undef FPR
+#undef VR
#define StackFramePtr(_mode64) hregPPC_GPR1(_mode64)
#define GuestStatePtr(_mode64) hregPPC_GPR31(_mode64)
+/* Num registers used for function calls */
+#define PPC_N_REGPARMS 8
+
+extern void ppHRegPPC ( HReg );
/* --------- Condition codes --------- */
extern void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offsetB, Bool mode64 );
-extern void getAllocableRegs_PPC ( Int*, HReg**, Bool mode64 );
+extern const RRegUniverse* getRRegUniverse_PPC ( Bool mode64 );
+
extern HInstrArray* iselSB_PPC ( const IRSB*,
VexArch,
const VexArchInfo*,
#include "host_ppc_defs.h"
/* GPR register class for ppc32/64 */
-#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
+#define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
/*---------------------------------------------------------*/
}
static HReg newVRegI ( ISelEnv* env )
-{
- HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
- True/*virtual reg*/);
+{
+ HReg reg
+ = mkHReg(True/*vreg*/, HRcGPR(env->mode64), 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegF ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*vreg*/, HRcFlt64, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegV ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*vreg*/, HRcVec128, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
case Ity_I8:
case Ity_I16:
case Ity_I32:
- if (mode64) { hregLo = mkHReg(j++, HRcInt64, True); break;
- } else { hregLo = mkHReg(j++, HRcInt32, True); break;
+ if (mode64) {
+ hregLo = mkHReg(True, HRcInt64, 0, j++);
+ } else {
+ hregLo = mkHReg(True, HRcInt32, 0, j++);
}
+ break;
case Ity_I64:
- if (mode64) { hregLo = mkHReg(j++, HRcInt64, True); break;
- } else { hregLo = mkHReg(j++, HRcInt32, True);
- hregMedLo = mkHReg(j++, HRcInt32, True); break;
+ if (mode64) {
+ hregLo = mkHReg(True, HRcInt64, 0, j++);
+ } else {
+ hregLo = mkHReg(True, HRcInt32, 0, j++);
+ hregMedLo = mkHReg(True, HRcInt32, 0, j++);
}
+ break;
case Ity_I128:
- if (mode64) { hregLo = mkHReg(j++, HRcInt64, True);
- hregMedLo = mkHReg(j++, HRcInt64, True); break;
- } else { hregLo = mkHReg(j++, HRcInt32, True);
- hregMedLo = mkHReg(j++, HRcInt32, True);
- hregMedHi = mkHReg(j++, HRcInt32, True);
- hregHi = mkHReg(j++, HRcInt32, True); break;
+ if (mode64) {
+ hregLo = mkHReg(True, HRcInt64, 0, j++);
+ hregMedLo = mkHReg(True, HRcInt64, 0, j++);
+ } else {
+ hregLo = mkHReg(True, HRcInt32, 0, j++);
+ hregMedLo = mkHReg(True, HRcInt32, 0, j++);
+ hregMedHi = mkHReg(True, HRcInt32, 0, j++);
+ hregHi = mkHReg(True, HRcInt32, 0, j++);
}
+ break;
case Ity_F32:
- case Ity_F64: hregLo = mkHReg(j++, HRcFlt64, True); break;
- case Ity_V128: hregLo = mkHReg(j++, HRcVec128, True); break;
+ case Ity_F64:
+ hregLo = mkHReg(True, HRcFlt64, 0, j++);
+ break;
+ case Ity_V128:
+ hregLo = mkHReg(True, HRcVec128, 0, j++);
+ break;
case Ity_D32:
- case Ity_D64: hregLo = mkHReg(j++, HRcFlt64, True); break;
- case Ity_D128: hregLo = mkHReg(j++, HRcFlt64, True);
- hregMedLo = mkHReg(j++, HRcFlt64, True); break;
+ case Ity_D64:
+ hregLo = mkHReg(True, HRcFlt64, 0, j++);
+ break;
+ case Ity_D128:
+ hregLo = mkHReg(True, HRcFlt64, 0, j++);
+ hregMedLo = mkHReg(True, HRcFlt64, 0, j++);
+ break;
default:
ppIRType(bb->tyenv->types[i]);
vpanic("iselBB(ppc): IRTemp type");
/*--- Registers ---*/
/*------------------------------------------------------------*/
+/* A mapping from register number to register index */
+static Int gpr_index[16]; // GPR regno -> register index
+static Int fpr_index[16]; // FPR regno -> register index
+
+HReg
+s390_hreg_gpr(UInt regno)
+{
+ Int ix = gpr_index[regno];
+ vassert(ix >= 0);
+ return mkHReg(/*virtual*/False, HRcInt64, regno, ix);
+}
+
+HReg
+s390_hreg_fpr(UInt regno)
+{
+ Int ix = fpr_index[regno];
+ vassert(ix >= 0);
+ return mkHReg(/*virtual*/False, HRcFlt64, regno, ix);
+}
+
+static __inline__ UInt
+hregNumber(HReg reg)
+{
+ return hregEncoding(reg);
+}
+
/* Decompile the given register into a static buffer and return it */
const HChar *
s390_hreg_as_string(HReg reg)
}
-/* Tell the register allocator which registers can be allocated. */
-static void
-s390_hreg_get_allocable(Int *nregs, HReg **arr)
-{
- UInt i;
-
- /* Total number of allocable registers (all classes) */
- *nregs = 16 /* GPRs */
- - 1 /* r0 */
- - 1 /* r12 scratch register for translation chaining support */
- - 1 /* r13 guest state pointer */
- - 1 /* r14 link register */
- - 1 /* r15 stack pointer */
- + 16 /* FPRs */
- ;
-
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
-
- i = 0;
-
- /* GPR0 is not available because it is interpreted as 0, when used
- as a base or index register. */
- (*arr)[i++] = mkHReg(1, HRcInt64, False);
- (*arr)[i++] = mkHReg(2, HRcInt64, False);
- (*arr)[i++] = mkHReg(3, HRcInt64, False);
- (*arr)[i++] = mkHReg(4, HRcInt64, False);
- (*arr)[i++] = mkHReg(5, HRcInt64, False);
- (*arr)[i++] = mkHReg(6, HRcInt64, False);
- (*arr)[i++] = mkHReg(7, HRcInt64, False);
- (*arr)[i++] = mkHReg(8, HRcInt64, False);
- (*arr)[i++] = mkHReg(9, HRcInt64, False);
- /* GPR10 and GPR11 are used for instructions that use register pairs.
- Otherwise, they are available to the allocator */
- (*arr)[i++] = mkHReg(10, HRcInt64, False);
- (*arr)[i++] = mkHReg(11, HRcInt64, False);
- /* GPR12 is not available because it us used as a scratch register
- in translation chaining. */
- /* GPR13 is not available because it is used as guest state pointer */
- /* GPR14 is not available because it is used as link register */
- /* GPR15 is not available because it is used as stack pointer */
-
- /* Add the available real (non-virtual) FPRs */
- (*arr)[i++] = mkHReg(0, HRcFlt64, False);
- (*arr)[i++] = mkHReg(1, HRcFlt64, False);
- (*arr)[i++] = mkHReg(2, HRcFlt64, False);
- (*arr)[i++] = mkHReg(3, HRcFlt64, False);
- (*arr)[i++] = mkHReg(4, HRcFlt64, False);
- (*arr)[i++] = mkHReg(5, HRcFlt64, False);
- (*arr)[i++] = mkHReg(6, HRcFlt64, False);
- (*arr)[i++] = mkHReg(7, HRcFlt64, False);
- (*arr)[i++] = mkHReg(8, HRcFlt64, False);
- (*arr)[i++] = mkHReg(9, HRcFlt64, False);
- (*arr)[i++] = mkHReg(10, HRcFlt64, False);
- (*arr)[i++] = mkHReg(11, HRcFlt64, False);
- (*arr)[i++] = mkHReg(12, HRcFlt64, False);
- (*arr)[i++] = mkHReg(13, HRcFlt64, False);
- (*arr)[i++] = mkHReg(14, HRcFlt64, False);
- (*arr)[i++] = mkHReg(15, HRcFlt64, False);
- /* FPR12 - FPR15 are also used as register pairs for 128-bit
- floating point operations */
-}
-
-
/* Return the real register that holds the guest state pointer */
HReg
s390_hreg_guest_state_pointer(void)
{
- return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False);
+ return s390_hreg_gpr(S390_REGNO_GUEST_STATE_POINTER);
}
am->tag = S390_AMODE_B12;
am->d = d;
am->b = b;
- am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
+ am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
return am;
}
am->tag = S390_AMODE_B20;
am->d = d;
am->b = b;
- am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */
+ am->x = s390_hreg_gpr(0); /* hregNumber(am->x) == 0 */
return am;
}
/*--- Helpers for register allocation ---*/
/*------------------------------------------------------------*/
-/* Called once per translation. */
-void
-getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64)
+/* Initialise and return the "register universe", i.e. a list of
+ all hardware registers. Called once. */
+const RRegUniverse *
+getRRegUniverse_S390(void)
{
- s390_hreg_get_allocable(nregs, arr);
-}
+ static RRegUniverse all_regs;
+ static Bool initialised = False;
+ RRegUniverse *ru = &all_regs;
+
+ if (LIKELY(initialised))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Assign invalid values to the gpr/fpr_index */
+ for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
+ gpr_index[i] = -1;
+ for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
+ fpr_index[i] = -1;
+
+ /* Add the registers that are available to the register allocator.
+ GPRs: registers 1..11 are available
+ FPRs: registers 0..15 are available
+ FPR12 - FPR15 are also used as register pairs for 128-bit
+ floating point operations
+ */
+ UInt regno;
+ for (regno = 1; regno <= 11; ++regno) {
+ gpr_index[regno] = ru->size;
+ ru->regs[ru->size++] = s390_hreg_gpr(regno);
+ }
+ for (regno = 0; regno <= 15; ++regno) {
+ fpr_index[regno] = ru->size;
+ ru->regs[ru->size++] = s390_hreg_fpr(regno);
+ }
+ ru->allocable = ru->size;
+
+ /* Add the registers that are not available for allocation.
+ r0 -- cannot be used as a base or index register
+ r12 -- scratch register for translation chaining support
+ r13 -- guest state pointer
+ r14 -- link register
+ r15 -- stack pointer
+ */
+ UInt other[] = { 0, 12, 13, 14, 15 };
+ for (UInt i = 0; i < sizeof other / sizeof other[0]; ++i) {
+ gpr_index[other[i]] = ru->size;
+ ru->regs[ru->size++] = s390_hreg_gpr(other[i]);
+ }
+ /* Sanity checking */
+ for (UInt i = 0; i < sizeof gpr_index / sizeof gpr_index[0]; ++i)
+ vassert(gpr_index[i] >= 0);
+ for (UInt i = 0; i < sizeof fpr_index / sizeof fpr_index[0]; ++i)
+ vassert(fpr_index[i] >= 0);
+
+ initialised = True;
+ return ru;
+}
/* Tell the register allocator how the given instruction uses the registers
it refers to. */
volatile registers are: r0 - r5. Valgrind's register allocator
does not know about r0, so we can leave that out */
for (i = 1; i <= 5; ++i) {
- addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False));
+ addHRegUse(u, HRmWrite, s390_hreg_gpr(i));
}
/* Ditto for floating point registers. f0 - f7 are volatile */
for (i = 0; i <= 7; ++i) {
- addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False));
+ addHRegUse(u, HRmWrite, s390_hreg_fpr(i));
}
/* The registers that are used for passing arguments will be read.
Not all of them may, but in general we need to assume that. */
for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) {
- addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i),
- HRcInt64, False));
+ addHRegUse(u, HRmRead, s390_hreg_gpr(s390_gprno_from_arg_index(i)));
}
/* s390_insn_helper_call_emit also reads / writes the link register
/* --------- Registers --------- */
const HChar *s390_hreg_as_string(HReg);
+HReg s390_hreg_gpr(UInt regno);
+HReg s390_hreg_fpr(UInt regno);
/* Dedicated registers */
HReg s390_hreg_guest_state_pointer(void);
Int emit_S390Instr ( Bool *, UChar *, Int, const s390_insn *, Bool,
VexEndness, const void *, const void *,
const void *, const void *);
-void getAllocableRegs_S390( Int *, HReg **, Bool );
+const RRegUniverse *getRRegUniverse_S390( void );
void genSpill_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
void genReload_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
HInstrArray *iselSB_S390 ( const IRSB *, VexArch, const VexArchInfo *,
}
-/* Allocate a new integer register */
-static HReg
-newVRegI(ISelEnv *env)
+/* Allocate a new virtual integer register */
+static __inline__ HReg
+mkVRegI(UInt ix)
{
- HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True /* virtual */ );
- env->vreg_ctr++;
+ return mkHReg(/*virtual*/True, HRcInt64, /*encoding*/0, ix);
+}
- return reg;
+static __inline__ HReg
+newVRegI(ISelEnv *env)
+{
+ return mkVRegI(env->vreg_ctr++);
}
-/* Allocate a new floating point register */
-static HReg
-newVRegF(ISelEnv *env)
+/* Allocate a new virtual floating point register */
+static __inline__ HReg
+mkVRegF(UInt ix)
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /* virtual */ );
-
- env->vreg_ctr++;
+ return mkHReg(/*virtual*/True, HRcFlt64, /*encoding*/0, ix);
+}
- return reg;
+static __inline__ HReg
+newVRegF(ISelEnv *env)
+{
+ return mkVRegF(env->vreg_ctr++);
}
static __inline__ HReg
make_gpr(UInt regno)
{
- return mkHReg(regno, HRcInt64, False /* virtual */ );
+ return s390_hreg_gpr(regno);
}
static __inline__ HReg
make_fpr(UInt regno)
{
- return mkHReg(regno, HRcFlt64, False /* virtual */ );
+ return s390_hreg_fpr(regno);
}
case Ity_I8:
case Ity_I16:
case Ity_I32:
- hreg = mkHReg(j++, HRcInt64, True);
- break;
-
case Ity_I64:
- hreg = mkHReg(j++, HRcInt64, True);
+ hreg = mkVRegI(j++);
break;
case Ity_I128:
- hreg = mkHReg(j++, HRcInt64, True);
- hregHI = mkHReg(j++, HRcInt64, True);
+ hreg = mkVRegI(j++);
+ hregHI = mkVRegI(j++);
break;
case Ity_F32:
case Ity_F64:
case Ity_D32:
case Ity_D64:
- hreg = mkHReg(j++, HRcFlt64, True);
+ hreg = mkVRegF(j++);
break;
case Ity_F128:
case Ity_D128:
- hreg = mkHReg(j++, HRcFlt64, True);
- hregHI = mkHReg(j++, HRcFlt64, True);
+ hreg = mkVRegF(j++);
+ hregHI = mkVRegF(j++);
break;
case Ity_V128: /* fall through */
/* --------- Registers. --------- */
+const RRegUniverse* getRRegUniverse_X86 ( void )
+{
+ /* The real-register universe is a big constant, so we just want to
+ initialise it once. */
+ static RRegUniverse rRegUniverse_X86;
+ static Bool rRegUniverse_X86_initted = False;
+
+ /* Handy shorthand, nothing more */
+ RRegUniverse* ru = &rRegUniverse_X86;
+
+ /* This isn't thread-safe. Sigh. */
+ if (LIKELY(rRegUniverse_X86_initted))
+ return ru;
+
+ RRegUniverse__init(ru);
+
+ /* Add the registers. The initial segment of this array must be
+ those available for allocation by reg-alloc, and those that
+ follow are not available for allocation. */
+ ru->regs[ru->size++] = hregX86_EAX();
+ ru->regs[ru->size++] = hregX86_EBX();
+ ru->regs[ru->size++] = hregX86_ECX();
+ ru->regs[ru->size++] = hregX86_EDX();
+ ru->regs[ru->size++] = hregX86_ESI();
+ ru->regs[ru->size++] = hregX86_EDI();
+ ru->regs[ru->size++] = hregX86_FAKE0();
+ ru->regs[ru->size++] = hregX86_FAKE1();
+ ru->regs[ru->size++] = hregX86_FAKE2();
+ ru->regs[ru->size++] = hregX86_FAKE3();
+ ru->regs[ru->size++] = hregX86_FAKE4();
+ ru->regs[ru->size++] = hregX86_FAKE5();
+ ru->regs[ru->size++] = hregX86_XMM0();
+ ru->regs[ru->size++] = hregX86_XMM1();
+ ru->regs[ru->size++] = hregX86_XMM2();
+ ru->regs[ru->size++] = hregX86_XMM3();
+ ru->regs[ru->size++] = hregX86_XMM4();
+ ru->regs[ru->size++] = hregX86_XMM5();
+ ru->regs[ru->size++] = hregX86_XMM6();
+ ru->regs[ru->size++] = hregX86_XMM7();
+ ru->allocable = ru->size;
+ /* And other regs, not available to the allocator. */
+ ru->regs[ru->size++] = hregX86_ESP();
+ ru->regs[ru->size++] = hregX86_EBP();
+
+ rRegUniverse_X86_initted = True;
+
+ RRegUniverse__check_is_sane(ru);
+ return ru;
+}
+
+
void ppHRegX86 ( HReg reg )
{
Int r;
/* But specific for real regs. */
switch (hregClass(reg)) {
case HRcInt32:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 8);
vex_printf("%s", ireg32_names[r]);
return;
case HRcFlt64:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 6);
vex_printf("%%fake%d", r);
return;
case HRcVec128:
- r = hregNumber(reg);
+ r = hregEncoding(reg);
vassert(r >= 0 && r < 8);
vex_printf("%%xmm%d", r);
return;
}
}
-HReg hregX86_EAX ( void ) { return mkHReg(0, HRcInt32, False); }
-HReg hregX86_ECX ( void ) { return mkHReg(1, HRcInt32, False); }
-HReg hregX86_EDX ( void ) { return mkHReg(2, HRcInt32, False); }
-HReg hregX86_EBX ( void ) { return mkHReg(3, HRcInt32, False); }
-HReg hregX86_ESP ( void ) { return mkHReg(4, HRcInt32, False); }
-HReg hregX86_EBP ( void ) { return mkHReg(5, HRcInt32, False); }
-HReg hregX86_ESI ( void ) { return mkHReg(6, HRcInt32, False); }
-HReg hregX86_EDI ( void ) { return mkHReg(7, HRcInt32, False); }
-
-HReg hregX86_FAKE0 ( void ) { return mkHReg(0, HRcFlt64, False); }
-HReg hregX86_FAKE1 ( void ) { return mkHReg(1, HRcFlt64, False); }
-HReg hregX86_FAKE2 ( void ) { return mkHReg(2, HRcFlt64, False); }
-HReg hregX86_FAKE3 ( void ) { return mkHReg(3, HRcFlt64, False); }
-HReg hregX86_FAKE4 ( void ) { return mkHReg(4, HRcFlt64, False); }
-HReg hregX86_FAKE5 ( void ) { return mkHReg(5, HRcFlt64, False); }
-
-HReg hregX86_XMM0 ( void ) { return mkHReg(0, HRcVec128, False); }
-HReg hregX86_XMM1 ( void ) { return mkHReg(1, HRcVec128, False); }
-HReg hregX86_XMM2 ( void ) { return mkHReg(2, HRcVec128, False); }
-HReg hregX86_XMM3 ( void ) { return mkHReg(3, HRcVec128, False); }
-HReg hregX86_XMM4 ( void ) { return mkHReg(4, HRcVec128, False); }
-HReg hregX86_XMM5 ( void ) { return mkHReg(5, HRcVec128, False); }
-HReg hregX86_XMM6 ( void ) { return mkHReg(6, HRcVec128, False); }
-HReg hregX86_XMM7 ( void ) { return mkHReg(7, HRcVec128, False); }
-
-
-void getAllocableRegs_X86 ( Int* nregs, HReg** arr )
-{
- *nregs = 20;
- *arr = LibVEX_Alloc_inline(*nregs * sizeof(HReg));
- (*arr)[0] = hregX86_EAX();
- (*arr)[1] = hregX86_EBX();
- (*arr)[2] = hregX86_ECX();
- (*arr)[3] = hregX86_EDX();
- (*arr)[4] = hregX86_ESI();
- (*arr)[5] = hregX86_EDI();
- (*arr)[6] = hregX86_FAKE0();
- (*arr)[7] = hregX86_FAKE1();
- (*arr)[8] = hregX86_FAKE2();
- (*arr)[9] = hregX86_FAKE3();
- (*arr)[10] = hregX86_FAKE4();
- (*arr)[11] = hregX86_FAKE5();
- (*arr)[12] = hregX86_XMM0();
- (*arr)[13] = hregX86_XMM1();
- (*arr)[14] = hregX86_XMM2();
- (*arr)[15] = hregX86_XMM3();
- (*arr)[16] = hregX86_XMM4();
- (*arr)[17] = hregX86_XMM5();
- (*arr)[18] = hregX86_XMM6();
- (*arr)[19] = hregX86_XMM7();
-}
-
/* --------- Condition codes, Intel encoding. --------- */
/* --------- The x86 assembler (bleh.) --------- */
-static UChar iregNo ( HReg r )
+inline static UInt iregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcInt32);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 7);
- return toUChar(n);
+ return n;
}
-static UInt fregNo ( HReg r )
+inline static UInt fregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcFlt64);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 5);
return n;
}
-static UInt vregNo ( HReg r )
+inline static UInt vregEnc ( HReg r )
{
UInt n;
vassert(hregClass(r) == HRcVec128);
vassert(!hregIsVirtual(r));
- n = hregNumber(r);
+ n = hregEncoding(r);
vassert(n <= 7);
return n;
}
-static UChar mkModRegRM ( UInt mod, UInt reg, UInt regmem )
+inline static UChar mkModRegRM ( UInt mod, UInt reg, UInt regmem )
{
vassert(mod < 4);
vassert((reg|regmem) < 8);
- return toUChar( ((mod & 3) << 6)
- | ((reg & 7) << 3)
- | (regmem & 7) );
+ return (UChar)( ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7) );
}
-static UChar mkSIB ( UInt shift, UInt regindex, UInt regbase )
+inline static UChar mkSIB ( UInt shift, UInt regindex, UInt regbase )
{
vassert(shift < 4);
vassert((regindex|regbase) < 8);
- return toUChar( ((shift & 3) << 6)
- | ((regindex & 7) << 3)
- | (regbase & 7) );
+ return (UChar)( ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7) );
}
static UChar* emit32 ( UChar* p, UInt w32 )
| index != ESP
= 10 greg 100, scale index base, d32
*/
-static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
+static UChar* doAMode_M__wrk ( UChar* p, UInt gregEnc, X86AMode* am )
{
if (am->tag == Xam_IR) {
if (am->Xam.IR.imm == 0
&& ! sameHReg(am->Xam.IR.reg, hregX86_ESP())
&& ! sameHReg(am->Xam.IR.reg, hregX86_EBP()) ) {
- *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
+ *p++ = mkModRegRM(0, gregEnc, iregEnc(am->Xam.IR.reg));
return p;
}
if (fits8bits(am->Xam.IR.imm)
&& ! sameHReg(am->Xam.IR.reg, hregX86_ESP())) {
- *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
+ *p++ = mkModRegRM(1, gregEnc, iregEnc(am->Xam.IR.reg));
*p++ = toUChar(am->Xam.IR.imm & 0xFF);
return p;
}
if (! sameHReg(am->Xam.IR.reg, hregX86_ESP())) {
- *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
+ *p++ = mkModRegRM(2, gregEnc, iregEnc(am->Xam.IR.reg));
p = emit32(p, am->Xam.IR.imm);
return p;
}
if (sameHReg(am->Xam.IR.reg, hregX86_ESP())
&& fits8bits(am->Xam.IR.imm)) {
- *p++ = mkModRegRM(1, iregNo(greg), 4);
+ *p++ = mkModRegRM(1, gregEnc, 4);
*p++ = 0x24;
*p++ = toUChar(am->Xam.IR.imm & 0xFF);
return p;
if (am->tag == Xam_IRRS) {
if (fits8bits(am->Xam.IRRS.imm)
&& ! sameHReg(am->Xam.IRRS.index, hregX86_ESP())) {
- *p++ = mkModRegRM(1, iregNo(greg), 4);
- *p++ = mkSIB(am->Xam.IRRS.shift, iregNo(am->Xam.IRRS.index),
- iregNo(am->Xam.IRRS.base));
+ *p++ = mkModRegRM(1, gregEnc, 4);
+ *p++ = mkSIB(am->Xam.IRRS.shift, iregEnc(am->Xam.IRRS.index),
+ iregEnc(am->Xam.IRRS.base));
*p++ = toUChar(am->Xam.IRRS.imm & 0xFF);
return p;
}
if (! sameHReg(am->Xam.IRRS.index, hregX86_ESP())) {
- *p++ = mkModRegRM(2, iregNo(greg), 4);
- *p++ = mkSIB(am->Xam.IRRS.shift, iregNo(am->Xam.IRRS.index),
- iregNo(am->Xam.IRRS.base));
+ *p++ = mkModRegRM(2, gregEnc, 4);
+ *p++ = mkSIB(am->Xam.IRRS.shift, iregEnc(am->Xam.IRRS.index),
+ iregEnc(am->Xam.IRRS.base));
p = emit32(p, am->Xam.IRRS.imm);
return p;
}
/*NOTREACHED*/
}
+static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
+{
+ return doAMode_M__wrk(p, iregEnc(greg), am);
+}
+
+static UChar* doAMode_M_enc ( UChar* p, UInt gregEnc, X86AMode* am )
+{
+ vassert(gregEnc < 8);
+ return doAMode_M__wrk(p, gregEnc, am);
+}
+
/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
-static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
+inline static UChar* doAMode_R__wrk ( UChar* p, UInt gregEnc, UInt eregEnc )
{
- *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
+ *p++ = mkModRegRM(3, gregEnc, eregEnc);
return p;
}
+static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
+{
+ return doAMode_R__wrk(p, iregEnc(greg), iregEnc(ereg));
+}
+
+static UChar* doAMode_R_enc_reg ( UChar* p, UInt gregEnc, HReg ereg )
+{
+ vassert(gregEnc < 8);
+ return doAMode_R__wrk(p, gregEnc, iregEnc(ereg));
+}
+
+static UChar* doAMode_R_enc_enc ( UChar* p, UInt gregEnc, UInt eregEnc )
+{
+ vassert( (gregEnc|eregEnc) < 8);
+ return doAMode_R__wrk(p, gregEnc, eregEnc);
+}
+
/* Emit ffree %st(7) */
static UChar* do_ffree_st7 ( UChar* p )
/* Emit f<op> %st(i), 1 <= i <= 5 */
static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
{
-# define fake(_n) mkHReg((_n), HRcInt32, False)
Int subopc;
switch (op) {
case Xfp_ADD: subopc = 0; break;
default: vpanic("do_fop2_st: unknown op");
}
*p++ = 0xD8;
- p = doAMode_R(p, fake(subopc), fake(i));
+ p = doAMode_R_enc_enc(p, subopc, i);
return p;
-# undef fake
}
/* Push a 32-bit word on the stack. The word depends on tags[3:0];
vassert(nbuf >= 32);
vassert(mode64 == False);
- /* Wrap an integer as a int register, for use assembling
- GrpN insns, in which the greg field is used as a sub-opcode
- and does not really contain a register. */
-# define fake(_n) mkHReg((_n), HRcInt32, False)
-
/* vex_printf("asm ");ppX86Instr(i, mode64); vex_printf("\n"); */
switch (i->tag) {
if (i->Xin.Alu32R.op == Xalu_MOV) {
switch (i->Xin.Alu32R.src->tag) {
case Xrmi_Imm:
- *p++ = toUChar(0xB8 + iregNo(i->Xin.Alu32R.dst));
+ *p++ = toUChar(0xB8 + iregEnc(i->Xin.Alu32R.dst));
p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
goto done;
case Xrmi_Reg:
} else
if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
*p++ = 0x83;
- p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Xin.Alu32R.dst);
*p++ = toUChar(0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32);
} else {
*p++ = 0x81;
- p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
+ p = doAMode_R_enc_reg(p, subopc_imm, i->Xin.Alu32R.dst);
p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
}
goto done;
goto done;
case Xri_Imm:
*p++ = 0xC7;
- p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst);
+ p = doAMode_M_enc(p, 0, i->Xin.Alu32M.dst);
p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
goto done;
default:
case Xri_Imm:
if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
*p++ = 0x83;
- p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+ p = doAMode_M_enc(p, subopc_imm, i->Xin.Alu32M.dst);
*p++ = toUChar(0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32);
goto done;
} else {
*p++ = 0x81;
- p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
+ p = doAMode_M_enc(p, subopc_imm, i->Xin.Alu32M.dst);
p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
goto done;
}
}
if (i->Xin.Sh32.src == 0) {
*p++ = toUChar(opc_cl);
- p = doAMode_R(p, fake(subopc), i->Xin.Sh32.dst);
+ p = doAMode_R_enc_reg(p, subopc, i->Xin.Sh32.dst);
} else {
*p++ = toUChar(opc_imm);
- p = doAMode_R(p, fake(subopc), i->Xin.Sh32.dst);
+ p = doAMode_R_enc_reg(p, subopc, i->Xin.Sh32.dst);
*p++ = (UChar)(i->Xin.Sh32.src);
}
goto done;
if (i->Xin.Test32.dst->tag == Xrm_Reg) {
/* testl $imm32, %reg */
*p++ = 0xF7;
- p = doAMode_R(p, fake(0), i->Xin.Test32.dst->Xrm.Reg.reg);
+ p = doAMode_R_enc_reg(p, 0, i->Xin.Test32.dst->Xrm.Reg.reg);
p = emit32(p, i->Xin.Test32.imm32);
goto done;
} else {
/* testl $imm32, amode */
*p++ = 0xF7;
- p = doAMode_M(p, fake(0), i->Xin.Test32.dst->Xrm.Mem.am);
+ p = doAMode_M_enc(p, 0, i->Xin.Test32.dst->Xrm.Mem.am);
p = emit32(p, i->Xin.Test32.imm32);
goto done;
}
case Xin_Unary32:
if (i->Xin.Unary32.op == Xun_NOT) {
*p++ = 0xF7;
- p = doAMode_R(p, fake(2), i->Xin.Unary32.dst);
+ p = doAMode_R_enc_reg(p, 2, i->Xin.Unary32.dst);
goto done;
}
if (i->Xin.Unary32.op == Xun_NEG) {
*p++ = 0xF7;
- p = doAMode_R(p, fake(3), i->Xin.Unary32.dst);
+ p = doAMode_R_enc_reg(p, 3, i->Xin.Unary32.dst);
goto done;
}
break;
*p++ = 0xF7;
switch (i->Xin.MulL.src->tag) {
case Xrm_Mem:
- p = doAMode_M(p, fake(subopc),
- i->Xin.MulL.src->Xrm.Mem.am);
+ p = doAMode_M_enc(p, subopc, i->Xin.MulL.src->Xrm.Mem.am);
goto done;
case Xrm_Reg:
- p = doAMode_R(p, fake(subopc),
- i->Xin.MulL.src->Xrm.Reg.reg);
+ p = doAMode_R_enc_reg(p, subopc, i->Xin.MulL.src->Xrm.Reg.reg);
goto done;
default:
goto bad;
*p++ = 0xF7;
switch (i->Xin.Div.src->tag) {
case Xrm_Mem:
- p = doAMode_M(p, fake(subopc),
- i->Xin.Div.src->Xrm.Mem.am);
+ p = doAMode_M_enc(p, subopc, i->Xin.Div.src->Xrm.Mem.am);
goto done;
case Xrm_Reg:
- p = doAMode_R(p, fake(subopc),
- i->Xin.Div.src->Xrm.Reg.reg);
+ p = doAMode_R_enc_reg(p, subopc, i->Xin.Div.src->Xrm.Reg.reg);
goto done;
default:
goto bad;
switch (i->Xin.Push.src->tag) {
case Xrmi_Mem:
*p++ = 0xFF;
- p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
+ p = doAMode_M_enc(p, 6, i->Xin.Push.src->Xrmi.Mem.am);
goto done;
case Xrmi_Imm:
*p++ = 0x68;
p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
goto done;
case Xrmi_Reg:
- *p++ = toUChar(0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg));
+ *p++ = toUChar(0x50 + iregEnc(i->Xin.Push.src->Xrmi.Reg.reg));
goto done;
default:
goto bad;
/* See detailed comment for Xin_Call in getRegUsage_X86Instr above
for explanation of this. */
switch (i->Xin.Call.regparms) {
- case 0: irno = iregNo(hregX86_EAX()); break;
- case 1: irno = iregNo(hregX86_EDX()); break;
- case 2: irno = iregNo(hregX86_ECX()); break;
- case 3: irno = iregNo(hregX86_EDI()); break;
+ case 0: irno = iregEnc(hregX86_EAX()); break;
+ case 1: irno = iregEnc(hregX86_EDX()); break;
+ case 2: irno = iregEnc(hregX86_ECX()); break;
+ case 3: irno = iregEnc(hregX86_EDI()); break;
default: vpanic(" emit_X86Instr:call:regparms");
}
/* jump over the following two insns if the condition does not
/* Update the guest EIP. */
/* movl $dstGA, amEIP */
*p++ = 0xC7;
- p = doAMode_M(p, fake(0), i->Xin.XDirect.amEIP);
+ p = doAMode_M_enc(p, 0, i->Xin.XDirect.amEIP);
p = emit32(p, i->Xin.XDirect.dstGA);
/* --- FIRST PATCHABLE BYTE follows --- */
Sigh. So start off my moving $0 into the dest. */
/* Do we need to swap in %eax? */
- if (iregNo(i->Xin.Set32.dst) >= 4) {
+ if (iregEnc(i->Xin.Set32.dst) >= 4) {
/* xchg %eax, %dst */
- *p++ = toUChar(0x90 + iregNo(i->Xin.Set32.dst));
+ *p++ = toUChar(0x90 + iregEnc(i->Xin.Set32.dst));
/* movl $0, %eax */
- *p++ =toUChar(0xB8 + iregNo(hregX86_EAX()));
+ *p++ =toUChar(0xB8 + iregEnc(hregX86_EAX()));
p = emit32(p, 0);
/* setb lo8(%eax) */
*p++ = 0x0F;
*p++ = toUChar(0x90 + (0xF & i->Xin.Set32.cond));
- p = doAMode_R(p, fake(0), hregX86_EAX());
+ p = doAMode_R_enc_reg(p, 0, hregX86_EAX());
/* xchg %eax, %dst */
- *p++ = toUChar(0x90 + iregNo(i->Xin.Set32.dst));
+ *p++ = toUChar(0x90 + iregEnc(i->Xin.Set32.dst));
} else {
/* movl $0, %dst */
- *p++ = toUChar(0xB8 + iregNo(i->Xin.Set32.dst));
+ *p++ = toUChar(0xB8 + iregEnc(i->Xin.Set32.dst));
p = emit32(p, 0);
/* setb lo8(%dst) */
*p++ = 0x0F;
*p++ = toUChar(0x90 + (0xF & i->Xin.Set32.cond));
- p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
+ p = doAMode_R_enc_reg(p, 0, i->Xin.Set32.dst);
}
goto done;
aren't encoded in the insn. */
*p++ = 0x0F;
*p++ = 0xC7;
- p = doAMode_M(p, fake(1), i->Xin.DACAS.addr);
+ p = doAMode_M_enc(p, 1, i->Xin.DACAS.addr);
goto done;
case Xin_Store:
if (i->Xin.Store.sz == 1) {
/* We have to do complex dodging and weaving if src is not
the low 8 bits of %eax/%ebx/%ecx/%edx. */
- if (iregNo(i->Xin.Store.src) < 4) {
+ if (iregEnc(i->Xin.Store.src) < 4) {
/* we're OK, can do it directly */
*p++ = 0x88;
p = doAMode_M(p, i->Xin.Store.src, i->Xin.Store.dst);
HReg swap = INVALID_HREG;
HReg eax = hregX86_EAX(), ebx = hregX86_EBX(),
ecx = hregX86_ECX(), edx = hregX86_EDX();
- Bool a_ok = True, b_ok = True, c_ok = True, d_ok = True;
HRegUsage u;
- Int j;
initHRegUsage(&u);
- addRegUsage_X86AMode(&u, i->Xin.Store.dst);
- for (j = 0; j < u.n_used; j++) {
- HReg r = u.hreg[j];
- if (sameHReg(r, eax)) a_ok = False;
- if (sameHReg(r, ebx)) b_ok = False;
- if (sameHReg(r, ecx)) c_ok = False;
- if (sameHReg(r, edx)) d_ok = False;
- }
- if (a_ok) swap = eax;
- if (b_ok) swap = ebx;
- if (c_ok) swap = ecx;
- if (d_ok) swap = edx;
+ addRegUsage_X86AMode(&u, i->Xin.Store.dst);
+ /**/ if (! HRegUsage__contains(&u, eax)) { swap = eax; }
+ else if (! HRegUsage__contains(&u, ebx)) { swap = ebx; }
+ else if (! HRegUsage__contains(&u, ecx)) { swap = ecx; }
+ else if (! HRegUsage__contains(&u, edx)) { swap = edx; }
vassert(! hregIsInvalid(swap));
/* xchgl %source, %swap. Could do better if swap is %eax. */
*p++ = 0x87;
--> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
*/
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpUnary.src));
p = do_fop1_st(p, i->Xin.FpUnary.op);
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpUnary.dst));
goto done;
case Xin_FpBinary:
/* ffree %st7 ; fld %st(srcL) ;
ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpBinary.srcL));
p = do_ffree_st7(p);
- p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
+ p = do_fld_st(p, 1+fregEnc(i->Xin.FpBinary.srcR));
*p++ = 0xD9;
*p++ = toUChar(i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9);
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpBinary.dst));
goto done;
}
if (i->Xin.FpBinary.op == Xfp_ATAN) {
/* ffree %st7 ; fld %st(srcL) ;
ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpBinary.srcL));
p = do_ffree_st7(p);
- p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
+ p = do_fld_st(p, 1+fregEnc(i->Xin.FpBinary.srcR));
*p++ = 0xD9; *p++ = 0xF3;
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpBinary.dst));
goto done;
}
if (i->Xin.FpBinary.op == Xfp_PREM
ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
fincstp ; ffree %st7 */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpBinary.srcR));
p = do_ffree_st7(p);
- p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
+ p = do_fld_st(p, 1+fregEnc(i->Xin.FpBinary.srcL));
*p++ = 0xD9;
switch (i->Xin.FpBinary.op) {
case Xfp_PREM: *p++ = 0xF8; break;
case Xfp_SCALE: *p++ = 0xFD; break;
default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
}
- p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
+ p = do_fstp_st(p, 2+fregEnc(i->Xin.FpBinary.dst));
*p++ = 0xD9; *p++ = 0xF7;
p = do_ffree_st7(p);
goto done;
--> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
*/
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpBinary.srcL));
p = do_fop2_st(p, i->Xin.FpBinary.op,
- 1+hregNumber(i->Xin.FpBinary.srcR));
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
+ 1+fregEnc(i->Xin.FpBinary.srcR));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpBinary.dst));
goto done;
case Xin_FpLdSt:
switch (i->Xin.FpLdSt.sz) {
case 4:
*p++ = 0xD9;
- p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 0/*subopcode*/, i->Xin.FpLdSt.addr);
break;
case 8:
*p++ = 0xDD;
- p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 0/*subopcode*/, i->Xin.FpLdSt.addr);
break;
case 10:
*p++ = 0xDB;
- p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 5/*subopcode*/, i->Xin.FpLdSt.addr);
break;
default:
vpanic("emitX86Instr(FpLdSt,load)");
}
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpLdSt.reg));
goto done;
} else {
/* Store from %fakeN into memory.
--> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
*/
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpLdSt.reg));
switch (i->Xin.FpLdSt.sz) {
case 4:
*p++ = 0xD9;
- p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 3/*subopcode*/, i->Xin.FpLdSt.addr);
break;
case 8:
*p++ = 0xDD;
- p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 3/*subopcode*/, i->Xin.FpLdSt.addr);
break;
case 10:
*p++ = 0xDB;
- p = doAMode_M(p, fake(7)/*subopcode*/, i->Xin.FpLdSt.addr);
+ p = doAMode_M_enc(p, 7/*subopcode*/, i->Xin.FpLdSt.addr);
break;
default:
vpanic("emitX86Instr(FpLdSt,store)");
}
p = do_ffree_st7(p);
*p++ = toUChar(opc);
- p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
- p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
+ p = doAMode_M_enc(p, subopc_imm/*subopcode*/, i->Xin.FpLdStI.addr);
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpLdStI.reg));
goto done;
} else {
/* Store from %fakeN into memory, converting to an int.
default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
}
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpLdStI.reg));
*p++ = toUChar(opc);
- p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
+ p = doAMode_M_enc(p, subopc_imm/*subopcode*/, i->Xin.FpLdStI.addr);
goto done;
}
break;
case Xin_Fp64to32:
/* ffree %st7 ; fld %st(src) */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.Fp64to32.src));
/* subl $4, %esp */
*p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
/* fstps (%esp) */
/* addl $4, %esp */
*p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
/* fstp %st(1+dst) */
- p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.Fp64to32.dst));
goto done;
case Xin_FpCMov:
/* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
p = do_ffree_st7(p);
- p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
- p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpCMov.src));
+ p = do_fstp_st(p, 1+fregEnc(i->Xin.FpCMov.dst));
/* Fill in the jump offset. */
*(ptmp-1) = toUChar(p - ptmp);
case Xin_FpLdCW:
*p++ = 0xD9;
- p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdCW.addr);
+ p = doAMode_M_enc(p, 5/*subopcode*/, i->Xin.FpLdCW.addr);
goto done;
case Xin_FpStSW_AX:
/* ffree %st7 */
p = do_ffree_st7(p);
/* fpush %fL */
- p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
+ p = do_fld_st(p, 0+fregEnc(i->Xin.FpCmp.srcL));
/* fucomp %(fR+1) */
*p++ = 0xDD;
- *p++ = toUChar(0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR))));
+ *p++ = toUChar(0xE8 + (7 & (1+fregEnc(i->Xin.FpCmp.srcR))));
/* fnstsw %ax */
*p++ = 0xDF;
*p++ = 0xE0;
/* movl (%esp), %xmm-dst */
*p++ = 0x0F;
*p++ = 0x10;
- *p++ = toUChar(0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst)));
+ *p++ = toUChar(0x04 + 8 * (7 & vregEnc(i->Xin.SseConst.dst)));
*p++ = 0x24;
/* addl $16, %esp */
*p++ = 0x83;
case Xin_SseLdSt:
*p++ = 0x0F;
*p++ = toUChar(i->Xin.SseLdSt.isLoad ? 0x10 : 0x11);
- p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
+ p = doAMode_M_enc(p, vregEnc(i->Xin.SseLdSt.reg), i->Xin.SseLdSt.addr);
goto done;
case Xin_SseLdzLO:
*p++ = toUChar(i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2);
*p++ = 0x0F;
*p++ = 0x10;
- p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
- i->Xin.SseLdzLO.addr);
+ p = doAMode_M_enc(p, vregEnc(i->Xin.SseLdzLO.reg), i->Xin.SseLdzLO.addr);
goto done;
case Xin_Sse32Fx4:
case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
- fake(vregNo(i->Xin.Sse32Fx4.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.Sse32Fx4.dst),
+ vregEnc(i->Xin.Sse32Fx4.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
- fake(vregNo(i->Xin.Sse64Fx2.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.Sse64Fx2.dst),
+ vregEnc(i->Xin.Sse64Fx2.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
- fake(vregNo(i->Xin.Sse32FLo.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.Sse32FLo.dst),
+ vregEnc(i->Xin.Sse32FLo.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
case Xsse_CMPUNF: *p++ = 0xC2; xtra = 0x103; break;
default: goto bad;
}
- p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
- fake(vregNo(i->Xin.Sse64FLo.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.Sse64FLo.dst),
+ vregEnc(i->Xin.Sse64FLo.src) );
if (xtra & 0x100)
*p++ = toUChar(xtra & 0xFF);
goto done;
case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
default: goto bad;
}
- p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
- fake(vregNo(i->Xin.SseReRg.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.SseReRg.dst),
+ vregEnc(i->Xin.SseReRg.src) );
# undef XX
goto done;
/* movaps %src, %dst */
*p++ = 0x0F;
*p++ = 0x28;
- p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
- fake(vregNo(i->Xin.SseCMov.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.SseCMov.dst),
+ vregEnc(i->Xin.SseCMov.src) );
/* Fill in the jump offset. */
*(ptmp-1) = toUChar(p - ptmp);
*p++ = 0x66;
*p++ = 0x0F;
*p++ = 0x70;
- p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
- fake(vregNo(i->Xin.SseShuf.src)) );
+ p = doAMode_R_enc_enc(p, vregEnc(i->Xin.SseShuf.dst),
+ vregEnc(i->Xin.SseShuf.src) );
*p++ = (UChar)(i->Xin.SseShuf.order);
goto done;
js/jns avoids that, though. */
UChar* p0 = p;
/* --- decl 8(%ebp) --- */
- /* "fake(1)" because + there's no register in this encoding;
+ /* "1" because + there's no register in this encoding;
instead the register + field is used as a sub opcode. The
- encoding for "decl r/m32" + is FF /1, hence the fake(1). */
+ encoding for "decl r/m32" + is FF /1, hence the "1". */
*p++ = 0xFF;
- p = doAMode_M(p, fake(1), i->Xin.EvCheck.amCounter);
+ p = doAMode_M_enc(p, 1, i->Xin.EvCheck.amCounter);
vassert(p - p0 == 3);
/* --- jns nofail --- */
*p++ = 0x79;
/* --- jmp* 0(%ebp) --- */
/* The encoding is FF /4. */
*p++ = 0xFF;
- p = doAMode_M(p, fake(4), i->Xin.EvCheck.amFailAddr);
+ p = doAMode_M_enc(p, 4, i->Xin.EvCheck.amFailAddr);
vassert(p - p0 == 8); /* also ensures that 0x03 offset above is ok */
/* And crosscheck .. */
vassert(evCheckSzB_X86() == 8);
done:
vassert(p - &buf[0] <= 32);
return p - &buf[0];
-
-# undef fake
}
6 real float regs, and 8 real vector regs.
*/
-extern void ppHRegX86 ( HReg );
+#define ST_IN static inline
+ST_IN HReg hregX86_EAX ( void ) { return mkHReg(False, HRcInt32, 0, 0); }
+ST_IN HReg hregX86_EBX ( void ) { return mkHReg(False, HRcInt32, 3, 1); }
+ST_IN HReg hregX86_ECX ( void ) { return mkHReg(False, HRcInt32, 1, 2); }
+ST_IN HReg hregX86_EDX ( void ) { return mkHReg(False, HRcInt32, 2, 3); }
+ST_IN HReg hregX86_ESI ( void ) { return mkHReg(False, HRcInt32, 6, 4); }
+ST_IN HReg hregX86_EDI ( void ) { return mkHReg(False, HRcInt32, 7, 5); }
+
+ST_IN HReg hregX86_FAKE0 ( void ) { return mkHReg(False, HRcFlt64, 0, 6); }
+ST_IN HReg hregX86_FAKE1 ( void ) { return mkHReg(False, HRcFlt64, 1, 7); }
+ST_IN HReg hregX86_FAKE2 ( void ) { return mkHReg(False, HRcFlt64, 2, 8); }
+ST_IN HReg hregX86_FAKE3 ( void ) { return mkHReg(False, HRcFlt64, 3, 9); }
+ST_IN HReg hregX86_FAKE4 ( void ) { return mkHReg(False, HRcFlt64, 4, 10); }
+ST_IN HReg hregX86_FAKE5 ( void ) { return mkHReg(False, HRcFlt64, 5, 11); }
+
+ST_IN HReg hregX86_XMM0 ( void ) { return mkHReg(False, HRcVec128, 0, 12); }
+ST_IN HReg hregX86_XMM1 ( void ) { return mkHReg(False, HRcVec128, 1, 13); }
+ST_IN HReg hregX86_XMM2 ( void ) { return mkHReg(False, HRcVec128, 2, 14); }
+ST_IN HReg hregX86_XMM3 ( void ) { return mkHReg(False, HRcVec128, 3, 15); }
+ST_IN HReg hregX86_XMM4 ( void ) { return mkHReg(False, HRcVec128, 4, 16); }
+ST_IN HReg hregX86_XMM5 ( void ) { return mkHReg(False, HRcVec128, 5, 17); }
+ST_IN HReg hregX86_XMM6 ( void ) { return mkHReg(False, HRcVec128, 6, 18); }
+ST_IN HReg hregX86_XMM7 ( void ) { return mkHReg(False, HRcVec128, 7, 19); }
+
+ST_IN HReg hregX86_ESP ( void ) { return mkHReg(False, HRcInt32, 4, 20); }
+ST_IN HReg hregX86_EBP ( void ) { return mkHReg(False, HRcInt32, 5, 21); }
+#undef ST_IN
-extern HReg hregX86_EAX ( void );
-extern HReg hregX86_EBX ( void );
-extern HReg hregX86_ECX ( void );
-extern HReg hregX86_EDX ( void );
-extern HReg hregX86_ESP ( void );
-extern HReg hregX86_EBP ( void );
-extern HReg hregX86_ESI ( void );
-extern HReg hregX86_EDI ( void );
-
-extern HReg hregX86_FAKE0 ( void );
-extern HReg hregX86_FAKE1 ( void );
-extern HReg hregX86_FAKE2 ( void );
-extern HReg hregX86_FAKE3 ( void );
-extern HReg hregX86_FAKE4 ( void );
-extern HReg hregX86_FAKE5 ( void );
-
-extern HReg hregX86_XMM0 ( void );
-extern HReg hregX86_XMM1 ( void );
-extern HReg hregX86_XMM2 ( void );
-extern HReg hregX86_XMM3 ( void );
-extern HReg hregX86_XMM4 ( void );
-extern HReg hregX86_XMM5 ( void );
-extern HReg hregX86_XMM6 ( void );
-extern HReg hregX86_XMM7 ( void );
+extern void ppHRegX86 ( HReg );
/* --------- Condition codes, Intel encoding. --------- */
extern void genReload_X86 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
-extern X86Instr* directReload_X86 ( X86Instr* i,
- HReg vreg, Short spill_off );
-extern void getAllocableRegs_X86 ( Int*, HReg** );
+extern X86Instr* directReload_X86 ( X86Instr* i, HReg vreg, Short spill_off );
+
+extern const RRegUniverse* getRRegUniverse_X86 ( void );
+
extern HInstrArray* iselSB_X86 ( const IRSB*,
VexArch,
const VexArchInfo*,
static HReg newVRegI ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcInt32, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegF ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt64, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
static HReg newVRegV ( ISelEnv* env )
{
- HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
+ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0/*enc*/, env->vreg_ctr);
env->vreg_ctr++;
return reg;
}
case Ity_I1:
case Ity_I8:
case Ity_I16:
- case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break;
- case Ity_I64: hreg = mkHReg(j++, HRcInt32, True);
- hregHI = mkHReg(j++, HRcInt32, True); break;
+ case Ity_I32: hreg = mkHReg(True, HRcInt32, 0, j++); break;
+ case Ity_I64: hreg = mkHReg(True, HRcInt32, 0, j++);
+ hregHI = mkHReg(True, HRcInt32, 0, j++); break;
case Ity_F32:
- case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break;
- case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break;
+ case Ity_F64: hreg = mkHReg(True, HRcFlt64, 0, j++); break;
+ case Ity_V128: hreg = mkHReg(True, HRcVec128, 0, j++); break;
default: ppIRType(bb->tyenv->types[i]);
vpanic("iselBB: IRTemp type");
}
vassert(sizeof(IRStmt) == 32);
}
+ /* Ditto */
+ vassert(sizeof(HReg) == 4);
+ /* If N_RREGUNIVERSE_REGS ever exceeds 64, the bitset fields in
+ RRegSet and HRegUsage will need to be changed to something
+ better than ULong. */
+ vassert(N_RREGUNIVERSE_REGS == 64);
+
/* Check that signed integer division on the host rounds towards
zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
correctly. */
/* This the bundle of functions we need to do the back-end stuff
(insn selection, reg-alloc, assembly) whilst being insulated
from the target instruction set. */
- HReg* available_real_regs;
- Int n_available_real_regs;
Bool (*isMove) ( const HInstr*, HReg*, HReg* );
void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool );
void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
Bool (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
+ const RRegUniverse* rRegUniv = NULL;
+
DisOneInstrFn disInstrFn;
VexGuestLayout* guest_layout;
Addr max_ga;
guest_layout = NULL;
- available_real_regs = NULL;
- n_available_real_regs = 0;
isMove = NULL;
getRegUsage = NULL;
mapRegs = NULL;
case VexArchX86:
mode64 = False;
- getAllocableRegs_X86 ( &n_available_real_regs,
- &available_real_regs );
+ rRegUniv = getRRegUniverse_X86();
isMove = (__typeof__(isMove)) isMove_X86Instr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_X86Instr;
mapRegs = (__typeof__(mapRegs)) mapRegs_X86Instr;
ppReg = (__typeof__(ppReg)) ppHRegX86;
iselSB = iselSB_X86;
emit = (__typeof__(emit)) emit_X86Instr;
- host_word_type = Ity_I32;
+ host_word_type = Ity_I32;
vassert(vta->archinfo_host.endness == VexEndnessLE);
break;
case VexArchAMD64:
- mode64 = True;
- getAllocableRegs_AMD64 ( &n_available_real_regs,
- &available_real_regs );
+ mode64 = True;
+ rRegUniv = getRRegUniverse_AMD64();
isMove = (__typeof__(isMove)) isMove_AMD64Instr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_AMD64Instr;
mapRegs = (__typeof__(mapRegs)) mapRegs_AMD64Instr;
ppReg = (__typeof__(ppReg)) ppHRegAMD64;
iselSB = iselSB_AMD64;
emit = (__typeof__(emit)) emit_AMD64Instr;
- host_word_type = Ity_I64;
+ host_word_type = Ity_I64;
vassert(vta->archinfo_host.endness == VexEndnessLE);
break;
case VexArchPPC32:
- mode64 = False;
- getAllocableRegs_PPC ( &n_available_real_regs,
- &available_real_regs, mode64 );
+ mode64 = False;
+ rRegUniv = getRRegUniverse_PPC(mode64);
isMove = (__typeof__(isMove)) isMove_PPCInstr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
ppReg = (__typeof__(ppReg)) ppHRegPPC;
iselSB = iselSB_PPC;
emit = (__typeof__(emit)) emit_PPCInstr;
- host_word_type = Ity_I32;
+ host_word_type = Ity_I32;
vassert(vta->archinfo_host.endness == VexEndnessBE);
break;
case VexArchPPC64:
- mode64 = True;
- getAllocableRegs_PPC ( &n_available_real_regs,
- &available_real_regs, mode64 );
+ mode64 = True;
+ rRegUniv = getRRegUniverse_PPC(mode64);
isMove = (__typeof__(isMove)) isMove_PPCInstr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
ppReg = (__typeof__(ppReg)) ppHRegPPC;
iselSB = iselSB_PPC;
emit = (__typeof__(emit)) emit_PPCInstr;
- host_word_type = Ity_I64;
+ host_word_type = Ity_I64;
vassert(vta->archinfo_host.endness == VexEndnessBE ||
vta->archinfo_host.endness == VexEndnessLE );
break;
case VexArchS390X:
- mode64 = True;
+ mode64 = True;
/* KLUDGE: export hwcaps. */
s390_host_hwcaps = vta->archinfo_host.hwcaps;
- getAllocableRegs_S390 ( &n_available_real_regs,
- &available_real_regs, mode64 );
+ rRegUniv = getRRegUniverse_S390();
isMove = (__typeof__(isMove)) isMove_S390Instr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_S390Instr;
mapRegs = (__typeof__(mapRegs)) mapRegs_S390Instr;
ppReg = (__typeof__(ppReg)) ppHRegS390;
iselSB = iselSB_S390;
emit = (__typeof__(emit)) emit_S390Instr;
- host_word_type = Ity_I64;
+ host_word_type = Ity_I64;
vassert(vta->archinfo_host.endness == VexEndnessBE);
break;
case VexArchARM:
- mode64 = False;
- getAllocableRegs_ARM ( &n_available_real_regs,
- &available_real_regs );
+ mode64 = False;
+ rRegUniv = getRRegUniverse_ARM();
isMove = (__typeof__(isMove)) isMove_ARMInstr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARMInstr;
mapRegs = (__typeof__(mapRegs)) mapRegs_ARMInstr;
ppReg = (__typeof__(ppReg)) ppHRegARM;
iselSB = iselSB_ARM;
emit = (__typeof__(emit)) emit_ARMInstr;
- host_word_type = Ity_I32;
+ host_word_type = Ity_I32;
vassert(vta->archinfo_host.endness == VexEndnessLE);
break;
case VexArchARM64:
- mode64 = True;
- getAllocableRegs_ARM64 ( &n_available_real_regs,
- &available_real_regs );
+ mode64 = True;
+ rRegUniv = getRRegUniverse_ARM64();
isMove = (__typeof__(isMove)) isMove_ARM64Instr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARM64Instr;
mapRegs = (__typeof__(mapRegs)) mapRegs_ARM64Instr;
ppReg = (__typeof__(ppReg)) ppHRegARM64;
iselSB = iselSB_ARM64;
emit = (__typeof__(emit)) emit_ARM64Instr;
- host_word_type = Ity_I64;
+ host_word_type = Ity_I64;
vassert(vta->archinfo_host.endness == VexEndnessLE);
break;
case VexArchMIPS32:
- mode64 = False;
- getAllocableRegs_MIPS ( &n_available_real_regs,
- &available_real_regs, mode64 );
+ mode64 = False;
+ rRegUniv = getRRegUniverse_MIPS(mode64);
isMove = (__typeof__(isMove)) isMove_MIPSInstr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
ppReg = (__typeof__(ppReg)) ppHRegMIPS;
iselSB = iselSB_MIPS;
emit = (__typeof__(emit)) emit_MIPSInstr;
- host_word_type = Ity_I32;
+ host_word_type = Ity_I32;
vassert(vta->archinfo_host.endness == VexEndnessLE
|| vta->archinfo_host.endness == VexEndnessBE);
break;
case VexArchMIPS64:
- mode64 = True;
- getAllocableRegs_MIPS ( &n_available_real_regs,
- &available_real_regs, mode64 );
+ mode64 = True;
+ rRegUniv = getRRegUniverse_MIPS(mode64);
isMove = (__typeof__(isMove)) isMove_MIPSInstr;
getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
ppReg = (__typeof__(ppReg)) ppHRegMIPS;
iselSB = iselSB_MIPS;
emit = (__typeof__(emit)) emit_MIPSInstr;
- host_word_type = Ity_I64;
+ host_word_type = Ity_I64;
vassert(vta->archinfo_host.endness == VexEndnessLE
|| vta->archinfo_host.endness == VexEndnessBE);
break;
}
/* Register allocate. */
- rcode = doRegisterAllocation ( vcode, available_real_regs,
- n_available_real_regs,
+ rcode = doRegisterAllocation ( vcode, rRegUniv,
isMove, getRegUsage, mapRegs,
genSpill, genReload, directReload,
guest_sizeB,