]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Bug 345215 - Performance improvements for the register allocator
authorJulian Seward <jseward@acm.org>
Thu, 26 Mar 2015 07:18:32 +0000 (07:18 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 26 Mar 2015 07:18:32 +0000 (07:18 +0000)
The basic idea is to change the representation of registers (HReg) so
as to give Real registers a unique integer index starting from 0, with
the registers available for allocation numbered consectively from zero
upwards. This allows the register allocator to index into its primary
data structure -- a table tracking the status of each available
register -- using normal array index instead of having to search
sequentially through the table, as now.

It also allows an efficient bitmap-based representation for "set of
Real registers", which is important for the NCODE work.

There are various other perf improvements, most notably in calling
getRegUsage once rather than twice per instruction.

Cost of register allocation is reduced to around 65% ish of what it
previously was. This translates in to speedups close to zero for
compute intensive code up to around 7% for JITing intensive
situations, eg "time perl tests/vg_regtest memcheck/tests/amd64".

git-svn-id: svn://svn.valgrind.org/vex/trunk@3107

25 files changed:
VEX/priv/host_amd64_defs.c
VEX/priv/host_amd64_defs.h
VEX/priv/host_amd64_isel.c
VEX/priv/host_arm64_defs.c
VEX/priv/host_arm64_defs.h
VEX/priv/host_arm64_isel.c
VEX/priv/host_arm_defs.c
VEX/priv/host_arm_defs.h
VEX/priv/host_arm_isel.c
VEX/priv/host_generic_reg_alloc2.c
VEX/priv/host_generic_regs.c
VEX/priv/host_generic_regs.h
VEX/priv/host_mips_defs.c
VEX/priv/host_mips_defs.h
VEX/priv/host_mips_isel.c
VEX/priv/host_ppc_defs.c
VEX/priv/host_ppc_defs.h
VEX/priv/host_ppc_isel.c
VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/host_s390_isel.c
VEX/priv/host_x86_defs.c
VEX/priv/host_x86_defs.h
VEX/priv/host_x86_isel.c
VEX/priv/main_main.c

index 3bf2ae7aa73b65fa6622a2b5e11431b018f8fa09..7534e4378cf49f8f5ed1d6c9e691cb70d83c7395 100644 (file)
 
 /* --------- 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;
@@ -58,17 +115,12 @@ void ppHRegAMD64 ( HReg 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", 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;
@@ -81,8 +133,8 @@ static void ppHRegAMD64_lo32 ( HReg reg )
 {
    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);
@@ -92,7 +144,7 @@ static void ppHRegAMD64_lo32 ( HReg 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;
@@ -101,77 +153,6 @@ static void ppHRegAMD64_lo32 ( HReg reg )
    }
 }
 
-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. --------- */
 
@@ -1962,80 +1943,61 @@ void genReload_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 /* --------- 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 )
@@ -2102,8 +2064,9 @@ static Bool fitsIn32Bits ( ULong x )
                |  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())
@@ -2111,39 +2074,36 @@ static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
           && ! 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;
@@ -2155,16 +2115,16 @@ static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
    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;
       }
@@ -2176,52 +2136,122 @@ static UChar* doAMode_M ( UChar* p, HReg greg, AMD64AMode* am )
    /*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);
 }
 
 
@@ -2271,14 +2301,14 @@ static UChar rexAMode_R ( HReg greg, HReg ereg )
 //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    }
@@ -2339,11 +2369,6 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
    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) {
@@ -2354,13 +2379,13 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -2380,14 +2405,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
                      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;
@@ -2475,14 +2500,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
                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;
@@ -2517,9 +2542,9 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
                                 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: 
@@ -2537,14 +2562,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
       }
@@ -2552,23 +2577,23 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
 
    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;
@@ -2606,16 +2631,16 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
                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;
@@ -2646,18 +2671,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -2672,15 +2693,13 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
                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;
@@ -2689,18 +2708,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -2712,17 +2727,17 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -3148,7 +3163,7 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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 */
@@ -3206,13 +3221,13 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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:
@@ -3227,15 +3242,15 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -3276,16 +3291,16 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
 
    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:
@@ -3318,10 +3333,10 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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:
@@ -3334,53 +3349,53 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -3394,10 +3409,12 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -3405,19 +3422,19 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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;
@@ -3435,8 +3452,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3445,8 +3462,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -3462,8 +3479,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3472,8 +3489,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -3491,8 +3508,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3501,8 +3518,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -3518,8 +3535,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3528,8 +3545,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
 #     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;
@@ -3589,8 +3606,8 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
 
@@ -3602,12 +3619,12 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
 
       /* 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);
@@ -3616,12 +3633,12 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
    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;
 
@@ -3652,14 +3669,14 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       /* ---  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;
@@ -3669,10 +3686,10 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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);
@@ -3710,8 +3727,6 @@ Int emit_AMD64Instr ( /*MB_MOD*/Bool* is_profInc,
   done:
    vassert(p - &buf[0] <= 32);
    return p - &buf[0];
-
-#  undef fake
 }
 
 
index b3959e47eec9011ce35f6af5bbf8e0e9ab564020..f76cd8392aedcb44f8c0fe777ec54c9fd6f9d282 100644 (file)
    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. --------- */
@@ -790,7 +788,8 @@ extern void genSpill_AMD64  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 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*,
index 6f9e125bcd3c4ba8ab1a460de469e289a41530d8..81bea0be900d370b924e531b29a4f1dd823c888f 100644 (file)
@@ -193,14 +193,14 @@ static void addInstr ( ISelEnv* env, AMD64Instr* instr )
 
 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;
 }
@@ -4951,20 +4951,20 @@ HInstrArray* iselSB_AMD64 ( const IRSB* bb,
       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]);
index fbfca3ceb32d2631c5996ce8c61826c1aefe7fc1..f937c4ddd2530b7549b32f1567bb0d70a1eca7fa 100644 (file)
@@ -36,8 +36,6 @@
 #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
@@ -190,7 +130,50 @@ void getAllocableRegs_ARM64 ( Int* nregs, HReg** arr )
    // 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)");
 }
 
 
@@ -2501,38 +2484,38 @@ void genReload_ARM64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 }
 
 
-//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) \
@@ -2863,7 +2846,7 @@ static inline UInt X_3_6_1_6_6_5_5 ( UInt f1, UInt f2, UInt f3,
 
 
 /* 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
@@ -2909,7 +2892,7 @@ static UInt* imm64_to_iregNo ( UInt* p, Int xD, ULong imm64 )
    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);
@@ -2932,8 +2915,8 @@ static UInt* imm64_to_iregNo_EXACTLY4 ( UInt* p, Int xD, ULong imm64 )
 }
 
 /* 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);
@@ -2973,7 +2956,7 @@ static UInt* do_load_or_store8 ( UInt* p,
       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;
    }
@@ -2984,7 +2967,7 @@ static UInt* do_load_or_store8 ( UInt* 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);
@@ -2995,8 +2978,8 @@ static UInt* do_load_or_store8 ( UInt* p,
       /* 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);
@@ -3022,7 +3005,7 @@ static UInt* do_load_or_store16 ( UInt* p,
       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;
    }
@@ -3033,7 +3016,7 @@ static UInt* do_load_or_store16 ( UInt* 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);
@@ -3044,8 +3027,8 @@ static UInt* do_load_or_store16 ( UInt* p,
       /* 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);
@@ -3071,7 +3054,7 @@ static UInt* do_load_or_store32 ( UInt* p,
       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;
    }
@@ -3082,7 +3065,7 @@ static UInt* do_load_or_store32 ( UInt* 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);
@@ -3093,8 +3076,8 @@ static UInt* do_load_or_store32 ( UInt* p,
       /* 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);
@@ -3119,7 +3102,7 @@ static UInt* do_load_or_store64 ( UInt* p,
       */
       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);
@@ -3133,7 +3116,7 @@ static UInt* do_load_or_store64 ( UInt* p,
       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);
@@ -3144,8 +3127,8 @@ static UInt* do_load_or_store64 ( UInt* p,
       /* 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);
@@ -3178,8 +3161,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
 
    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:
@@ -3191,7 +3174,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
                       );
                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
@@ -3205,7 +3188,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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) {
@@ -3220,7 +3203,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -3231,8 +3214,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          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);
@@ -3260,7 +3243,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
                /* 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;
@@ -3272,7 +3255,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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: {
@@ -3290,8 +3273,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          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);
@@ -3322,7 +3305,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
                /* 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) {
@@ -3340,8 +3323,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          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 */
@@ -3371,37 +3354,37 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
       }
@@ -3430,7 +3413,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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);
 
@@ -3447,8 +3430,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          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 --- */
 
@@ -3486,12 +3468,12 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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. */
@@ -3525,7 +3507,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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 */
@@ -3554,11 +3536,11 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
                       "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. */
@@ -3577,9 +3559,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
 
       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);
@@ -3610,15 +3592,14 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          }
 
          // 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);
@@ -3649,7 +3630,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
 
       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;
@@ -3660,9 +3641,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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:
@@ -3725,8 +3706,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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));
@@ -3742,8 +3723,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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));
@@ -3759,8 +3740,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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) {
@@ -3781,8 +3762,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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) {
@@ -3827,8 +3808,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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. */
@@ -3876,8 +3857,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             ---------- 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 {
@@ -3892,8 +3873,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             ------------------- 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) {
@@ -3930,8 +3911,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             ------------------- 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) {
@@ -3968,9 +3949,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             ---------------- 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;
@@ -3991,9 +3972,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             ---------------- 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;
@@ -4009,15 +3990,15 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
       }
@@ -4027,9 +4008,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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,
@@ -4038,7 +4019,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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);
@@ -4048,7 +4029,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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);
@@ -4208,9 +4189,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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);
@@ -4670,8 +4651,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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);
@@ -4743,8 +4724,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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);
@@ -4856,8 +4837,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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) {
@@ -4915,8 +4896,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
                     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 */
 
@@ -5053,9 +5034,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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,
@@ -5063,7 +5044,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          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) {
@@ -5107,8 +5088,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -5119,8 +5100,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -5132,9 +5113,9 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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);
@@ -5145,8 +5126,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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);
@@ -5159,8 +5140,8 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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,
@@ -5178,14 +5159,14 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
         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;
            }
@@ -5235,7 +5216,7 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -5286,13 +5267,13 @@ VexInvalRange chainXDirect_ARM64 ( VexEndness endness_host,
         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:
@@ -5302,13 +5283,12 @@ VexInvalRange chainXDirect_ARM64 ( VexEndness endness_host,
         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};
@@ -5332,12 +5312,12 @@ VexInvalRange unchainXDirect_ARM64 ( VexEndness endness_host,
         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);
 
@@ -5348,11 +5328,10 @@ VexInvalRange unchainXDirect_ARM64 ( VexEndness endness_host,
         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};
@@ -5370,12 +5349,11 @@ VexInvalRange patchProfInc_ARM64 ( VexEndness endness_host,
    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;
 }
index 281cb0e86e7ed718daf492bbdfe0f9d796247ea1..ab3d91754fb798d745321340adda96c5cc129207 100644 (file)
 
 /* --------- 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 */
 
@@ -953,7 +949,8 @@ extern void genSpill_ARM64  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 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*,
index 669939af218aff60313680276f984df1c64eeb52..829c39a3d5b247b41ded9da509f1700e8999c4e4 100644 (file)
@@ -157,21 +157,21 @@ static void addInstr ( ISelEnv* env, ARM64Instr* instr )
 
 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;
 }
@@ -3959,22 +3959,22 @@ HInstrArray* iselSB_ARM64 ( const IRSB* bb,
       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]);
index bd2e9d38d9287aedc9cdfc850d0c54ddbb70a937..310271d392bcff877c9af44885ae1b3da2f61b0f 100644 (file)
@@ -46,9 +46,99 @@ UInt arm_hwcaps = 0;
 
 /* --------- 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;
@@ -60,22 +150,22 @@ void ppHRegARM ( HReg reg )  {
    /* 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;
@@ -84,110 +174,6 @@ void ppHRegARM ( HReg reg )  {
    }
 }
 
-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. --------- */
 
@@ -2682,46 +2668,44 @@ void genReload_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
    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) \
@@ -2787,7 +2771,7 @@ static UInt skeletal_RI84 ( ARMRI84* ri )
       instr |= ri->ARMri84.I84.imm8;
    } else {
       instr = 0 << 25;
-      instr |= iregNo(ri->ARMri84.R.reg);
+      instr |= iregEnc(ri->ARMri84.R.reg);
    }
    return instr;
 }
@@ -2804,7 +2788,7 @@ static UInt skeletal_RI5 ( ARMRI5* ri )
       instr |= imm5 << 7;
    } else {
       instr = 1 << 4;
-      instr |= iregNo(ri->ARMri5.R.reg) << 8;
+      instr |= iregEnc(ri->ARMri5.R.reg) << 8;
    }
    return instr;
 }
@@ -2812,7 +2796,7 @@ static UInt skeletal_RI5 ( ARMRI5* ri )
 
 /* 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!
@@ -2894,7 +2878,7 @@ static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
    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. */
@@ -2916,8 +2900,8 @@ static UInt* imm32_to_iregNo_EXACTLY2 ( UInt* p, Int rD, UInt imm32 )
 }
 
 /* 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. */
@@ -2955,7 +2939,7 @@ static UInt* do_load_or_store32 ( UInt* p,
    }
    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;
@@ -2985,8 +2969,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
    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 */
@@ -3013,8 +2997,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
@@ -3030,8 +3014,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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,
@@ -3061,7 +3045,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
       }
@@ -3071,13 +3055,13 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -3112,8 +3096,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             }
             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;
@@ -3146,22 +3130,22 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             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;
             }
@@ -3191,8 +3175,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             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 {
@@ -3226,7 +3210,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          /* 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);
 
@@ -3241,8 +3225,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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 --- */
 
@@ -3283,14 +3267,13 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          /* 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. */
@@ -3322,7 +3305,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          /* 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 */
@@ -3349,13 +3332,12 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
                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. */
@@ -3377,7 +3359,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
       }
@@ -3401,8 +3383,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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);
@@ -3430,8 +3412,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             *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, /*___*/
@@ -3454,11 +3436,11 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             /* 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;
@@ -3519,8 +3501,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3535,8 +3517,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3552,9 +3534,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3574,9 +3556,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3600,8 +3582,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -3623,8 +3605,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -3654,8 +3636,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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 */
@@ -3663,8 +3645,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
@@ -3672,8 +3654,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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,
@@ -3683,16 +3665,16 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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);
@@ -3701,9 +3683,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          }
       }
       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
@@ -3717,8 +3699,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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
@@ -3736,8 +3718,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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);
@@ -3746,8 +3728,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          }
          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);
@@ -3756,8 +3738,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          }
          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);
@@ -3766,8 +3748,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          }
          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);
@@ -3779,7 +3761,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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);
@@ -3805,7 +3787,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
 
       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;
@@ -3813,10 +3795,10 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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),
@@ -3825,7 +3807,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3833,10 +3815,10 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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),
@@ -3860,11 +3842,11 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
                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;
@@ -3875,9 +3857,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
                *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;
@@ -3911,9 +3893,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
                *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;
@@ -3952,9 +3934,9 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
                *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;
@@ -4006,8 +3988,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -4017,11 +3999,11 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -4222,11 +4204,11 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -4256,14 +4238,14 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -4482,14 +4464,14 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -4529,8 +4511,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -4544,8 +4526,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
@@ -4592,8 +4574,8 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
@@ -4609,12 +4591,12 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -4663,7 +4645,7 @@ Int emit_ARMInstr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -4715,12 +4697,12 @@ VexInvalRange chainXDirect_ARM ( VexEndness endness_host,
         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:
@@ -4729,7 +4711,7 @@ VexInvalRange chainXDirect_ARM ( VexEndness endness_host,
           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
@@ -4774,7 +4756,7 @@ VexInvalRange chainXDirect_ARM ( VexEndness endness_host,
       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;
    }
@@ -4799,7 +4781,7 @@ VexInvalRange unchainXDirect_ARM ( VexEndness endness_host,
           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
@@ -4813,7 +4795,7 @@ VexInvalRange unchainXDirect_ARM ( VexEndness endness_host,
    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 */
@@ -4837,10 +4819,10 @@ VexInvalRange unchainXDirect_ARM ( VexEndness endness_host,
         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};
@@ -4858,15 +4840,14 @@ VexInvalRange patchProfInc_ARM ( VexEndness endness_host,
    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;
 }
index 6bc24d4d04e409a6d3e10c5b7c04a49c0982476f..f0b172baef2de40bdee36bed5a3aa8d78139c639 100644 (file)
@@ -39,47 +39,50 @@ extern UInt arm_hwcaps;
 
 /* --------- 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 */
 
@@ -1038,7 +1041,8 @@ extern void genSpill_ARM  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 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*,
index c3443d81490c34e922955fac42a965cbb4d3ab6b..b867c3d106e20aa60d2a55b3da1152fdecf8a6b6 100644 (file)
@@ -149,40 +149,32 @@ static void addInstr ( ISelEnv* env, ARMInstr* instr )
       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;
 }
@@ -6394,18 +6386,18 @@ HInstrArray* iselSB_ARM ( const IRSB* bb,
          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");
       }
@@ -6442,3 +6434,4 @@ HInstrArray* iselSB_ARM ( const IRSB* bb,
 /*---------------------------------------------------------------*/
 /*--- end                                     host_arm_isel.c ---*/
 /*---------------------------------------------------------------*/
+
index 5ea9c0058653e565e82ef862d3ffe3f869d5ca17..b3036063f349da4b310bc0caef57dae4ddc46757 100644 (file)
@@ -88,12 +88,14 @@ typedef
 /* 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 ------ */
@@ -142,24 +144,6 @@ typedef
 #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)(&reg_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
@@ -170,16 +154,19 @@ static Bool instrMentionsReg (
    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;
@@ -190,9 +177,8 @@ Int findMostDistantlyMentionedVReg (
       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(&reg_usages_in[m], state[k].vreg))
             break;
       }
       if (m > furthest) {
@@ -205,7 +191,8 @@ Int findMostDistantlyMentionedVReg (
 
 
 /* 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:
@@ -217,11 +204,11 @@ static inline void sanity_check_spill_offset ( VRegLR* vreg )
 
 
 /* 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);
@@ -231,6 +218,12 @@ static void ensureRRLRspace ( RRegLR** info, Int* size, Int used )
    *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
@@ -289,6 +282,61 @@ static void sortRRLRarray ( RRegLR* arr,
 }
 
 
+/* 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.
@@ -309,10 +357,10 @@ HInstrArray* doRegisterAllocation (
    /* 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. */
@@ -348,11 +396,6 @@ HInstrArray* doRegisterAllocation (
 
    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;
@@ -371,9 +414,14 @@ HInstrArray* doRegisterAllocation (
    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;
@@ -426,7 +474,7 @@ HInstrArray* doRegisterAllocation (
          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;         \
@@ -457,17 +505,19 @@ HInstrArray* doRegisterAllocation (
 
    /* ... 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;
@@ -475,7 +525,7 @@ HInstrArray* doRegisterAllocation (
       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;
 
 
@@ -494,7 +544,7 @@ HInstrArray* doRegisterAllocation (
    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;
@@ -502,6 +552,11 @@ HInstrArray* doRegisterAllocation (
       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 ------ */
@@ -517,11 +572,11 @@ HInstrArray* doRegisterAllocation (
 
    /* 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;
    }
@@ -530,27 +585,26 @@ HInstrArray* doRegisterAllocation (
 
    /* ------ 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)( &reg_usage, instrs_in->arr[ii], mode64 );
+      (*getRegUsage)( &reg_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(&reg_usage);
-#     endif
+      if (0) {
+         vex_printf("\n%d  stage1: ", ii);
+         (*ppInstr)(instrs_in->arr[ii], mode64);
+         vex_printf("\n");
+         ppHRegUsage(univ, &reg_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);
@@ -570,7 +624,7 @@ HInstrArray* doRegisterAllocation (
          }
 
          /* 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);
@@ -596,74 +650,90 @@ HInstrArray* doRegisterAllocation (
                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) {
@@ -672,13 +742,13 @@ HInstrArray* doRegisterAllocation (
             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 ------ */
 
@@ -689,17 +759,17 @@ HInstrArray* doRegisterAllocation (
    /* ------ 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)
@@ -709,7 +779,7 @@ HInstrArray* doRegisterAllocation (
       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++;
@@ -723,22 +793,20 @@ HInstrArray* doRegisterAllocation (
       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");
       }
    }
@@ -746,7 +814,7 @@ HInstrArray* doRegisterAllocation (
    /* 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*/  );
@@ -756,36 +824,36 @@ HInstrArray* doRegisterAllocation (
    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. --------- */
 
@@ -804,7 +872,7 @@ HInstrArray* doRegisterAllocation (
       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.
@@ -813,12 +881,11 @@ HInstrArray* doRegisterAllocation (
       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.  */
@@ -834,6 +901,7 @@ HInstrArray* doRegisterAllocation (
          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:
@@ -841,18 +909,16 @@ HInstrArray* doRegisterAllocation (
                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:
@@ -860,22 +926,22 @@ HInstrArray* doRegisterAllocation (
             /* 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] );
@@ -883,12 +949,12 @@ HInstrArray* doRegisterAllocation (
       /*    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 --------- */
 
@@ -913,27 +979,27 @@ HInstrArray* doRegisterAllocation (
 
    /* ------ 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) {
@@ -941,28 +1007,25 @@ HInstrArray* doRegisterAllocation (
          /* 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);
             }
          }
 
@@ -970,17 +1033,21 @@ HInstrArray* doRegisterAllocation (
             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);
@@ -988,15 +1055,14 @@ HInstrArray* doRegisterAllocation (
 
          /* 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
@@ -1004,20 +1070,20 @@ HInstrArray* doRegisterAllocation (
             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) */
@@ -1032,46 +1098,46 @@ HInstrArray* doRegisterAllocation (
       /* 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
@@ -1085,20 +1151,20 @@ HInstrArray* doRegisterAllocation (
       /* 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");
             }
          }
@@ -1137,18 +1203,17 @@ HInstrArray* doRegisterAllocation (
             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. */
@@ -1159,7 +1224,7 @@ HInstrArray* doRegisterAllocation (
                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)
@@ -1178,13 +1243,11 @@ HInstrArray* doRegisterAllocation (
          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. ------ */
 
@@ -1194,8 +1257,6 @@ HInstrArray* doRegisterAllocation (
          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)( &reg_usage, instrs_in->arr[ii], mode64 );
 
       initHRegRemap(&remap);
 
@@ -1203,31 +1264,30 @@ HInstrArray* doRegisterAllocation (
 
       /* 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);
@@ -1242,8 +1302,9 @@ HInstrArray* doRegisterAllocation (
 
          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) {
@@ -1254,7 +1315,7 @@ HInstrArray* doRegisterAllocation (
                /* Update info about the insn, so it looks as if it had
                   been in this form all along. */
                instrs_in->arr[ii] = reloaded;
-               (*getRegUsage)( &reg_usage, instrs_in->arr[ii], mode64 );
+               (*getRegUsage)( &reg_usage_arr[ii], instrs_in->arr[ii], mode64 );
                if (debug_direct_reload && !reloaded) {
                   vex_printf("  -->  ");
                   ppInstr(reloaded, mode64);
@@ -1269,35 +1330,32 @@ HInstrArray* doRegisterAllocation (
 
       /* ------------ 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
@@ -1305,10 +1363,11 @@ HInstrArray* doRegisterAllocation (
             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
@@ -1326,22 +1385,22 @@ HInstrArray* doRegisterAllocation (
          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);
@@ -1350,10 +1409,10 @@ HInstrArray* doRegisterAllocation (
                /* 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 {
@@ -1375,11 +1434,13 @@ HInstrArray* doRegisterAllocation (
             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;
                }
@@ -1391,9 +1452,9 @@ HInstrArray* doRegisterAllocation (
             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.
@@ -1408,12 +1469,12 @@ HInstrArray* doRegisterAllocation (
          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
@@ -1423,7 +1484,7 @@ HInstrArray* doRegisterAllocation (
          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)
@@ -1439,17 +1500,17 @@ HInstrArray* doRegisterAllocation (
 
          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)
@@ -1459,19 +1520,19 @@ HInstrArray* doRegisterAllocation (
             /* 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:
@@ -1488,11 +1549,11 @@ HInstrArray* doRegisterAllocation (
       (*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 ------ */
 
@@ -1508,12 +1569,10 @@ HInstrArray* doRegisterAllocation (
          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;
@@ -1523,11 +1582,11 @@ HInstrArray* doRegisterAllocation (
          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 */
 
@@ -1538,9 +1597,6 @@ HInstrArray* doRegisterAllocation (
    /* 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);
 
index 75fd4149b499756c4a77853038ffb5cb0f441700..a6192f7c472bc84b7bed1b89068534c66fb11876 100644 (file)
 #include "host_generic_regs.h"
 
 
+/*---------------------------------------------------------*/
+/*--- Representing HOST REGISTERS                       ---*/
+/*---------------------------------------------------------*/
+
 void ppHRegClass ( HRegClass hrc )
 {
    switch (hrc) {
@@ -56,79 +60,172 @@ void ppHRegClass ( HRegClass 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*/
 }
 
 
@@ -151,12 +248,6 @@ void ppHRegRemap ( HRegRemap* map )
 }
 
 
-void initHRegRemap ( HRegRemap* map )
-{
-   map->n_used = 0;
-}
-
-
 void addToHRegRemap ( HRegRemap* map, HReg orig, HReg replacement )
 {
    Int i;
@@ -186,6 +277,7 @@ HReg lookupHRegRemap ( HRegRemap* map, HReg orig )
    vpanic("lookupHRegRemap: not found");
 }
 
+
 /*---------------------------------------------------------*/
 /*--- Abstract instructions                             ---*/
 /*---------------------------------------------------------*/
@@ -200,21 +292,18 @@ HInstrArray* newHInstrArray ( void )
    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);
 }
 
 
index e0af59eab68bea5ea8c8274ff01aeba42670a06c..b6de07b6909030bbf8a7a802224fc020c6eb5a44 100644 (file)
 
 /* 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
@@ -93,7 +106,9 @@ typedef
       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 { 
@@ -113,45 +128,128 @@ extern void ppHRegClass ( HRegClass );
 /* 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)          ---*/
 /*---------------------------------------------------------*/
@@ -161,24 +259,36 @@ typedef
    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
@@ -187,6 +297,7 @@ static inline void initHRegUsage ( HRegUsage* tab ) {
 */
 extern void addHRegUse ( HRegUsage*, HRegMode, HReg );
 
+extern Bool HRegUsage__contains ( const HRegUsage*, HReg );
 
 
 /*---------------------------------------------------------*/
@@ -211,10 +322,14 @@ typedef
    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                             ---*/
@@ -242,7 +357,21 @@ typedef
    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);
+   }
+}
 
 
 /*---------------------------------------------------------*/
@@ -319,10 +448,10 @@ HInstrArray* doRegisterAllocation (
    /* 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. */
index e960c5a2c27c5f274fab7a65daafce31deb42454..e7c59f89b5965b5a52958833c57ad872bc428677 100644 (file)
 /* 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;
@@ -86,22 +165,22 @@ void ppHRegMIPS(HReg reg, Bool mode64)
    /* 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;
@@ -113,503 +192,6 @@ void ppHRegMIPS(HReg reg, Bool mode64)
    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 ----------------------*/
 
@@ -914,13 +496,11 @@ MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am)
          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;
@@ -934,13 +514,11 @@ MIPSAMode *nextMIPSAModeInt(MIPSAMode * am)
          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;
@@ -2379,8 +1957,7 @@ Bool isMove_MIPSInstr(const MIPSInstr * i, HReg * src, HReg * dst)
          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;
@@ -2457,30 +2034,30 @@ void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
 
 /* --------- 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;
 }
index 787088b256d9005f7efc3189be3e146b693e24c1..500c97f2b09eba934de68be11bedb532b7fd9cc2 100644 (file)
 #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 */
@@ -726,7 +698,8 @@ extern void genSpill_MIPS ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2,
 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*,
index 09ac321ecebcc201b674643903068d98e6d86cc7..213c52a0ba73bab3971ffd00fb478b962462bcd4 100644 (file)
@@ -56,13 +56,13 @@ static Bool mode64 = False;
 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                                           ---*/
@@ -168,23 +168,24 @@ static void addInstr(ISelEnv * env, MIPSInstr * instr)
 
 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;
 }
@@ -4219,36 +4220,36 @@ HInstrArray *iselSB_MIPS ( const IRSB* bb,
          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]);
index 57e3b38f89c06215adbf8586ec3ba1907a893480..740403efc07c0cd3fc4836aa6a660166e2886092 100644 (file)
 
 /* --------- 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;
@@ -64,22 +166,22 @@ void ppHRegPPC ( HReg reg )
    /* 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;
@@ -89,188 +191,6 @@ void ppHRegPPC ( HReg reg )
 }
 
 
-#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 )
@@ -1520,7 +1440,7 @@ static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
 }
 
 static void ppMovReg ( HReg dst, HReg src ) {
-   if (hregNumber(dst) != hregNumber(src)) {
+   if (!sameHReg(dst, src)) {
       vex_printf("mr ");
       ppHRegPPC(dst);
       vex_printf(",");
@@ -1550,7 +1470,7 @@ void ppPPCInstr ( const PPCInstr* i, Bool mode64 )
       /* 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(",");
@@ -2531,7 +2451,7 @@ void getRegUsage_PPCInstr ( HRegUsage* u, const PPCInstr* i, Bool mode64 )
       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);
@@ -3127,32 +3047,32 @@ void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 
 /* --------- 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;
 }
@@ -3431,7 +3351,7 @@ static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
    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
@@ -3451,8 +3371,8 @@ static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
    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;
@@ -3821,17 +3741,17 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    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:
@@ -3902,10 +3822,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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);
 
@@ -4015,9 +3935,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    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) */
@@ -4038,7 +3958,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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;
 
@@ -4059,7 +3979,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
          }
          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)
@@ -4072,8 +3992,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -4101,9 +4021,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    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);
@@ -4138,9 +4058,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    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);
@@ -4310,7 +4230,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       /* 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
           );
 
@@ -4350,7 +4270,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       /* 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
           );
 
@@ -4408,7 +4328,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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 */
@@ -4427,7 +4347,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -4446,7 +4366,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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:
@@ -4480,13 +4400,13 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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;
@@ -4495,7 +4415,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    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;
 
@@ -4524,7 +4444,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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;
 
@@ -4537,7 +4457,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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:
@@ -4576,21 +4496,21 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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 );
@@ -4629,9 +4549,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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 );
@@ -4664,10 +4584,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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,
@@ -4693,7 +4613,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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;
@@ -4720,8 +4640,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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);
@@ -4729,16 +4649,16 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -4780,8 +4700,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -4801,16 +4721,16 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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);
@@ -4825,7 +4745,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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);
@@ -4840,8 +4760,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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) {
@@ -4849,7 +4769,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
          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)
@@ -4863,8 +4783,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -4897,9 +4817,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -4924,9 +4844,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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) {
 
@@ -4972,9 +4892,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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) {
 
@@ -5026,9 +4946,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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) {
 
@@ -5085,9 +5005,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -5116,8 +5036,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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
@@ -5128,9 +5048,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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
@@ -5144,8 +5064,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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) {
@@ -5158,9 +5078,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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) {
@@ -5174,9 +5094,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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:
@@ -5230,8 +5150,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -5252,36 +5172,36 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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)
@@ -5295,16 +5215,16 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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);
@@ -5322,7 +5242,7 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
          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 );
       }
@@ -5330,8 +5250,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5350,14 +5270,14 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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
@@ -5386,9 +5306,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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. */
@@ -5416,8 +5336,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5437,9 +5357,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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:                                                          
@@ -5462,9 +5382,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       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).                                                           
@@ -5494,10 +5414,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
       /* 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.
@@ -5537,10 +5457,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5577,8 +5497,8 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5591,10 +5511,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5622,9 +5542,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5643,10 +5563,10 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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;
@@ -5684,9 +5604,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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.
@@ -5713,9 +5633,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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:
@@ -5732,11 +5652,11 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
    }
 
    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.
@@ -5757,9 +5677,9 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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);
@@ -5775,11 +5695,11 @@ Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
 
    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
index fa5c591f80c91ee4e19e07b82545dfdb950794b8..8f41190c94255a1bf4a4d2e7f6d90cc3e54ca21d 100644 (file)
 #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 --------- */
@@ -1156,7 +1125,8 @@ extern void genSpill_PPC  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 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*,
index 71e3d395729f1f1b42fdf446372ca8d62a8c367e..a2b03983204d157de0c2c7063387f0f696a38d6c 100644 (file)
@@ -45,7 +45,7 @@
 #include "host_ppc_defs.h"
 
 /* GPR register class for ppc32/64 */
-#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
+#define HRcGPR(_mode64) ((_mode64) ? HRcInt64 : HRcInt32)
 
 
 /*---------------------------------------------------------*/
@@ -340,23 +340,23 @@ static void addInstr ( ISelEnv* env, PPCInstr* instr )
 }
 
 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;
 }
@@ -6190,29 +6190,46 @@ HInstrArray* iselSB_PPC ( const IRSB* bb,
       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");
index 22550c7257cae093e170cb68efbca311b6ad821d..75612323aead1cb02c91e398aa790114ea5a7b8a 100644 (file)
@@ -66,6 +66,32 @@ static UInt s390_tchain_load64_len(void);
 /*--- 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)
@@ -110,74 +136,11 @@ 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);
 }
 
 
@@ -212,7 +175,7 @@ s390_amode_b12(Int d, HReg b)
    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;
 }
@@ -229,7 +192,7 @@ s390_amode_b20(Int d, HReg b)
    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;
 }
@@ -421,13 +384,65 @@ ppHRegS390(HReg reg)
 /*--- 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. */
@@ -649,19 +664,18 @@ s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn)
          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
index 6a29aea585fcc85b4fbcb280f63ff30e79732703..9d732f975e420c9df7bed2a0e949f9270df3ac24 100644 (file)
@@ -40,6 +40,8 @@
 
 /* --------- 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);
@@ -738,7 +740,7 @@ Bool  isMove_S390Instr     ( const s390_insn *, HReg *, HReg * );
 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 *,
index 436e9e1ea39038adc63a69fe0939048430a613df..dee892aeb62fe4c929e7ce7f583b84d5e00a3629 100644 (file)
@@ -215,26 +215,31 @@ lookupIRTemp128(HReg *hi, HReg *lo, ISelEnv *env, IRTemp tmp)
 }
 
 
-/* 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++);
 }
 
 
@@ -242,7 +247,7 @@ newVRegF(ISelEnv *env)
 static __inline__ HReg
 make_gpr(UInt regno)
 {
-   return mkHReg(regno, HRcInt64, False /* virtual */ );
+   return s390_hreg_gpr(regno);
 }
 
 
@@ -250,7 +255,7 @@ make_gpr(UInt regno)
 static __inline__ HReg
 make_fpr(UInt regno)
 {
-   return mkHReg(regno, HRcFlt64, False /* virtual */ );
+   return s390_hreg_fpr(regno);
 }
 
 
@@ -4109,29 +4114,26 @@ iselSB_S390(const IRSB *bb, VexArch arch_host, const VexArchInfo *archinfo_host,
       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 */
index 1d6fec9d1090ed3365c53dab0b3aa7faeea96786..792381e4cef58bb66cf3b4a7991d43b9d79c4142 100644 (file)
 
 /* --------- 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;
@@ -57,17 +108,17 @@ void ppHRegX86 ( HReg reg )
    /* 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;
@@ -76,58 +127,6 @@ void ppHRegX86 ( HReg reg )
    }
 }
 
-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. --------- */
 
@@ -1832,52 +1831,48 @@ X86Instr* directReload_X86( X86Instr* i, HReg vreg, Short spill_off )
 
 /* --------- 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 )
@@ -1921,29 +1916,29 @@ static Bool fits8bits ( 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;
@@ -1955,16 +1950,16 @@ static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
    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;
       }
@@ -1976,14 +1971,42 @@ static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
    /*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 )
@@ -2049,7 +2072,6 @@ static UChar* do_fop1_st ( UChar* p, X86FpOp op )
 /* 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;
@@ -2059,9 +2081,8 @@ static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
       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];
@@ -2116,11 +2137,6 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
    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) {
@@ -2130,7 +2146,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       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:
@@ -2207,11 +2223,11 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
             } 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;
@@ -2241,7 +2257,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
                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: 
@@ -2266,12 +2282,12 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
             }
@@ -2290,10 +2306,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       }
       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;
@@ -2302,13 +2318,13 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
       }
@@ -2316,12 +2332,12 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
    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;
@@ -2336,12 +2352,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       *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;
@@ -2353,12 +2367,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       *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;
@@ -2384,14 +2396,14 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       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;
@@ -2411,10 +2423,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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
@@ -2455,7 +2467,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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 --- */
@@ -2668,26 +2680,26 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
 
@@ -2754,7 +2766,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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:
@@ -2770,7 +2782,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       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);
@@ -2785,22 +2797,13 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -2821,9 +2824,9 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          --> 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:
@@ -2833,12 +2836,12 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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) {
@@ -2846,11 +2849,11 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          /* 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
@@ -2861,9 +2864,9 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -2871,7 +2874,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -2881,10 +2884,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          --> 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:
@@ -2896,39 +2899,39 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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)");
@@ -2950,8 +2953,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          }
          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.
@@ -2964,9 +2967,9 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
             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;
@@ -2974,7 +2977,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
    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) */
@@ -2984,7 +2987,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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:
@@ -2995,8 +2998,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
 
       /* 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);
@@ -3004,7 +3007,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
 
    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:
@@ -3021,10 +3024,10 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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;
@@ -3042,7 +3045,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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;
@@ -3054,7 +3057,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
    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:
@@ -3063,8 +3066,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       *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:
@@ -3086,8 +3088,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3112,8 +3114,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3138,8 +3140,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3164,8 +3166,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3229,8 +3231,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
 
@@ -3243,8 +3245,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* 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);
@@ -3254,8 +3256,8 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       *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;
 
@@ -3275,11 +3277,11 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
          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;
@@ -3288,7 +3290,7 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
       /* --- 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);
@@ -3328,8 +3330,6 @@ Int emit_X86Instr ( /*MB_MOD*/Bool* is_profInc,
   done:
    vassert(p - &buf[0] <= 32);
    return p - &buf[0];
-
-#  undef fake
 }
 
 
index f51d5b07c36aa111824aa74a0d4f0753bf3a8310..f1f737f34366e4623065b28958f21ae2576a44c6 100644 (file)
    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. --------- */
@@ -728,9 +731,10 @@ extern void genSpill_X86  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
 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*,
index 8eeb3bf6b268bf86c1b010ce8b158d9c72010cb6..c51b6f7cc18ad5de8108af3fd28e867bc4d6e0f1 100644 (file)
@@ -217,21 +217,21 @@ static void addInstr ( ISelEnv* env, X86Instr* instr )
 
 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;
 }
@@ -4467,12 +4467,12 @@ HInstrArray* iselSB_X86 ( const IRSB* bb,
          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");
       }
index c0272a59ba5c0af6e5bdf92f2c2746b024b23539..e202dbb68f84612a525b078be36fc5e728f85aa6 100644 (file)
@@ -184,6 +184,13 @@ void LibVEX_Init (
       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. */
@@ -211,8 +218,6 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
    /* 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 );
@@ -231,6 +236,8 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
    IRExpr*      (*specHelper)   ( const HChar*, IRExpr**, IRStmt**, Int );
    Bool         (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
 
+   const RRegUniverse* rRegUniv = NULL;
+
    DisOneInstrFn disInstrFn;
 
    VexGuestLayout* guest_layout;
@@ -247,8 +254,6 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
    Addr            max_ga;
 
    guest_layout           = NULL;
-   available_real_regs    = NULL;
-   n_available_real_regs  = 0;
    isMove                 = NULL;
    getRegUsage            = NULL;
    mapRegs                = NULL;
@@ -298,8 +303,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
 
       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;
@@ -310,14 +314,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -327,14 +330,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -344,14 +346,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -361,17 +362,16 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -382,14 +382,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -399,14 +398,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -416,14 +414,13 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -433,15 +430,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -451,7 +447,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          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;
@@ -877,8 +873,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
    }
 
    /* Register allocate. */
-   rcode = doRegisterAllocation ( vcode, available_real_regs,
-                                  n_available_real_regs,
+   rcode = doRegisterAllocation ( vcode, rRegUniv,
                                   isMove, getRegUsage, mapRegs, 
                                   genSpill, genReload, directReload, 
                                   guest_sizeB,