Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                                host_tilegx_defs.c ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7   This file is part of Valgrind, a dynamic binary instrumentation
      8   framework.
      9 
     10   Copyright (C) 2010-2015 Tilera Corp.
     11 
     12   This program is free software; you can redistribute it and/or
     13   modify it under the terms of the GNU General Public License as
     14   published by the Free Software Foundation; either version 2 of the
     15   License, or (at your option) any later version.
     16 
     17   This program is distributed in the hope that it will be useful, but
     18   WITHOUT ANY WARRANTY; without even the implied warranty of
     19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20   General Public License for more details.
     21 
     22   You should have received a copy of the GNU General Public License
     23   along with this program; if not, write to the Free Software
     24   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     25   02111-1307, USA.
     26 
     27   The GNU General Public License is contained in the file COPYING.
     28 */
     29 
     30 /* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
     31 
     32 #include "libvex_basictypes.h"
     33 #include "libvex.h"
     34 #include "libvex_trc_values.h"
     35 
     36 #include "main_util.h"
     37 #include "host_generic_regs.h"
     38 #include "host_tilegx_defs.h"
     39 #include "tilegx_disasm.h"
     40 
     41 /* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
     42 
     43 /* Register number for guest state pointer in host code, r50 */
     44 #define GuestSP     ( 50)
     45 /* CONTEXT_EX0 offset */
     46 #define OFFSET_EX0  (576)
     47 /* CONTEXT_EX1 offset */
     48 #define OFFSET_EX1  (584)
     49 /* COND offset */
     50 #define OFFSET_COND (608)
     51 /* PC offset */
     52 #define OFFSET_PC   (512)
     53 
     54 /* guest_COND offset. */
     55 #define COND_OFFSET() OFFSET_COND
     56 
     57 /*---------------- Registers ----------------*/
     58 
     59 void ppHRegTILEGX ( HReg reg )
     60 {
     61   Int r;
     62   static const HChar *ireg_names[64] = {
     63     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",
     64     "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
     65     "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29",
     66     "r30", "r31", "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
     67     "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", "r48", "r49",
     68     "r50", "r51", "r52", "r53", "r54", "r55",
     69     "sn",  "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero"
     70   };
     71 
     72   /* Be generic for all virtual regs. */
     73   if (hregIsVirtual(reg)) {
     74     ppHReg(reg);
     75     return;
     76   }
     77 
     78   /* But specific for real regs. */
     79   vassert(hregClass(reg) == HRcInt32 || hregClass(reg) == HRcInt64 ||
     80           hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64);
     81 
     82   /* But specific for real regs. */
     83   switch (hregClass(reg)) {
     84   case HRcInt32:
     85   case HRcInt64:
     86     r = hregEncoding(reg);
     87     vassert(r >= 0 && r < 64);
     88     vex_printf("%s", ireg_names[r]);
     89     return;
     90   case HRcFlt32:
     91     r = hregEncoding(reg);
     92     vassert(r >= 0 && r < 64);
     93     vex_printf("%s", ireg_names[r]);
     94     return;
     95   case HRcFlt64:
     96     r = hregEncoding(reg);
     97     vassert(r >= 0 && r < 64);
     98     vex_printf("%s", ireg_names[r]);
     99     return;
    100   default:
    101     vpanic("ppHRegTILEGX");
    102   }
    103 
    104   return;
    105 }
    106 
    107 static const HChar* tilegxUnaryOp [] =
    108   {
    109     "clz ",
    110     "ctz ",
    111     "nop "
    112   };
    113 
    114 static const HChar* tilegxAluOp [] =
    115   {  "Alu_invalid",
    116      "Add ",
    117      "Sub ",
    118      "And ",
    119      "Or  ",
    120      "Nor ",
    121      "Xor "
    122   };
    123 
    124 static const HChar* tilegxShftOp [] =
    125   {
    126     "Shft_invalid",
    127     "Sll    ",
    128     "Srl    ",
    129     "Sra    ",
    130     "Sll8x8 ",
    131     "Srl8x8 ",
    132   };
    133 
    134 static const HChar* tilegxBfOp [] =
    135   {
    136     "BfExts ",
    137     "BfEtxu ",
    138     "BfIns  "
    139   };
    140 
    141 
    142 static const HChar* tilegxAcasOp [] =
    143   {
    144     "CmpExch    ",
    145     "Exch       ",
    146     "FetchAnd   ",
    147     "FetchAdd   ",
    148     "FetchAddgez",
    149     "FetchOr    "
    150   };
    151 
    152 static const HChar* tilegxInstrTag [] =
    153   {
    154     "Imm      ",
    155     "ALU      ",
    156     "Shift    ",
    157     "Unary    ",
    158     "Cmp      ",
    159     "CmpI     ",
    160     "Mul      ",
    161     "Call     ",
    162     "XDirect  ",
    163     "XIndir   ",
    164     "XAssisted",
    165     "EvCheck  ",
    166     "ProfInc  ",
    167     "RdWrLR   ",
    168     "Load     ",
    169     "Store    ",
    170     "MovCond  ",
    171     "BitField ",
    172     "ACAS     "
    173   };
    174 
    175 /* -------- Pretty Print instructions ------------- */
    176 static void ppLoadImm ( HReg dst, ULong imm )
    177 {
    178   vex_printf("li ");
    179   ppHRegTILEGX(dst);
    180   vex_printf(",0x%016lx", (unsigned long)imm);
    181 }
    182 
    183 void ppTILEGXInstr ( const TILEGXInstr * instr )
    184 {
    185   vex_printf("%s ", tilegxInstrTag[instr->tag]);
    186   switch (instr->tag) {
    187   case GXin_LI:  {
    188     ppHRegTILEGX(instr->GXin.LI.dst);
    189     vex_printf(",0x%016llx", instr->GXin.LI.imm);
    190   }
    191     break;
    192 
    193   case GXin_Alu: {
    194     HReg r_srcL = instr->GXin.Alu.srcL;
    195     TILEGXRH *rh_srcR = instr->GXin.Alu.srcR;
    196     /* generic */
    197     vex_printf("%s ", tilegxAluOp[instr->GXin.Alu.op]);
    198     ppHRegTILEGX(instr->GXin.Alu.dst);
    199     vex_printf(",");
    200     ppHRegTILEGX(r_srcL);
    201     vex_printf(",");
    202     ppTILEGXRH(rh_srcR);
    203   }
    204     break;
    205 
    206   case GXin_Shft: {
    207     HReg r_srcL = instr->GXin.Shft.srcL;
    208     TILEGXRH *rh_srcR = instr->GXin.Shft.srcR;
    209     vex_printf("%s ", tilegxShftOp[instr->GXin.Shft.op]);
    210     ppHRegTILEGX(instr->GXin.Shft.dst);
    211     vex_printf(",");
    212     ppHRegTILEGX(r_srcL);
    213     vex_printf(",");
    214     ppTILEGXRH(rh_srcR);
    215   }
    216     break;
    217 
    218   case GXin_Unary: {
    219     vex_printf("%s ", tilegxUnaryOp[instr->GXin.Unary.op]);
    220     ppHRegTILEGX(instr->GXin.Unary.dst);
    221     vex_printf(",");
    222     ppHRegTILEGX(instr->GXin.Unary.src);
    223   }
    224     break;
    225 
    226   case GXin_Cmp: {
    227     ppHRegTILEGX(instr->GXin.Cmp.dst);
    228     vex_printf(" = %s ( ", showTILEGXCondCode(instr->GXin.Cmp.cond));
    229     ppHRegTILEGX(instr->GXin.Cmp.srcL);
    230     vex_printf(", ");
    231     ppHRegTILEGX(instr->GXin.Cmp.srcR);
    232     vex_printf(" )");
    233   }
    234     break;
    235 
    236   case GXin_CmpI: {
    237     ppHRegTILEGX(instr->GXin.CmpI.dst);
    238     vex_printf(" = %s ( ", showTILEGXCondCode(instr->GXin.CmpI.cond));
    239     ppHRegTILEGX(instr->GXin.CmpI.srcL);
    240     vex_printf(", ");
    241     ppTILEGXRH(instr->GXin.CmpI.srcR);
    242     vex_printf(" )");
    243   }
    244     break;
    245 
    246   case GXin_Mul: {
    247     if (instr->GXin.Mul.widening == False) {
    248       vex_printf("mul ");
    249       ppHRegTILEGX(instr->GXin.Mul.dst);
    250       vex_printf(", ");
    251       ppHRegTILEGX(instr->GXin.Mul.srcL);
    252       vex_printf(", ");
    253       ppHRegTILEGX(instr->GXin.Mul.srcR);
    254 
    255     } else {
    256       vex_printf("%s ", instr->GXin.Mul.syned ? "mull32s" : "mull32u");
    257       ppHRegTILEGX(instr->GXin.Mul.dst);
    258       vex_printf(", ");
    259       ppHRegTILEGX(instr->GXin.Mul.srcL);
    260       vex_printf(", ");
    261       ppHRegTILEGX(instr->GXin.Mul.srcR);
    262     }
    263   }
    264     break;
    265 
    266   case GXin_Call: {
    267     Int n;
    268     if (instr->GXin.Call.cond != TILEGXcc_AL) {
    269       vex_printf("if (%s (", showTILEGXCondCode(instr->GXin.Call.cond));
    270       ppHRegTILEGX(instr->GXin.Call.src);
    271       vex_printf(",zero))");
    272     }
    273     else
    274       vex_printf("(always) ");
    275 
    276     vex_printf("{ ");
    277     ppLoadImm(hregTILEGX_R11(), instr->GXin.Call.target);
    278 
    279     vex_printf(" ; [");
    280     for (n = 0; n < 56; n++) {
    281       if (instr->GXin.Call.argiregs & (1ULL << n)) {
    282         vex_printf("r%d", n);
    283         if ((instr->GXin.Call.argiregs >> n) > 1)
    284           vex_printf(",");
    285       }
    286     }
    287     vex_printf("] }");
    288   }
    289     break;
    290 
    291   case GXin_XDirect:
    292     vex_printf("(xDirect) ");
    293     vex_printf("if (guest_COND.%s) { ",
    294                showTILEGXCondCode(instr->GXin.XDirect.cond));
    295     vex_printf("move r11, 0x%x,", (UInt)instr->GXin.XDirect.dstGA);
    296     vex_printf("; st r11, ");
    297     ppTILEGXAMode(instr->GXin.XDirect.amPC);
    298     vex_printf("; move r11, $disp_cp_chain_me_to_%sEP; jalr r11; nop}",
    299                instr->GXin.XDirect.toFastEP ? "fast" : "slow");
    300     return;
    301   case GXin_XIndir:
    302     vex_printf("(xIndir) ");
    303     vex_printf("if (guest_COND.%s) { st ",
    304                showTILEGXCondCode(instr->GXin.XIndir.cond));
    305     ppHRegTILEGX(instr->GXin.XIndir.dstGA);
    306     vex_printf(", ");
    307     ppTILEGXAMode(instr->GXin.XIndir.amPC);
    308     vex_printf("; move r11, $disp_indir; jalr r11; nop}");
    309     return;
    310   case GXin_XAssisted:
    311     vex_printf("(xAssisted) ");
    312     vex_printf("if (guest_COND.%s) { ",
    313                showTILEGXCondCode(instr->GXin.XAssisted.cond));
    314     vex_printf("st ");
    315     ppHRegTILEGX(instr->GXin.XAssisted.dstGA);
    316     vex_printf(", ");
    317     ppTILEGXAMode(instr->GXin.XAssisted.amPC);
    318     vex_printf("; move r50, $IRJumpKind_to_TRCVAL(%d)",
    319                (Int)instr->GXin.XAssisted.jk);
    320     vex_printf("; move r11, $disp_assisted; jalr r11; nop; }");
    321     return;
    322 
    323   case GXin_EvCheck:
    324     vex_printf("(evCheck) ld r11, ");
    325     ppTILEGXAMode(instr->GXin.EvCheck.amCounter);
    326     vex_printf("; addli r11, r11, -1");
    327     vex_printf("; st r11, ");
    328     ppTILEGXAMode(instr->GXin.EvCheck.amCounter);
    329     vex_printf("; bgez r11, nofail; jalr *");
    330     ppTILEGXAMode(instr->GXin.EvCheck.amFailAddr);
    331     vex_printf("; nofail:");
    332     return;
    333   case GXin_ProfInc:
    334     vex_printf("(profInc) move r11, ($NotKnownYet); "
    335                "ld r8, r11; "
    336                "addi r8, r8, 1; "
    337                "st r11, r8; " );
    338     return;
    339   case GXin_Load: {
    340     UChar sz = instr->GXin.Load.sz;
    341     UChar c_sz = sz == 1 ? '1' : sz == 2 ? '2' : sz == 4 ? '4' : '8';
    342     vex_printf("ld%c ", c_sz);
    343     ppHRegTILEGX(instr->GXin.Load.dst);
    344     vex_printf(",");
    345     ppTILEGXAMode(instr->GXin.Load.src);
    346   }
    347     break;
    348 
    349   case GXin_Store: {
    350     UChar sz = instr->GXin.Store.sz;
    351     UChar c_sz = sz == 1 ? '1' : sz == 2 ? '2' : sz == 4 ? '4' : '8';
    352     vex_printf("st%c ", c_sz);
    353     ppTILEGXAMode(instr->GXin.Store.dst);
    354     vex_printf(",");
    355     ppHRegTILEGX(instr->GXin.Store.src);
    356   }
    357     break;
    358 
    359   case GXin_MovCond: {
    360     ppHRegTILEGX(instr->GXin.MovCond.dst);
    361     vex_printf("=");
    362     showTILEGXCondCode(instr->GXin.MovCond.cond);
    363     vex_printf("?");
    364     ppHRegTILEGX(instr->GXin.MovCond.srcL);
    365     vex_printf(":");
    366     ppTILEGXRH(instr->GXin.MovCond.srcR);
    367   }
    368     break;
    369 
    370   case GXin_Acas: {
    371     vex_printf("%s ",  tilegxAcasOp[instr->GXin.Acas.op]);
    372     ppHRegTILEGX(instr->GXin.Acas.old);
    373     vex_printf(",");
    374     if (instr->GXin.Acas.op == GXacas_CMPEXCH) {
    375       ppHRegTILEGX(instr->GXin.Acas.exp);
    376       vex_printf(",");
    377     }
    378     ppHRegTILEGX(instr->GXin.Acas.new);
    379   }
    380     break;
    381 
    382   case GXin_Bf: {
    383     vex_printf("%s ",  tilegxBfOp[instr->GXin.Bf.op]);
    384     ppHRegTILEGX(instr->GXin.Bf.dst);
    385     vex_printf(",");
    386     ppHRegTILEGX(instr->GXin.Bf.src);
    387     vex_printf(",");
    388     vex_printf("%d,%d", (Int)instr->GXin.Bf.Start, (Int)instr->GXin.Bf.End);
    389   }
    390     break;
    391 
    392   default:
    393     vassert(0);
    394   }
    395 }
    396 
    397 
    398 const RRegUniverse* getRRegUniverse_TILEGX ( void )
    399 {
    400   /* The 'universe' is constant and BIG, do it statically. */
    401   static RRegUniverse rRegUniverse_TILEGX;
    402   static UInt         rRegUniverse_TILEGX_initted = False;
    403 
    404   /* Get a pointer of the 'universe' */
    405   RRegUniverse* ru = &rRegUniverse_TILEGX;
    406 
    407   if (LIKELY(rRegUniverse_TILEGX_initted))
    408     return ru;
    409 
    410   RRegUniverse__init(ru);
    411 
    412   /* Callee saves ones are listed first, since we prefer them
    413      if they're available */
    414 
    415   ru->regs[ru->size++] = hregTILEGX_R30();
    416   ru->regs[ru->size++] = hregTILEGX_R31();
    417   ru->regs[ru->size++] = hregTILEGX_R32();
    418   ru->regs[ru->size++] = hregTILEGX_R33();
    419   ru->regs[ru->size++] = hregTILEGX_R34();
    420   ru->regs[ru->size++] = hregTILEGX_R35();
    421   ru->regs[ru->size++] = hregTILEGX_R36();
    422   ru->regs[ru->size++] = hregTILEGX_R37();
    423   ru->regs[ru->size++] = hregTILEGX_R38();
    424   ru->regs[ru->size++] = hregTILEGX_R39();
    425 
    426   ru->regs[ru->size++] = hregTILEGX_R40();
    427   ru->regs[ru->size++] = hregTILEGX_R41();
    428   ru->regs[ru->size++] = hregTILEGX_R42();
    429   ru->regs[ru->size++] = hregTILEGX_R43();
    430   ru->regs[ru->size++] = hregTILEGX_R44();
    431   ru->regs[ru->size++] = hregTILEGX_R45();
    432   ru->regs[ru->size++] = hregTILEGX_R46();
    433   ru->regs[ru->size++] = hregTILEGX_R47();
    434   ru->regs[ru->size++] = hregTILEGX_R48();
    435   ru->regs[ru->size++] = hregTILEGX_R49();
    436 
    437   /* GPR 50 is reserved as Guest state */
    438   /* GPR 51 is reserved register, mainly used to do memory
    439      load and store since TileGx has no pre-displacement
    440      addressing mode */
    441 
    442   ru->regs[ru->size++] = hregTILEGX_R10();
    443 
    444   /* GPR 11 is reserved as next guest address */
    445 
    446   ru->regs[ru->size++] = hregTILEGX_R13();
    447   ru->regs[ru->size++] = hregTILEGX_R14();
    448   ru->regs[ru->size++] = hregTILEGX_R15();
    449   ru->regs[ru->size++] = hregTILEGX_R16();
    450   ru->regs[ru->size++] = hregTILEGX_R17();
    451   ru->regs[ru->size++] = hregTILEGX_R18();
    452   ru->regs[ru->size++] = hregTILEGX_R19();
    453   ru->regs[ru->size++] = hregTILEGX_R20();
    454   ru->regs[ru->size++] = hregTILEGX_R21();
    455   ru->regs[ru->size++] = hregTILEGX_R22();
    456   ru->regs[ru->size++] = hregTILEGX_R23();
    457   ru->regs[ru->size++] = hregTILEGX_R24();
    458   ru->regs[ru->size++] = hregTILEGX_R25();
    459   ru->regs[ru->size++] = hregTILEGX_R26();
    460   ru->regs[ru->size++] = hregTILEGX_R27();
    461   ru->regs[ru->size++] = hregTILEGX_R28();
    462   ru->regs[ru->size++] = hregTILEGX_R29();
    463 
    464   ru->allocable = ru->size;
    465 
    466   /* And other unallocable registers. */
    467   ru->regs[ru->size++] = hregTILEGX_R0();
    468   ru->regs[ru->size++] = hregTILEGX_R1();
    469   ru->regs[ru->size++] = hregTILEGX_R2();
    470   ru->regs[ru->size++] = hregTILEGX_R3();
    471   ru->regs[ru->size++] = hregTILEGX_R4();
    472   ru->regs[ru->size++] = hregTILEGX_R5();
    473   ru->regs[ru->size++] = hregTILEGX_R6();
    474   ru->regs[ru->size++] = hregTILEGX_R7();
    475   ru->regs[ru->size++] = hregTILEGX_R8();
    476   ru->regs[ru->size++] = hregTILEGX_R9();
    477   ru->regs[ru->size++] = hregTILEGX_R11();
    478   ru->regs[ru->size++] = hregTILEGX_R12();
    479   ru->regs[ru->size++] = hregTILEGX_R50();
    480   ru->regs[ru->size++] = hregTILEGX_R51();
    481   ru->regs[ru->size++] = hregTILEGX_R52();
    482   ru->regs[ru->size++] = hregTILEGX_R53();
    483   ru->regs[ru->size++] = hregTILEGX_R54();
    484   ru->regs[ru->size++] = hregTILEGX_R55();
    485   ru->regs[ru->size++] = hregTILEGX_R63();
    486 
    487   rRegUniverse_TILEGX_initted = True;
    488 
    489   RRegUniverse__check_is_sane(ru);
    490 
    491   return ru;
    492 }
    493 
    494 /*----------------- Condition Codes ----------------------*/
    495 
    496 const HChar *showTILEGXCondCode ( TILEGXCondCode cond )
    497 {
    498   switch (cond) {
    499   case TILEGXcc_EQ:
    500     return "e"; /* equal */
    501   case TILEGXcc_EQ8x8:
    502     return "e8x8"; /* equal */
    503 
    504   case TILEGXcc_NE:
    505     return "ne";   /* not equal */
    506   case TILEGXcc_NE8x8:
    507     return "ne8x8";   /* not equal */
    508 
    509   case TILEGXcc_HS:
    510     return "hs";   /* >=u (higher or same) */
    511   case TILEGXcc_LO:
    512     return "lo";   /* <u  (lower) */
    513 
    514   case TILEGXcc_MI:
    515     return "mi";   /* minus (negative) */
    516   case TILEGXcc_PL:
    517     return "pl";   /* plus (zero or +ve) */
    518 
    519   case TILEGXcc_VS:
    520     return "vs";   /* overflow */
    521   case TILEGXcc_VC:
    522     return "vc";   /* no overflow */
    523 
    524   case TILEGXcc_HI:
    525     return "hi";   /* >u   (higher) */
    526   case TILEGXcc_LS:
    527     return "ls";   /* <=u  (lower or same) */
    528 
    529   case TILEGXcc_GE:
    530     return "ge";   /* >=s (signed greater or equal) */
    531   case TILEGXcc_LT:
    532     return "lt";   /* <s  (signed less than) */
    533 
    534   case TILEGXcc_GT:
    535     return "gt";   /* >s  (signed greater) */
    536   case TILEGXcc_LE:
    537     return "le";   /* <=s (signed less or equal) */
    538 
    539   case TILEGXcc_AL:
    540     return "al";   /* always (unconditional) */
    541   case TILEGXcc_NV:
    542     return "nv";   /* never (unconditional): */
    543   case TILEGXcc_EZ:
    544     return "ez"; /* equal 0 */
    545   case TILEGXcc_NZ:
    546     return "nz"; /* not equal 0 */
    547 
    548   default:
    549     vpanic("showTILEGXCondCode");
    550   }
    551 }
    552 
    553 
    554 /* --------- TILEGXAMode: memory address expressions. --------- */
    555 
    556 TILEGXAMode *TILEGXAMode_IR ( Int idx, HReg base )
    557 {
    558   TILEGXAMode *am = LibVEX_Alloc(sizeof(TILEGXAMode));
    559   am->tag = GXam_IR;
    560   am->GXam.IR.base = base;
    561   am->GXam.IR.index = idx;
    562 
    563   return am;
    564 }
    565 
    566 TILEGXAMode *nextTILEGXAModeInt ( TILEGXAMode * am )
    567 {
    568   if (am->tag == GXam_IR)
    569     return TILEGXAMode_IR(am->GXam.IR.index + 4, am->GXam.IR.base);
    570 
    571   vpanic("dopyTILEGXAMode");
    572 }
    573 
    574 void ppTILEGXAMode ( const TILEGXAMode * am )
    575 {
    576   if (am->tag == GXam_IR)
    577   {
    578     if (am->GXam.IR.index == 0)
    579       vex_printf("(");
    580     else
    581       vex_printf("%d(", (Int) am->GXam.IR.index);
    582     ppHRegTILEGX(am->GXam.IR.base);
    583     vex_printf(")");
    584     return;
    585   }
    586   vpanic("ppTILEGXAMode");
    587 }
    588 
    589 static void addRegUsage_TILEGXAMode ( HRegUsage * u, TILEGXAMode * am )
    590 {
    591   if (am->tag == GXam_IR)
    592   {
    593     addHRegUse(u, HRmRead, am->GXam.IR.base);
    594     return;
    595   }
    596 
    597   vpanic("addRegUsage_TILEGXAMode");
    598 }
    599 
    600 static void mapRegs_TILEGXAMode ( HRegRemap * m, TILEGXAMode * am )
    601 {
    602   if (am->tag == GXam_IR)
    603   {
    604     am->GXam.IR.base = lookupHRegRemap(m, am->GXam.IR.base);
    605     return;
    606   }
    607 
    608   vpanic("mapRegs_TILEGXAMode");
    609 }
    610 
    611 /* --------- Operand, which can be a reg or a u16/s16. --------- */
    612 
    613 TILEGXRH *TILEGXRH_Imm ( Bool syned, UShort imm16 )
    614 {
    615   TILEGXRH *op = LibVEX_Alloc(sizeof(TILEGXRH));
    616   op->tag = GXrh_Imm;
    617   op->GXrh.Imm.syned = syned;
    618   op->GXrh.Imm.imm16 = imm16;
    619   /* If this is a signed value, ensure it's not -32768, so that we
    620      are guaranteed always to be able to negate if needed. */
    621   if (syned)
    622     vassert(imm16 != 0x8000);
    623   vassert(syned == True || syned == False);
    624   return op;
    625 }
    626 
    627 TILEGXRH *TILEGXRH_Reg ( HReg reg )
    628 {
    629   TILEGXRH *op = LibVEX_Alloc(sizeof(TILEGXRH));
    630   op->tag = GXrh_Reg;
    631   op->GXrh.Reg.reg = reg;
    632   return op;
    633 }
    634 
    635 void ppTILEGXRH ( const TILEGXRH * op )
    636 {
    637   TILEGXRHTag tag = op->tag;
    638   switch (tag) {
    639   case GXrh_Imm:
    640     if (op->GXrh.Imm.syned)
    641       vex_printf("%d", (Int) (Short) op->GXrh.Imm.imm16);
    642     else
    643       vex_printf("%u", (UInt) (UShort) op->GXrh.Imm.imm16);
    644     return;
    645   case GXrh_Reg:
    646     ppHRegTILEGX(op->GXrh.Reg.reg);
    647     return;
    648   default:
    649     vpanic("ppTILEGXRH");
    650   }
    651 }
    652 
    653 /* An TILEGXRH can only be used in a "read" context (what would it mean
    654    to write or modify a literal?) and so we enumerate its registers
    655    accordingly. */
    656 static void addRegUsage_TILEGXRH ( HRegUsage * u, TILEGXRH * op )
    657 {
    658   switch (op->tag) {
    659   case GXrh_Imm:
    660     return;
    661   case GXrh_Reg:
    662     addHRegUse(u, HRmRead, op->GXrh.Reg.reg);
    663     return;
    664   default:
    665     vpanic("addRegUsage_TILEGXRH");
    666   }
    667 }
    668 
    669 static void mapRegs_TILEGXRH ( HRegRemap * m, TILEGXRH * op )
    670 {
    671   switch (op->tag) {
    672   case GXrh_Imm:
    673     return;
    674   case GXrh_Reg:
    675     op->GXrh.Reg.reg = lookupHRegRemap(m, op->GXrh.Reg.reg);
    676     return;
    677   default:
    678     vpanic("mapRegs_TILEGXRH");
    679   }
    680 }
    681 
    682 TILEGXInstr *TILEGXInstr_LI ( HReg dst, ULong imm )
    683 {
    684   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    685   i->tag = GXin_LI;
    686   i->GXin.LI.dst = dst;
    687   i->GXin.LI.imm = imm;
    688   return i;
    689 }
    690 
    691 TILEGXInstr *TILEGXInstr_Alu ( TILEGXAluOp op, HReg dst, HReg srcL,
    692                                TILEGXRH * srcR )
    693 {
    694   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    695   i->tag = GXin_Alu;
    696   i->GXin.Alu.op = op;
    697   i->GXin.Alu.dst = dst;
    698   i->GXin.Alu.srcL = srcL;
    699   i->GXin.Alu.srcR = srcR;
    700   return i;
    701 }
    702 
    703 TILEGXInstr *TILEGXInstr_Shft ( TILEGXShftOp op, Bool sz32, HReg dst, HReg srcL,
    704                                 TILEGXRH * srcR )
    705 {
    706   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    707   i->tag = GXin_Shft;
    708   i->GXin.Shft.op = op;
    709   i->GXin.Shft.sz32 = sz32;
    710   i->GXin.Shft.dst = dst;
    711   i->GXin.Shft.srcL = srcL;
    712   i->GXin.Shft.srcR = srcR;
    713   return i;
    714 }
    715 
    716 TILEGXInstr *TILEGXInstr_Unary ( TILEGXUnaryOp op, HReg dst, HReg src )
    717 {
    718   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    719   i->tag = GXin_Unary;
    720   i->GXin.Unary.op = op;
    721   i->GXin.Unary.dst = dst;
    722   i->GXin.Unary.src = src;
    723   return i;
    724 }
    725 
    726 TILEGXInstr *TILEGXInstr_Cmp ( Bool syned, Bool sz32, HReg dst,
    727                                HReg srcL, HReg srcR, TILEGXCondCode cond )
    728 {
    729   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    730   i->tag = GXin_Cmp;
    731   i->GXin.Cmp.syned = syned;
    732   i->GXin.Cmp.sz32 = sz32;
    733   i->GXin.Cmp.dst = dst;
    734   i->GXin.Cmp.srcL = srcL;
    735   i->GXin.Cmp.srcR = srcR;
    736   i->GXin.Cmp.cond = cond;
    737   return i;
    738 }
    739 
    740 TILEGXInstr *TILEGXInstr_CmpI ( Bool syned, Bool sz32, HReg dst,
    741                                 HReg srcL, TILEGXRH * srcR,
    742                                 TILEGXCondCode cond )
    743 {
    744   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    745   i->tag = GXin_CmpI;
    746   i->GXin.CmpI.syned = syned;
    747   i->GXin.CmpI.sz32 = sz32;
    748   i->GXin.CmpI.dst = dst;
    749   i->GXin.CmpI.srcL = srcL;
    750   i->GXin.CmpI.srcR = srcR;
    751   i->GXin.CmpI.cond = cond;
    752   return i;
    753 }
    754 
    755 TILEGXInstr *TILEGXInstr_Bf ( TILEGXBfOp op, HReg dst, HReg src,
    756                               UInt Start, UInt End )
    757 {
    758   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    759   i->tag = GXin_Bf;
    760   i->GXin.Bf.op = op;
    761   i->GXin.Bf.dst = dst;
    762   i->GXin.Bf.src = src;
    763   i->GXin.Bf.Start = Start;
    764   i->GXin.Bf.End = End;
    765   return i;
    766 }
    767 
    768 TILEGXInstr *TILEGXInstr_Acas ( TILEGXAcasOp op, HReg old,
    769                                 HReg addr, HReg exp, HReg new, UInt sz )
    770 {
    771   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    772   i->tag = GXin_Acas;
    773   i->GXin.Acas.op = op;
    774   i->GXin.Acas.old = old;
    775   i->GXin.Acas.addr = addr;
    776   i->GXin.Acas.exp = exp;
    777   i->GXin.Acas.new = new;
    778   i->GXin.Acas.sz = sz;
    779   return i;
    780 }
    781 
    782 /* multiply */
    783 TILEGXInstr *TILEGXInstr_Mul ( Bool syned, Bool wid, Bool sz32,
    784                                HReg dst, HReg srcL,
    785                                HReg srcR )
    786 {
    787   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    788   i->tag = GXin_Mul;
    789   i->GXin.Mul.syned = syned;
    790   i->GXin.Mul.widening = wid; /* widen=True else False */
    791   i->GXin.Mul.sz32 = sz32;    /* True = 32 bits */
    792   i->GXin.Mul.dst = dst;
    793   i->GXin.Mul.srcL = srcL;
    794   i->GXin.Mul.srcR = srcR;
    795   return i;
    796 }
    797 
    798 TILEGXInstr *TILEGXInstr_Call ( TILEGXCondCode cond, Addr64 target,
    799                                 ULong argiregs,
    800                                 HReg src )
    801 {
    802   ULong mask;
    803   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    804   i->tag = GXin_Call;
    805   i->GXin.Call.cond = cond;
    806   i->GXin.Call.target = target;
    807   i->GXin.Call.argiregs = argiregs;
    808   i->GXin.Call.src = src;
    809 
    810   /* Only r0 .. r9 inclusive may be used as arg regs. Hence: */
    811   mask = (1ULL << 10) - 1;
    812   vassert(0 == (argiregs & ~mask));
    813   return i;
    814 }
    815 
    816 TILEGXInstr *TILEGXInstr_CallAlways ( TILEGXCondCode cond, Addr64 target,
    817                                       ULong argiregs )
    818 {
    819   ULong mask;
    820   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    821   i->tag = GXin_Call;
    822   i->GXin.Call.cond = cond;
    823   i->GXin.Call.target = target;
    824   i->GXin.Call.argiregs = argiregs;
    825 
    826   /* Only r0 .. r9 inclusive may be used as arg regs. Hence: */
    827   mask = (1ULL << 10) - 1;
    828   vassert(0 == (argiregs & ~mask));
    829   return i;
    830 }
    831 
    832 TILEGXInstr *TILEGXInstr_XDirect ( Addr64 dstGA, TILEGXAMode* amPC,
    833                                    TILEGXCondCode cond, Bool toFastEP )
    834 {
    835   TILEGXInstr* i             = LibVEX_Alloc(sizeof(TILEGXInstr));
    836   i->tag                     = GXin_XDirect;
    837   i->GXin.XDirect.dstGA      = dstGA;
    838   i->GXin.XDirect.amPC       = amPC;
    839   i->GXin.XDirect.cond       = cond;
    840   i->GXin.XDirect.toFastEP   = toFastEP;
    841   return i;
    842 }
    843 
    844 TILEGXInstr *TILEGXInstr_XIndir ( HReg dstGA, TILEGXAMode* amPC,
    845                                   TILEGXCondCode cond )
    846 {
    847   TILEGXInstr* i           = LibVEX_Alloc(sizeof(TILEGXInstr));
    848   i->tag                   = GXin_XIndir;
    849   i->GXin.XIndir.dstGA     = dstGA;
    850   i->GXin.XIndir.amPC      = amPC;
    851   i->GXin.XIndir.cond      = cond;
    852   return i;
    853 }
    854 
    855 TILEGXInstr *TILEGXInstr_XAssisted ( HReg dstGA, TILEGXAMode* amPC,
    856                                      TILEGXCondCode cond, IRJumpKind jk )
    857 {
    858   TILEGXInstr* i              = LibVEX_Alloc(sizeof(TILEGXInstr));
    859   i->tag                      = GXin_XAssisted;
    860   i->GXin.XAssisted.dstGA     = dstGA;
    861   i->GXin.XAssisted.amPC      = amPC;
    862   i->GXin.XAssisted.cond      = cond;
    863   i->GXin.XAssisted.jk        = jk;
    864   return i;
    865 }
    866 
    867 TILEGXInstr *TILEGXInstr_EvCheck ( TILEGXAMode* amCounter,
    868                                    TILEGXAMode* amFailAddr ) {
    869   TILEGXInstr* i               = LibVEX_Alloc(sizeof(TILEGXInstr));
    870   i->tag                       = GXin_EvCheck;
    871   i->GXin.EvCheck.amCounter     = amCounter;
    872   i->GXin.EvCheck.amFailAddr    = amFailAddr;
    873   return i;
    874 }
    875 
    876 TILEGXInstr* TILEGXInstr_ProfInc ( void ) {
    877   TILEGXInstr* i = LibVEX_Alloc(sizeof(TILEGXInstr));
    878   i->tag       = GXin_ProfInc;
    879   return i;
    880 }
    881 
    882 TILEGXInstr *TILEGXInstr_Load ( UChar sz, HReg dst, TILEGXAMode * src )
    883 {
    884   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    885   i->tag = GXin_Load;
    886   i->GXin.Load.sz = sz;
    887   i->GXin.Load.src = src;
    888   i->GXin.Load.dst = dst;
    889   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    890   return i;
    891 }
    892 
    893 TILEGXInstr *TILEGXInstr_Store(UChar sz, TILEGXAMode * dst, HReg src)
    894 {
    895   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    896   i->tag = GXin_Store;
    897   i->GXin.Store.sz = sz;
    898   i->GXin.Store.src = src;
    899   i->GXin.Store.dst = dst;
    900   vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    901   return i;
    902 }
    903 
    904 /* Read/Write Link Register */
    905 TILEGXInstr *TILEGXInstr_RdWrLR ( Bool wrLR, HReg gpr )
    906 {
    907   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    908   i->tag = GXin_RdWrLR;
    909   i->GXin.RdWrLR.wrLR = wrLR;
    910   i->GXin.RdWrLR.gpr = gpr;
    911   return i;
    912 }
    913 
    914 TILEGXInstr *TILEGXInstr_MovCond ( HReg dst, HReg argL, TILEGXRH * argR,
    915                                    HReg condR, TILEGXCondCode cond )
    916 {
    917   TILEGXInstr *i = LibVEX_Alloc(sizeof(TILEGXInstr));
    918   i->tag = GXin_MovCond;
    919   i->GXin.MovCond.dst = dst;
    920   i->GXin.MovCond.srcL = argL;
    921   i->GXin.MovCond.srcR = argR;
    922   i->GXin.MovCond.condR = condR;
    923   i->GXin.MovCond.cond = cond;
    924   return i;
    925 }
    926 
    927 /* --------- Helpers for register allocation. --------- */
    928 
    929 void getRegUsage_TILEGXInstr ( HRegUsage * u, TILEGXInstr * i )
    930 {
    931   initHRegUsage(u);
    932   switch (i->tag) {
    933   case GXin_LI:
    934     addHRegUse(u, HRmWrite, i->GXin.LI.dst);
    935     break;
    936   case GXin_Alu:
    937     addHRegUse(u, HRmRead, i->GXin.Alu.srcL);
    938     addRegUsage_TILEGXRH(u, i->GXin.Alu.srcR);
    939     addHRegUse(u, HRmWrite, i->GXin.Alu.dst);
    940     return;
    941   case GXin_CmpI:
    942     addHRegUse(u, HRmRead, i->GXin.CmpI.srcL);
    943     addRegUsage_TILEGXRH(u, i->GXin.CmpI.srcR);
    944     addHRegUse(u, HRmWrite, i->GXin.CmpI.dst);
    945     return;
    946   case GXin_Shft:
    947     addHRegUse(u, HRmRead, i->GXin.Shft.srcL);
    948     addRegUsage_TILEGXRH(u, i->GXin.Shft.srcR);
    949     addHRegUse(u, HRmWrite, i->GXin.Shft.dst);
    950     return;
    951   case GXin_Cmp:
    952     addHRegUse(u, HRmRead, i->GXin.Cmp.srcL);
    953     addHRegUse(u, HRmRead, i->GXin.Cmp.srcR);
    954     addHRegUse(u, HRmWrite, i->GXin.Cmp.dst);
    955     return;
    956   case GXin_Bf:
    957     addHRegUse(u, HRmRead, i->GXin.Bf.src);
    958     addHRegUse(u, HRmWrite, i->GXin.Bf.dst);
    959     return;
    960   case GXin_Acas:
    961     addHRegUse(u, HRmRead, i->GXin.Acas.addr);
    962     addHRegUse(u, HRmRead, i->GXin.Acas.new);
    963     if (i->GXin.Acas.op == GXacas_CMPEXCH)
    964       addHRegUse(u, HRmRead, i->GXin.Acas.exp);
    965     addHRegUse(u, HRmWrite, i->GXin.Acas.old);
    966     return;
    967   case GXin_Unary:
    968     addHRegUse(u, HRmRead, i->GXin.Unary.src);
    969     addHRegUse(u, HRmWrite, i->GXin.Unary.dst);
    970     return;
    971   case GXin_Mul:
    972     addHRegUse(u, HRmWrite, i->GXin.Mul.dst);
    973     addHRegUse(u, HRmRead, i->GXin.Mul.srcL);
    974     addHRegUse(u, HRmRead, i->GXin.Mul.srcR);
    975     return;
    976   case GXin_Call: {
    977     if (i->GXin.Call.cond != TILEGXcc_AL)
    978       addHRegUse(u, HRmRead, i->GXin.Call.src);
    979     ULong argir;
    980 
    981     // Only need save r10-r29, and r0-r9 is not allocable.
    982     addHRegUse(u, HRmWrite, hregTILEGX_R10());
    983     addHRegUse(u, HRmWrite, hregTILEGX_R11());
    984     addHRegUse(u, HRmWrite, hregTILEGX_R12());
    985     addHRegUse(u, HRmWrite, hregTILEGX_R13());
    986     addHRegUse(u, HRmWrite, hregTILEGX_R14());
    987     addHRegUse(u, HRmWrite, hregTILEGX_R15());
    988 
    989     addHRegUse(u, HRmWrite, hregTILEGX_R16());
    990     addHRegUse(u, HRmWrite, hregTILEGX_R17());
    991     addHRegUse(u, HRmWrite, hregTILEGX_R18());
    992     addHRegUse(u, HRmWrite, hregTILEGX_R19());
    993     addHRegUse(u, HRmWrite, hregTILEGX_R20());
    994     addHRegUse(u, HRmWrite, hregTILEGX_R21());
    995     addHRegUse(u, HRmWrite, hregTILEGX_R22());
    996     addHRegUse(u, HRmWrite, hregTILEGX_R23());
    997 
    998     addHRegUse(u, HRmWrite, hregTILEGX_R24());
    999     addHRegUse(u, HRmWrite, hregTILEGX_R25());
   1000     addHRegUse(u, HRmWrite, hregTILEGX_R26());
   1001     addHRegUse(u, HRmWrite, hregTILEGX_R27());
   1002 
   1003     addHRegUse(u, HRmWrite, hregTILEGX_R28());
   1004     addHRegUse(u, HRmWrite, hregTILEGX_R29());
   1005 
   1006     /* Now we have to state any parameter-carrying registers
   1007        which might be read.  This depends on the argiregs field. */
   1008     argir = i->GXin.Call.argiregs;
   1009     if (argir & (1 << 9))
   1010       addHRegUse(u, HRmRead, hregTILEGX_R9());
   1011     if (argir & (1 << 8))
   1012       addHRegUse(u, HRmRead, hregTILEGX_R8());
   1013     if (argir & (1 << 7))
   1014       addHRegUse(u, HRmRead, hregTILEGX_R7());
   1015     if (argir & (1 << 6))
   1016       addHRegUse(u, HRmRead, hregTILEGX_R6());
   1017     if (argir & (1 << 5))
   1018       addHRegUse(u, HRmRead, hregTILEGX_R5());
   1019     if (argir & (1 << 4))
   1020       addHRegUse(u, HRmRead, hregTILEGX_R4());
   1021     if (argir & (1 << 3))
   1022       addHRegUse(u, HRmRead, hregTILEGX_R3());
   1023     if (argir & (1 << 2))
   1024       addHRegUse(u, HRmRead, hregTILEGX_R2());
   1025     if (argir & (1 << 1))
   1026       addHRegUse(u, HRmRead, hregTILEGX_R1());
   1027     if (argir & (1 << 0))
   1028       addHRegUse(u, HRmRead, hregTILEGX_R0());
   1029 
   1030     vassert(0 == (argir & ~((1ULL << 10) - 1)));
   1031     return;
   1032   }
   1033   case GXin_XDirect:
   1034     addRegUsage_TILEGXAMode(u, i->GXin.XDirect.amPC);
   1035     return;
   1036   case GXin_XIndir:
   1037     addHRegUse(u, HRmRead, i->GXin.XIndir.dstGA);
   1038     addRegUsage_TILEGXAMode(u, i->GXin.XIndir.amPC);
   1039     return;
   1040   case GXin_XAssisted:
   1041     addHRegUse(u, HRmRead, i->GXin.XAssisted.dstGA);
   1042     addRegUsage_TILEGXAMode(u, i->GXin.XAssisted.amPC);
   1043     return;
   1044 
   1045   case GXin_EvCheck:
   1046     addRegUsage_TILEGXAMode(u, i->GXin.EvCheck.amCounter);
   1047     addRegUsage_TILEGXAMode(u, i->GXin.EvCheck.amFailAddr);
   1048     return;
   1049   case GXin_ProfInc:
   1050     return;
   1051   case GXin_Load:
   1052     addRegUsage_TILEGXAMode(u, i->GXin.Load.src);
   1053     addHRegUse(u, HRmWrite, i->GXin.Load.dst);
   1054     return;
   1055   case GXin_Store:
   1056     addHRegUse(u, HRmRead, i->GXin.Store.src);
   1057     addRegUsage_TILEGXAMode(u, i->GXin.Store.dst);
   1058     return;
   1059   case GXin_RdWrLR:
   1060     addHRegUse(u, (i->GXin.RdWrLR.wrLR ? HRmRead : HRmWrite),
   1061                i->GXin.RdWrLR.gpr);
   1062     return;
   1063   case GXin_MovCond:
   1064     if (i->GXin.MovCond.srcR->tag == GXrh_Reg) {
   1065       addHRegUse(u, HRmRead, i->GXin.MovCond.srcR->GXrh.Reg.reg);
   1066     }
   1067     addHRegUse(u, HRmRead, i->GXin.MovCond.srcL);
   1068     addHRegUse(u, HRmRead, i->GXin.MovCond.condR);
   1069     addHRegUse(u, HRmWrite, i->GXin.MovCond.dst);
   1070     return;
   1071   default:
   1072     vpanic("getRegUsage_TILEGXInstr");
   1073   }
   1074 }
   1075 
   1076 /* local helper */
   1077 static void mapReg ( HRegRemap * m, HReg * r )
   1078 {
   1079   *r = lookupHRegRemap(m, *r);
   1080 }
   1081 
   1082 void mapRegs_TILEGXInstr ( HRegRemap * m, TILEGXInstr * i )
   1083 {
   1084   switch (i->tag) {
   1085   case GXin_LI:
   1086     mapReg(m, &i->GXin.LI.dst);
   1087     break;
   1088   case GXin_Alu:
   1089     mapReg(m, &i->GXin.Alu.srcL);
   1090     mapRegs_TILEGXRH(m, i->GXin.Alu.srcR);
   1091     mapReg(m, &i->GXin.Alu.dst);
   1092     return;
   1093   case GXin_CmpI:
   1094     mapReg(m, &i->GXin.CmpI.srcL);
   1095     mapRegs_TILEGXRH(m, i->GXin.CmpI.srcR);
   1096     mapReg(m, &i->GXin.CmpI.dst);
   1097     return;
   1098   case GXin_Shft:
   1099     mapReg(m, &i->GXin.Shft.srcL);
   1100     mapRegs_TILEGXRH(m, i->GXin.Shft.srcR);
   1101     mapReg(m, &i->GXin.Shft.dst);
   1102     return;
   1103   case GXin_Cmp:
   1104     mapReg(m, &i->GXin.Cmp.srcL);
   1105     mapReg(m, &i->GXin.Cmp.srcR);
   1106     mapReg(m, &i->GXin.Cmp.dst);
   1107     return;
   1108   case GXin_Acas:
   1109     mapReg(m, &i->GXin.Acas.old);
   1110     mapReg(m, &i->GXin.Acas.addr);
   1111     mapReg(m, &i->GXin.Acas.new);
   1112     if (i->GXin.Acas.op == GXacas_CMPEXCH)
   1113       mapReg(m, &i->GXin.Acas.exp);
   1114     return;
   1115   case GXin_Bf:
   1116     mapReg(m, &i->GXin.Bf.src);
   1117     mapReg(m, &i->GXin.Bf.dst);
   1118     return;
   1119   case GXin_Unary:
   1120     mapReg(m, &i->GXin.Unary.src);
   1121     mapReg(m, &i->GXin.Unary.dst);
   1122     return;
   1123   case GXin_Mul:
   1124     mapReg(m, &i->GXin.Mul.dst);
   1125     mapReg(m, &i->GXin.Mul.srcL);
   1126     mapReg(m, &i->GXin.Mul.srcR);
   1127     return;
   1128   case GXin_Call:
   1129     {
   1130       if (i->GXin.Call.cond != TILEGXcc_AL)
   1131         mapReg(m, &i->GXin.Call.src);
   1132       return;
   1133     }
   1134   case GXin_XDirect:
   1135     mapRegs_TILEGXAMode(m, i->GXin.XDirect.amPC);
   1136     return;
   1137   case GXin_XIndir:
   1138     mapReg(m, &i->GXin.XIndir.dstGA);
   1139     mapRegs_TILEGXAMode(m, i->GXin.XIndir.amPC);
   1140     return;
   1141   case GXin_XAssisted:
   1142     mapReg(m, &i->GXin.XAssisted.dstGA);
   1143     mapRegs_TILEGXAMode(m, i->GXin.XAssisted.amPC);
   1144     return;
   1145   case GXin_EvCheck:
   1146     mapRegs_TILEGXAMode(m, i->GXin.EvCheck.amCounter);
   1147     mapRegs_TILEGXAMode(m, i->GXin.EvCheck.amFailAddr);
   1148     return;
   1149   case GXin_ProfInc:
   1150     return;
   1151   case GXin_Load:
   1152     mapRegs_TILEGXAMode(m, i->GXin.Load.src);
   1153     mapReg(m, &i->GXin.Load.dst);
   1154     return;
   1155   case GXin_Store:
   1156     mapReg(m, &i->GXin.Store.src);
   1157     mapRegs_TILEGXAMode(m, i->GXin.Store.dst);
   1158     return;
   1159   case GXin_RdWrLR:
   1160     mapReg(m, &i->GXin.RdWrLR.gpr);
   1161     return;
   1162   case GXin_MovCond:
   1163     if (i->GXin.MovCond.srcR->tag == GXrh_Reg) {
   1164       mapReg(m, &(i->GXin.MovCond.srcR->GXrh.Reg.reg));
   1165     }
   1166     mapReg(m, &i->GXin.MovCond.srcL);
   1167     mapReg(m, &i->GXin.MovCond.condR);
   1168     mapReg(m, &i->GXin.MovCond.dst);
   1169 
   1170     return;
   1171   default:
   1172     vpanic("mapRegs_TILEGXInstr");
   1173   }
   1174 }
   1175 
   1176 /* Figure out if i represents a reg-reg move, and if so assign the
   1177    source and destination to *src and *dst.  If in doubt say No.  Used
   1178    by the register allocator to do move coalescing.
   1179 */
   1180 Bool isMove_TILEGXInstr ( TILEGXInstr * i, HReg * src, HReg * dst )
   1181 {
   1182   /* Moves between integer regs */
   1183   if (i->tag == GXin_Alu) {
   1184     // or Rd,Rs,Rs == mov Rd, Rs
   1185     if (i->GXin.Alu.op != GXalu_OR)
   1186       return False;
   1187     if (i->GXin.Alu.srcR->tag != GXrh_Reg)
   1188       return False;
   1189     if (!sameHReg(i->GXin.Alu.srcR->GXrh.Reg.reg, i->GXin.Alu.srcL))
   1190       return False;
   1191     *src = i->GXin.Alu.srcL;
   1192     *dst = i->GXin.Alu.dst;
   1193     return True;
   1194   }
   1195   return False;
   1196 }
   1197 
   1198 /* Generate tilegx spill/reload instructions under the direction of the
   1199    register allocator.
   1200 */
   1201 void genSpill_TILEGX ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
   1202                        Int offsetB )
   1203 {
   1204   TILEGXAMode *am;
   1205   vassert(offsetB >= 0);
   1206   vassert(!hregIsVirtual(rreg));
   1207   *i1 = *i2 = NULL;
   1208   am = TILEGXAMode_IR(offsetB, TILEGXGuestStatePointer());
   1209 
   1210   switch (hregClass(rreg)) {
   1211   case HRcInt64:
   1212     *i1 = TILEGXInstr_Store(8, am, rreg);
   1213     break;
   1214   case HRcInt32:
   1215     *i1 = TILEGXInstr_Store(4, am, rreg);
   1216     break;
   1217   default:
   1218     ppHRegClass(hregClass(rreg));
   1219     vpanic("genSpill_TILEGX: unimplemented regclass");
   1220   }
   1221 }
   1222 
   1223 void genReload_TILEGX ( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
   1224                         Int offsetB )
   1225 {
   1226   TILEGXAMode *am;
   1227   vassert(!hregIsVirtual(rreg));
   1228   am = TILEGXAMode_IR(offsetB, TILEGXGuestStatePointer());
   1229 
   1230   switch (hregClass(rreg)) {
   1231   case HRcInt64:
   1232     *i1 = TILEGXInstr_Load(8, rreg, am);
   1233     break;
   1234   case HRcInt32:
   1235     *i1 = TILEGXInstr_Load(4, rreg, am);
   1236     break;
   1237   default:
   1238     ppHRegClass(hregClass(rreg));
   1239     vpanic("genReload_TILEGX: unimplemented regclass");
   1240     break;
   1241   }
   1242 }
   1243 
   1244 /* --------- The tilegx assembler --------- */
   1245 
   1246 static UChar *mkInsnBin ( UChar * p, ULong insn )
   1247 {
   1248   vassert(insn != (ULong)(-1));
   1249   if (((Addr)p) & 7) {
   1250     vex_printf("p=%p\n", p);
   1251     vassert((((Addr)p) & 7) == 0);
   1252   }
   1253   *((ULong *)(Addr)p) = insn;
   1254   p += 8;
   1255   return p;
   1256 }
   1257 
   1258 static Int display_insn ( struct tilegx_decoded_instruction
   1259                           decoded[1] )
   1260 {
   1261   Int i;
   1262   for (i = 0;
   1263        decoded[i].opcode && (i < 1);
   1264        i++) {
   1265     Int n;
   1266     vex_printf("%s ", decoded[i].opcode->name);
   1267 
   1268     for (n = 0; n < decoded[i].opcode->num_operands; n++) {
   1269       const struct tilegx_operand *op = decoded[i].operands[n];
   1270 
   1271       if (op->type == TILEGX_OP_TYPE_REGISTER)
   1272         vex_printf("r%d", (Int) decoded[i].operand_values[n]);
   1273       else
   1274         vex_printf("%llu", (ULong)decoded[i].operand_values[n]);
   1275 
   1276       if (n != (decoded[i].opcode->num_operands - 1))
   1277         vex_printf(", ");
   1278     }
   1279     vex_printf(" ");
   1280   }
   1281   return i;
   1282 }
   1283 
   1284 
   1285 Int decode_and_display ( tilegx_bundle_bits *p, Int count, ULong pc )
   1286 {
   1287   struct tilegx_decoded_instruction
   1288     decode[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
   1289   Int i;
   1290 
   1291 #ifdef TILEGX_DEBUG
   1292   vex_printf("Insn@0x%lx\n", (ULong)p);
   1293 #endif
   1294 
   1295   if (count > 0x1000) {
   1296     vex_printf("insn count: %d", count);
   1297     vassert(0);
   1298   }
   1299 
   1300   for (i = 0 ; i < count ; i++) {
   1301     if (pc) {
   1302       vex_printf("%012llx %016llx  ", pc, (ULong)p[i]);
   1303       pc += 8;
   1304     }
   1305     parse_insn_tilegx(p[i], 0, decode);
   1306 
   1307     Int n, k, bundled = 0;
   1308 
   1309     for(k = 0; (k < TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) && decode[k].opcode;
   1310         k++) {
   1311       if (decode[k].opcode->mnemonic != TILEGX_OPC_FNOP)
   1312         bundled++;
   1313     }
   1314 
   1315     /* Print "{", ";" and "}" only if multiple instructions are bundled. */
   1316     if (bundled > 1)
   1317       vex_printf("{ ");
   1318 
   1319     n = bundled;
   1320     for(k = 0; (k < TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) && decode[k].opcode;
   1321         k++) {
   1322       if (decode[k].opcode->mnemonic == TILEGX_OPC_FNOP)
   1323         continue;
   1324 
   1325       display_insn(&decode[k]);
   1326 
   1327       if (--n > 0)
   1328         vex_printf("; ");
   1329     }
   1330 
   1331     if (bundled > 1)
   1332       vex_printf(" }");
   1333 
   1334     vex_printf("\n");
   1335   }
   1336   return count;
   1337 }
   1338 
   1339 static UInt iregNo ( HReg r )
   1340 {
   1341   UInt n;
   1342   vassert(hregClass(r) == HRcInt64);
   1343   vassert(!hregIsVirtual(r));
   1344   n = hregEncoding(r);
   1345   vassert(n <= 63);
   1346   return n;
   1347 }
   1348 
   1349 static UChar *doAMode_IR ( UChar * p, UInt opc1, UInt rSD, TILEGXAMode * am )
   1350 {
   1351   UInt rA;
   1352   vassert(am->tag == GXam_IR);
   1353 
   1354   rA = iregNo(am->GXam.IR.base);
   1355 
   1356   if (opc1 == TILEGX_OPC_ST1 || opc1 == TILEGX_OPC_ST2 ||
   1357       opc1 == TILEGX_OPC_ST4 || opc1 == TILEGX_OPC_ST) {
   1358     if ( am->GXam.IR.index ) {
   1359       /* r51 is reserved scratch registers. */
   1360       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1361                                     51, rA, am->GXam.IR.index));
   1362       /* store rSD to address in r51 */
   1363       p = mkInsnBin(p, mkTileGxInsn(opc1, 2, 51, rSD));
   1364     } else {
   1365       /* store rSD to address in rA */
   1366       p = mkInsnBin(p, mkTileGxInsn(opc1, 2, rA, rSD));
   1367     }
   1368   } else {
   1369     if ( am->GXam.IR.index ) {
   1370       /* r51 is reserved scratch registers. */
   1371       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1372                                     51, rA, am->GXam.IR.index));
   1373       /* load from address in r51 to rSD. */
   1374       p = mkInsnBin(p, mkTileGxInsn(opc1, 2, rSD, 51));
   1375     } else {
   1376       /* load from address in rA to rSD. */
   1377       p = mkInsnBin(p, mkTileGxInsn(opc1, 2, rSD, rA));
   1378     }
   1379   }
   1380   return p;
   1381 }
   1382 
   1383 /* Generate a machine-word sized load or store using exact 2 bundles.
   1384    Simplified version of the GXin_Load and GXin_Store cases below. */
   1385 static UChar* do_load_or_store_machine_word ( UChar* p, Bool isLoad, UInt reg,
   1386                                               TILEGXAMode* am )
   1387 {
   1388   UInt rA = iregNo(am->GXam.IR.base);
   1389 
   1390   if (am->tag != GXam_IR)
   1391     vpanic(__func__);
   1392 
   1393   if (isLoad) /* load */ {
   1394      /* r51 is reserved scratch registers. */
   1395      p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1396 				   51, rA, am->GXam.IR.index));
   1397      /* load from address in r51 to rSD. */
   1398      p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_LD, 2, reg, 51));
   1399   } else /* store */ {
   1400      /* r51 is reserved scratch registers. */
   1401      p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1402 				   51, rA, am->GXam.IR.index));
   1403      /* store rSD to address in r51 */
   1404      p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ST, 2, 51, reg));
   1405   }
   1406   return p;
   1407 }
   1408 
   1409 /* Load imm to r_dst */
   1410 static UChar *mkLoadImm ( UChar * p, UInt r_dst, ULong imm )
   1411 {
   1412   vassert(r_dst < 0x40);
   1413 
   1414   if (imm == 0)
   1415   {
   1416     /* A special case, use r63 - zero register. */
   1417     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVE, 2, r_dst, 63));
   1418   }
   1419   else if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000)
   1420   {
   1421     /* only need one 16-bit sign-extendable movli instructon. */
   1422     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVELI, 2,
   1423                                   r_dst, imm & 0xFFFF));
   1424 
   1425   }
   1426   else if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL)
   1427   {
   1428     /* Sign-extendable moveli and a shl16insli */
   1429     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVELI, 2,
   1430                                   r_dst,
   1431                                   (imm >> 16) & 0xFFFF));
   1432 
   1433     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1434                                   r_dst, r_dst,
   1435                                   (imm & 0xFFFF)));
   1436 
   1437   }
   1438   else
   1439   {
   1440     /* A general slower and rare case, use 4 instructions/bundles:
   1441        moveli     r_dst, imm[63:48]
   1442        shl16insli r_dst, imm[47:32]
   1443        shl16insli r_dst, imm[31:16]
   1444        shl16insli r_dst, imm[15: 0]
   1445     */
   1446     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVELI, 2,
   1447                                   r_dst,
   1448                                   (imm >> 48) & 0xFFFF));
   1449 
   1450     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1451                                   r_dst, r_dst,
   1452                                   (imm >> 32) & 0xFFFF));
   1453 
   1454     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1455                                   r_dst, r_dst,
   1456                                   (imm >> 16) & 0xFFFF));
   1457 
   1458     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1459                                   r_dst, r_dst,
   1460                                   imm & 0xFFFF));
   1461   }
   1462   return p;
   1463 }
   1464 
   1465 /* Load imm to r_dst using exact 4 bundles. A special case of above
   1466    mkLoadImm(...). */
   1467 static UChar *mkLoadImm_EXACTLY4 ( UChar * p, UInt r_dst, ULong imm )
   1468 {
   1469   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVELI, 2,
   1470                                 r_dst,
   1471                                 (imm >> 48) & 0xFFFF));
   1472 
   1473   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1474                                 r_dst, r_dst,
   1475                                 (imm >> 32) & 0xFFFF));
   1476 
   1477   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1478                                 r_dst, r_dst,
   1479                                 (imm >> 16) & 0xFFFF));
   1480 
   1481   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1482                                 r_dst, r_dst,
   1483                                 (imm) & 0xFFFF));
   1484   return p;
   1485 }
   1486 
   1487 /* Move r_dst to r_src */
   1488 static UChar *mkMoveReg ( UChar * p, UInt r_dst, UInt r_src )
   1489 {
   1490   vassert(r_dst < 0x40);
   1491   vassert(r_src < 0x40);
   1492 
   1493   if (r_dst != r_src) {
   1494     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVE, 2,
   1495                                   r_dst, r_src));
   1496   }
   1497   return p;
   1498 }
   1499 
   1500 /* Emit an instruction into buf and return the number of bytes used.
   1501    Note that buf is not the insn's final place, and therefore it is
   1502    imperative to emit position-independent code. */
   1503 Int emit_TILEGXInstr ( Bool*  is_profInc,
   1504                        UChar* buf,
   1505                        Int    nbuf,
   1506                        TILEGXInstr* i,
   1507                        Bool   mode64,
   1508                        VexEndness endness_host,
   1509                        void*  disp_cp_chain_me_to_slowEP,
   1510                        void*  disp_cp_chain_me_to_fastEP,
   1511                        void*  disp_cp_xindir,
   1512                        void*  disp_cp_xassisted )
   1513 {
   1514   Int instr_bytes = 0;
   1515   UChar *p = &buf[0];
   1516   UChar *ptmp = p;
   1517   vassert(nbuf >= 32);
   1518   vassert(!((Addr)p & 0x7));
   1519   vassert (mode64);
   1520 
   1521   switch (i->tag) {
   1522   case GXin_MovCond: {
   1523 
   1524     TILEGXRH *srcR = i->GXin.MovCond.srcR;
   1525     UInt condR = iregNo(i->GXin.MovCond.condR);
   1526     UInt dst = iregNo(i->GXin.MovCond.dst);
   1527 
   1528     UInt srcL = iregNo(i->GXin.MovCond.srcL);
   1529 
   1530     if (i->GXin.MovCond.cond == TILEGXcc_EZ) {
   1531       if (srcR->tag == GXrh_Reg) {
   1532         p = mkMoveReg(p, dst, iregNo(srcR->GXrh.Reg.reg));
   1533         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMOVEQZ, 3,
   1534                                       dst, condR, srcL));
   1535       } else {
   1536         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MOVELI, 2,
   1537                                       dst, srcR->GXrh.Imm.imm16));
   1538         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMOVEQZ, 3,
   1539                                       dst, condR, srcL));
   1540       }
   1541     } else {
   1542       vassert(0);
   1543     }
   1544 
   1545     goto done;
   1546   }
   1547   case GXin_LI:
   1548 
   1549     // Tilegx, load literal
   1550     p = mkLoadImm(p, iregNo(i->GXin.LI.dst), i->GXin.LI.imm);
   1551     goto done;
   1552 
   1553   case GXin_Alu: {
   1554     TILEGXRH *srcR = i->GXin.Alu.srcR;
   1555     Bool immR = toBool(srcR->tag == GXrh_Imm);
   1556     UInt r_dst = iregNo(i->GXin.Alu.dst);
   1557     UInt r_srcL = iregNo(i->GXin.Alu.srcL);
   1558     UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->GXrh.Reg.reg);
   1559 
   1560     switch (i->GXin.Alu.op) {
   1561       /*GXalu_ADD, GXalu_SUB, GXalu_AND, GXalu_OR, GXalu_NOR, GXalu_XOR */
   1562     case GXalu_ADD:
   1563       if (immR) {
   1564         vassert(srcR->GXrh.Imm.imm16 != 0x8000);
   1565         if (srcR->GXrh.Imm.syned)
   1566           /* addi */
   1567           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1568                                         r_dst, r_srcL,
   1569                                         srcR->GXrh.Imm.imm16));
   1570         else
   1571           /* addiu, use shil16insli for tilegx  */
   1572           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL16INSLI, 3,
   1573                                         r_dst, 63,
   1574                                         srcR->GXrh.Imm.imm16));
   1575       } else {
   1576         /* addu */
   1577         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADD, 3,
   1578                                       r_dst, r_srcL,
   1579                                       r_srcR));
   1580       }
   1581       break;
   1582     case GXalu_SUB:
   1583       if (immR) {
   1584         /* addi , but with negated imm */
   1585         vassert(srcR->GXrh.Imm.syned);
   1586         vassert(srcR->GXrh.Imm.imm16 != 0x8000);
   1587         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   1588                                       r_dst, r_srcL,
   1589                                       -srcR->GXrh.Imm.imm16));
   1590       } else {
   1591         /* subu */
   1592         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SUB, 3,
   1593                                       r_dst, r_srcL,
   1594                                       r_srcR));
   1595       }
   1596       break;
   1597     case GXalu_AND:
   1598       if (immR) {
   1599         /* andi */
   1600         vassert((srcR->GXrh.Imm.imm16 >> 8 == 0) ||
   1601                 (srcR->GXrh.Imm.imm16 >> 8 == 0xFF));
   1602 
   1603         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ANDI, 3,
   1604                                       r_dst, r_srcL,
   1605                                       srcR->GXrh.Imm.imm16));
   1606 
   1607       } else {
   1608         /* and */
   1609         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_AND, 3,
   1610                                       r_dst, r_srcL,
   1611                                       r_srcR));
   1612       }
   1613       break;
   1614     case GXalu_OR:
   1615       if (immR) {
   1616         /* ori */
   1617         vassert((srcR->GXrh.Imm.imm16 >> 8 == 0) ||
   1618                 (srcR->GXrh.Imm.imm16 >> 8 == 0xFF));
   1619 
   1620         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ORI, 3,
   1621                                       r_dst, r_srcL,
   1622                                       srcR->GXrh.Imm.imm16));
   1623       } else {
   1624         /* or */
   1625         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_OR, 3,
   1626                                       r_dst, r_srcL,
   1627                                       r_srcR));
   1628       }
   1629       break;
   1630     case GXalu_NOR:
   1631       /* nor */
   1632       vassert(!immR);
   1633       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOR, 3,
   1634                                     r_dst, r_srcL,
   1635                                     r_srcR));
   1636       break;
   1637     case GXalu_XOR:
   1638       if (immR) {
   1639         /* xori */
   1640         vassert(srcR->GXrh.Imm.syned);
   1641         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_XORI, 3,
   1642                                       r_dst, r_srcL,
   1643                                       srcR->GXrh.Imm.imm16));
   1644       } else {
   1645         /* xor */
   1646         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_XOR, 3,
   1647                                       r_dst, r_srcL,
   1648                                       r_srcR));
   1649       }
   1650       break;
   1651 
   1652     default:
   1653       goto bad;
   1654     }
   1655     goto done;
   1656   }
   1657 
   1658   case GXin_Shft: {
   1659     TILEGXRH *srcR = i->GXin.Shft.srcR;
   1660     Bool sz32 = i->GXin.Shft.sz32;
   1661     Bool immR = toBool(srcR->tag == GXrh_Imm);
   1662     UInt r_dst = iregNo(i->GXin.Shft.dst);
   1663     UInt r_srcL = iregNo(i->GXin.Shft.srcL);
   1664     UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->GXrh.Reg.reg);
   1665 
   1666     switch (i->GXin.Shft.op) {
   1667     case GXshft_SLL:
   1668       if (sz32) {
   1669         if (immR) {
   1670           UInt n = srcR->GXrh.Imm.imm16;
   1671           vassert(n >= 0 && n < 64);
   1672           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHLXI, 3,
   1673                                         r_dst, r_srcL,
   1674                                         srcR->GXrh.Imm.imm16));
   1675         } else {
   1676           /* shift variable */
   1677           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHLX, 3,
   1678                                         r_dst, r_srcL,
   1679                                         r_srcR));
   1680         }
   1681       } else {
   1682         if (immR) {
   1683           UInt n = srcR->GXrh.Imm.imm16;
   1684           vassert(n >= 0 && n < 64);
   1685           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHLI, 3,
   1686                                         r_dst, r_srcL,
   1687                                         srcR->GXrh.Imm.imm16));
   1688         } else {
   1689           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHL, 3,
   1690                                         r_dst, r_srcL,
   1691                                         r_srcR));
   1692         }
   1693       }
   1694       break;
   1695 
   1696     case GXshft_SLL8x8:
   1697       if (immR) {
   1698         UInt n = srcR->GXrh.Imm.imm16;
   1699         vassert(n >= 0 && n < 64);
   1700         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1SHLI, 3,
   1701                                       r_dst, r_srcL,
   1702                                       srcR->GXrh.Imm.imm16));
   1703       } else {
   1704         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1SHL, 3,
   1705                                       r_dst, r_srcL,
   1706                                       r_srcR));
   1707       }
   1708       break;
   1709 
   1710     case GXshft_SRL8x8:
   1711       if (immR) {
   1712         UInt n = srcR->GXrh.Imm.imm16;
   1713         vassert(n >= 0 && n < 64);
   1714         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1SHRUI, 3,
   1715                                       r_dst, r_srcL,
   1716                                       srcR->GXrh.Imm.imm16));
   1717       } else {
   1718         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1SHRU, 3,
   1719                                       r_dst, r_srcL,
   1720                                       r_srcR));
   1721       }
   1722       break;
   1723 
   1724     case GXshft_SRL:
   1725       if (sz32) {
   1726         // SRL, SRLV
   1727         if (immR) {
   1728           UInt n = srcR->GXrh.Imm.imm16;
   1729           vassert(n >= 0 && n < 32);
   1730           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRUXI, 3,
   1731                                         r_dst, r_srcL,
   1732                                         srcR->GXrh.Imm.imm16));
   1733         } else {
   1734           /* shift variable */
   1735           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRUX, 3,
   1736                                         r_dst, r_srcL,
   1737                                         r_srcR));
   1738         }
   1739       } else {
   1740         // DSRL, DSRL32, DSRLV
   1741         if (immR) {
   1742           UInt n = srcR->GXrh.Imm.imm16;
   1743           vassert((n >= 0 && n < 64));
   1744           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRUI, 3,
   1745                                         r_dst, r_srcL,
   1746                                         srcR->GXrh.Imm.imm16));
   1747         } else {
   1748           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRU, 3,
   1749                                         r_dst, r_srcL,
   1750                                         r_srcR));
   1751         }
   1752       }
   1753       break;
   1754 
   1755     case GXshft_SRA:
   1756       if (sz32) {
   1757         // SRA, SRAV
   1758         if (immR) {
   1759           UInt n = srcR->GXrh.Imm.imm16;
   1760           vassert(n >= 0 && n < 64);
   1761           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRSI, 3,
   1762                                         r_dst, r_srcL,
   1763                                         srcR->GXrh.Imm.imm16));
   1764 
   1765         } else {
   1766           /* shift variable */
   1767           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRS, 3,
   1768                                         r_dst, r_srcL,
   1769                                         r_srcR));
   1770         }
   1771       } else {
   1772         // DSRA, DSRA32, DSRAV
   1773         if (immR) {
   1774 
   1775           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRSI, 3,
   1776                                         r_dst, r_srcL,
   1777                                         srcR->GXrh.Imm.imm16));
   1778         } else {
   1779           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_SHRS, 3,
   1780                                         r_dst, r_srcL,
   1781                                         r_srcR));
   1782         }
   1783       }
   1784       break;
   1785 
   1786     default:
   1787       goto bad;
   1788     }
   1789 
   1790     goto done;
   1791   }
   1792 
   1793   case GXin_Unary: {
   1794     UInt r_dst = iregNo(i->GXin.Unary.dst);
   1795     UInt r_src = iregNo(i->GXin.Unary.src);
   1796 
   1797     switch (i->GXin.Unary.op) {
   1798       /* GXun_CLZ, GXun_NOP */
   1799     case GXun_CLZ:  //clz
   1800 
   1801       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CLZ, 2,
   1802                                     r_dst, r_src));
   1803       break;
   1804     case GXun_CTZ:  //ctz
   1805 
   1806       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CTZ, 2,
   1807                                     r_dst, r_src));
   1808       break;
   1809 
   1810     case GXun_NOP:
   1811       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   1812       break;
   1813     }
   1814     goto done;
   1815   }
   1816 
   1817   case GXin_Cmp: {
   1818 
   1819     Bool syned = i->GXin.Cmp.syned;
   1820     UInt r_srcL = iregNo(i->GXin.Cmp.srcL);
   1821     UInt r_srcR = iregNo(i->GXin.Cmp.srcR);
   1822     UInt r_dst = iregNo(i->GXin.Cmp.dst);
   1823 
   1824     switch (i->GXin.Cmp.cond) {
   1825     case TILEGXcc_EQ:
   1826 
   1827       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPEQ, 3,
   1828                                     r_dst, r_srcL,
   1829                                     r_srcR));
   1830 
   1831       break;
   1832 
   1833     case TILEGXcc_NE:
   1834       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPNE, 3,
   1835                                     r_dst, r_srcL,
   1836                                     r_srcR));
   1837 
   1838       break;
   1839     case TILEGXcc_LT:
   1840       /*  slt r_dst, r_srcL, r_srcR */
   1841 
   1842       if (syned)
   1843         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLTS, 3,
   1844                                       r_dst, r_srcL,
   1845                                       r_srcR));
   1846       else
   1847         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLTU, 3,
   1848                                       r_dst, r_srcL,
   1849                                       r_srcR));
   1850 
   1851       break;
   1852     case TILEGXcc_LO:
   1853       /*  sltu r_dst, r_srcL, r_srcR */
   1854 
   1855       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLTU, 3,
   1856                                     r_dst, r_srcL,
   1857                                     r_srcR));
   1858 
   1859       break;
   1860     case TILEGXcc_LE:
   1861       if (syned)
   1862         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLES, 3,
   1863                                       r_dst, r_srcL,
   1864                                       r_srcR));
   1865       else
   1866         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLEU, 3,
   1867                                       r_dst, r_srcL,
   1868                                       r_srcR));
   1869       break;
   1870     case TILEGXcc_LS:
   1871 
   1872       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPLTU, 3,
   1873                                     r_dst, r_srcL,
   1874                                     r_srcR));
   1875       break;
   1876     default:
   1877       goto bad;
   1878     }
   1879     goto done;
   1880   }
   1881 
   1882   case GXin_CmpI: {
   1883 
   1884     TILEGXRH *srcR = i->GXin.CmpI.srcR;
   1885     Bool immR = toBool(srcR->tag == GXrh_Imm);
   1886     UInt r_dst = iregNo(i->GXin.CmpI.dst);
   1887     UInt r_srcL = iregNo(i->GXin.CmpI.srcL);
   1888     UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->GXrh.Reg.reg);
   1889 
   1890     switch (i->GXin.CmpI.cond) {
   1891     case TILEGXcc_EQ8x8:
   1892       if (immR) {
   1893         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1CMPEQI, 3,
   1894                                       r_dst, r_srcL,
   1895                                       srcR->GXrh.Imm.imm16));
   1896       } else {
   1897         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1CMPEQ, 3,
   1898                                       r_dst, r_srcL,
   1899                                       r_srcR));
   1900       }
   1901       break;
   1902 
   1903     case TILEGXcc_NE8x8:
   1904       if (immR) {
   1905         vassert(0);
   1906       } else {
   1907         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_V1CMPNE, 3,
   1908                                       r_dst, r_srcR,
   1909                                       r_srcL));
   1910       }
   1911       break;
   1912     default:
   1913       vassert(0);
   1914     }
   1915     goto done;
   1916     break;
   1917   }
   1918 
   1919   case GXin_Bf: {
   1920 
   1921     /* Bit Field */
   1922     UInt r_dst = iregNo(i->GXin.Bf.dst);
   1923     UInt r_src = iregNo(i->GXin.Bf.src);
   1924     UInt Start = i->GXin.Bf.Start;
   1925     UInt End   = i->GXin.Bf.End;
   1926 
   1927     switch (i->GXin.Bf.op) {
   1928     case GXbf_EXTS:
   1929       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_BFEXTS, 4,
   1930                                     r_dst, r_src,
   1931                                     Start, End));
   1932 
   1933       break;
   1934     case GXbf_EXTU:
   1935       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_BFEXTU, 4,
   1936                                     r_dst, r_src,
   1937                                     Start, End));
   1938 
   1939       break;
   1940     case GXbf_INS:
   1941       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_BFINS, 4,
   1942                                     r_dst, r_src,
   1943                                     Start, End));
   1944 
   1945       break;
   1946     default:
   1947       vassert(0);
   1948     }
   1949     goto done;
   1950     break;
   1951   }
   1952 
   1953   case GXin_Acas: {
   1954 
   1955     /* Atomic */
   1956     UInt sz =  i->GXin.Acas.sz;
   1957     UInt old = iregNo(i->GXin.Acas.old);
   1958     UInt addr= iregNo(i->GXin.Acas.addr);
   1959     UInt new = iregNo(i->GXin.Acas.new);
   1960 
   1961     switch (i->GXin.Acas.op) {
   1962     case GXacas_CMPEXCH:
   1963       {
   1964         UInt exp = iregNo(i->GXin.Acas.exp);
   1965         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MTSPR, 2,
   1966                                       0x2780, exp));
   1967         if (sz == 8)
   1968           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPEXCH, 3,
   1969                                         old, addr, new));
   1970         else
   1971           p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_CMPEXCH4, 3,
   1972                                         old, addr, new));
   1973       }
   1974       break;
   1975 
   1976     case GXacas_EXCH:
   1977       if (sz == 8)
   1978         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_EXCH, 3,
   1979                                       old, addr, new));
   1980       else
   1981         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_EXCH4, 3,
   1982                                       old, addr, new));
   1983       break;
   1984 
   1985     case GXacas_FetchAnd:
   1986       if (sz == 8)
   1987         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHAND, 3,
   1988                                       old, addr, new));
   1989       else
   1990         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHAND4, 3,
   1991                                       old, addr, new));
   1992       break;
   1993 
   1994     case GXacas_FetchAdd:
   1995       if (sz == 8)
   1996         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHADD, 3,
   1997                                       old, addr, new));
   1998       else
   1999         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHADD4, 3,
   2000                                       old, addr, new));
   2001       break;
   2002 
   2003     case GXacas_FetchAddgez:
   2004       if (sz == 8)
   2005         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHADDGEZ, 3,
   2006                                       old, addr, new));
   2007       else
   2008         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHADDGEZ4, 3,
   2009                                       old, addr, new));
   2010       break;
   2011 
   2012     case GXacas_FetchOr:
   2013       if (sz == 8)
   2014         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHOR, 3,
   2015                                       old, addr, new));
   2016       else
   2017         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_FETCHOR4, 3,
   2018                                       old, addr, new));
   2019       break;
   2020 
   2021     default: vassert(0);
   2022     }
   2023     goto done;
   2024     break;
   2025   }
   2026 
   2027   case GXin_Mul: {
   2028 
   2029     /* Multiplication */
   2030     Bool syned = i->GXin.Mul.syned;
   2031     Bool widening = i->GXin.Mul.widening;
   2032     Bool sz32 = i->GXin.Mul.sz32;
   2033     UInt r_srcL = iregNo(i->GXin.Mul.srcL);
   2034     UInt r_srcR = iregNo(i->GXin.Mul.srcR);
   2035     UInt r_dst = iregNo(i->GXin.Mul.dst);
   2036 
   2037     vassert(widening);  // always widen.
   2038     vassert(!sz32);   // always be 64 bits.
   2039 
   2040     if (syned) {
   2041       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MUL_LS_LS, 3,
   2042                                     r_dst, r_srcL, r_srcR));
   2043     } else {
   2044       p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MUL_LU_LU, 3,
   2045                                     r_dst, r_srcL, r_srcR));
   2046     }
   2047     goto done;
   2048   }
   2049 
   2050   case GXin_Call: {
   2051 
   2052     /* Function Call. */
   2053     TILEGXCondCode cond = i->GXin.Call.cond;
   2054     UInt r_dst = 11;  /* using r11 as address temporary */
   2055 
   2056     /* jump over the following insns if conditional. */
   2057     if (cond != TILEGXcc_AL) {
   2058       /* jmp fwds if !condition */
   2059       /* don't know how many bytes to jump over yet...
   2060          make space for a jump instruction + nop!!! and fill in later. */
   2061       ptmp = p;   /* fill in this bit later */
   2062       p += 8;
   2063     }
   2064 
   2065     /* load target to r_dst */
   2066     p = mkLoadImm(p, r_dst, i->GXin.Call.target);
   2067 
   2068     /* jalr %r_dst */
   2069     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALRP, 1,
   2070                                   r_dst));
   2071 
   2072     /* Fix up the conditional jump, if there was one. */
   2073     if (cond != TILEGXcc_AL) {
   2074       UInt r_src = iregNo(i->GXin.Call.src);
   2075       Int delta = p - ptmp;
   2076 
   2077       vassert(cond == TILEGXcc_EQ);
   2078 
   2079       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_BEQZ, 2,
   2080                                           r_src, delta / 8));
   2081    }
   2082     goto done;
   2083   }
   2084 
   2085   case GXin_XDirect: {
   2086     /* NB: what goes on here has to be very closely coordinated
   2087        with the chainXDirect_TILEGX and unchainXDirect_TILEGX below. */
   2088     /* We're generating chain-me requests here, so we need to be
   2089        sure this is actually allowed -- no-redir translations
   2090        can't use chain-me's.  Hence: */
   2091     vassert(disp_cp_chain_me_to_slowEP != NULL);
   2092     vassert(disp_cp_chain_me_to_fastEP != NULL);
   2093 
   2094     /* Use ptmp for backpatching conditional jumps. */
   2095     ptmp = NULL;
   2096 
   2097     /* First, if this is conditional, create a conditional
   2098        jump over the rest of it.  Or at least, leave a space for
   2099        it that we will shortly fill in. */
   2100     if (i->GXin.XDirect.cond != TILEGXcc_AL) {
   2101       vassert(i->GXin.XDirect.cond != TILEGXcc_NV);
   2102       ptmp = p;
   2103       p += 24;
   2104     }
   2105 
   2106     /* Update the guest PC. */
   2107     /* move r11, dstGA */
   2108     /* st   amPC, r11  */
   2109     p = mkLoadImm_EXACTLY4(p, /*r*/ 11, (ULong)i->GXin.XDirect.dstGA);
   2110 
   2111     p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 11,
   2112                                       i->GXin.XDirect.amPC);
   2113 
   2114     /* --- FIRST PATCHABLE BYTE follows --- */
   2115     /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
   2116        calling to) backs up the return address, so as to find the
   2117        address of the first patchable byte.  So: don't change the
   2118        number of instructions (3) below. */
   2119     /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */
   2120     /* jr  r11  */
   2121     void* disp_cp_chain_me
   2122       = i->GXin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
   2123       : disp_cp_chain_me_to_slowEP;
   2124     p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2125                            (Addr)disp_cp_chain_me);
   2126     /* jalr r11 */
   2127     /* nop */
   2128     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2129 
   2130     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2131 
   2132     /* --- END of PATCHABLE BYTES --- */
   2133 
   2134     /* Fix up the conditional jump, if there was one. */
   2135     if (i->GXin.XDirect.cond != TILEGXcc_AL) {
   2136       Int delta = p - ptmp;
   2137       delta = delta / 8 - 3;
   2138 
   2139       /* ld r11, COND_OFFSET(GuestSP=r50)
   2140          beqz r11, delta
   2141       */
   2142       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2143                                           11, 50, COND_OFFSET()));
   2144       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_LD, 2,
   2145                                           11, 11));
   2146 
   2147       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_BEQZ, 2,
   2148                                           11, delta));
   2149 
   2150     }
   2151     goto done;
   2152   }
   2153 
   2154   case GXin_XIndir: {
   2155     /* We're generating transfers that could lead indirectly to a
   2156        chain-me, so we need to be sure this is actually allowed --
   2157        no-redir translations are not allowed to reach normal
   2158        translations without going through the scheduler.  That means
   2159        no XDirects or XIndirs out from no-redir translations.
   2160        Hence: */
   2161     vassert(disp_cp_xindir != NULL);
   2162 
   2163     /* Use ptmp for backpatching conditional jumps. */
   2164     ptmp = NULL;
   2165 
   2166     /* First off, if this is conditional, create a conditional
   2167        jump over the rest of it. */
   2168     if (i->GXin.XIndir.cond != TILEGXcc_AL) {
   2169       vassert(i->GXin.XIndir.cond != TILEGXcc_NV);
   2170       ptmp = p;
   2171       p += 24;
   2172     }
   2173 
   2174     /* Update the guest PC. */
   2175     /* st amPC, dstGA */
   2176     p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
   2177                                       iregNo(i->GXin.XIndir.dstGA),
   2178                                       i->GXin.XIndir.amPC);
   2179 
   2180     /* move r11, VG_(disp_cp_xindir), 4 bundles. */
   2181     /* jalr r11 */
   2182     /* nop */
   2183     p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2184                            (Addr)disp_cp_xindir);
   2185 
   2186     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2187 
   2188     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2189 
   2190     /* Fix up the conditional jump, if there was one. */
   2191     if (i->GXin.XIndir.cond != TILEGXcc_AL) {
   2192       Int delta = p - ptmp;
   2193       delta = delta / 8 - 3;
   2194       vassert(delta > 0 && delta < 40);
   2195 
   2196       /* ld r11, COND_OFFSET($GuestSP)
   2197          beqz r11, delta  */
   2198 
   2199       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2200                                           11, 50, COND_OFFSET()));
   2201       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_LD, 2,
   2202                                           11, 11));
   2203       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_BEQZ, 2,
   2204                                           11, delta));
   2205     }
   2206     goto done;
   2207   }
   2208 
   2209   case GXin_XAssisted: {
   2210     /* First off, if this is conditional, create a conditional jump
   2211        over the rest of it.  Or at least, leave a space for it that
   2212        we will shortly fill in. */
   2213     ptmp = NULL;
   2214     if (i->GXin.XAssisted.cond != TILEGXcc_AL) {
   2215       vassert(i->GXin.XAssisted.cond != TILEGXcc_NV);
   2216       ptmp = p;
   2217       p += 24;
   2218     }
   2219 
   2220     /* Update the guest PC. */
   2221     /* st amPC, dstGA */
   2222     p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
   2223                                       iregNo(i->GXin.XIndir.dstGA),
   2224                                       i->GXin.XIndir.amPC);
   2225 
   2226     UInt trcval = 0;
   2227     switch (i->GXin.XAssisted.jk) {
   2228     case Ijk_ClientReq:     trcval = VEX_TRC_JMP_CLIENTREQ;     break;
   2229     case Ijk_Sys_syscall:   trcval = VEX_TRC_JMP_SYS_SYSCALL;   break;
   2230     case Ijk_Yield:         trcval = VEX_TRC_JMP_YIELD;         break;
   2231     case Ijk_EmWarn:        trcval = VEX_TRC_JMP_EMWARN;        break;
   2232     case Ijk_EmFail:        trcval = VEX_TRC_JMP_EMFAIL;        break;
   2233     case Ijk_NoDecode:      trcval = VEX_TRC_JMP_NODECODE;      break;
   2234     case Ijk_InvalICache:   trcval = VEX_TRC_JMP_INVALICACHE;   break;
   2235     case Ijk_NoRedir:       trcval = VEX_TRC_JMP_NOREDIR;       break;
   2236     case Ijk_SigILL:        trcval = VEX_TRC_JMP_SIGILL;        break;
   2237     case Ijk_SigTRAP:       trcval = VEX_TRC_JMP_SIGTRAP;       break;
   2238     case Ijk_SigBUS:        trcval = VEX_TRC_JMP_SIGBUS;        break;
   2239     case Ijk_SigFPE_IntDiv: trcval = VEX_TRC_JMP_SIGFPE_INTDIV; break;
   2240     case Ijk_SigFPE_IntOvf: trcval = VEX_TRC_JMP_SIGFPE_INTOVF; break;
   2241     case Ijk_Boring:        trcval = VEX_TRC_JMP_BORING;        break;
   2242     case Ijk_Ret:
   2243       {
   2244         /* Tilegx "iret" instruction. */
   2245         trcval = VEX_TRC_JMP_BORING;
   2246         /* Interrupt return "iret", setup the jump address into EX_CONTRXT_0_0.
   2247            Read context_0_1 from guest_state */
   2248         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2249                                       51, 50, OFFSET_EX1));
   2250         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_LD, 2,
   2251                                       11, 51));
   2252         /* Write into host cpu's context_0_1 spr. */
   2253         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MTSPR, 2,
   2254                                       0x2581, 11));
   2255         /* Read context_0_0 from guest_state */
   2256         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2257                                       51, 50, OFFSET_EX0));
   2258         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_LD, 2,
   2259                                       11, 51));
   2260         /* Write into host cpu's context_0_0 spr */
   2261         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_MTSPR, 2,
   2262                                       0x2580, 11));
   2263         /* Update the guest PC  so branch to the iret target address
   2264            in EX_CONTEXT_0. */
   2265         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2266                                       51, 50, 512));
   2267         p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ST, 2,
   2268                                       51, 11));
   2269       }
   2270       break;
   2271       /* We don't expect to see the following being assisted.
   2272          case Ijk_Call:
   2273          fallthrough */
   2274     default:
   2275       ppIRJumpKind(i->GXin.XAssisted.jk);
   2276       vpanic("emit_TILEGXInstr.GXin_XAssisted: unexpected jump kind");
   2277     }
   2278     vassert(trcval != 0);
   2279 
   2280     /* moveli r50, trcval */
   2281 
   2282     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDLI, 3, 50, 63, trcval));
   2283 
   2284     /* move r11, VG_(disp_cp_xassisted) */
   2285 
   2286     p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2287                            (Addr)disp_cp_xassisted);
   2288     /* jalr r11
   2289        nop  */
   2290 
   2291     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2292     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2293 
   2294     /* Fix up the conditional jump, if there was one. */
   2295     if (i->GXin.XAssisted.cond != TILEGXcc_AL) {
   2296       Int delta = p - ptmp;
   2297       delta = delta / 8 - 3;
   2298       vassert(delta > 0 && delta < 40);
   2299 
   2300       /* ld  r11, COND_OFFSET($GuestSP)
   2301          beqz r11, delta
   2302          nop  */
   2303 
   2304       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_ADDLI, 3,
   2305                                           11, 50, COND_OFFSET()));
   2306       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_LD, 2,
   2307                                           11, 11));
   2308       ptmp = mkInsnBin(ptmp, mkTileGxInsn(TILEGX_OPC_BEQZ, 2,
   2309                                           11, delta));
   2310     }
   2311     goto done;
   2312   }
   2313 
   2314   case GXin_EvCheck: {
   2315     /* We generate:
   2316        ld      r11, amCounter
   2317        addi    r11, r11, -1
   2318        st      amCounter, r11
   2319        bgez    r11, nofail
   2320        ld      r11, amFailAddr
   2321        jalr    r11
   2322        nop
   2323        nofail:
   2324     */
   2325     UChar* p0 = p;
   2326     /* ld  r11, amCounter */
   2327     p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 11,
   2328                                       i->GXin.EvCheck.amCounter);
   2329 
   2330     /* addi r11,r11,-1 */
   2331 
   2332     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDI, 3,
   2333                                   11, 11, -1));
   2334 
   2335     /* st amCounter, 11 */
   2336     p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 11,
   2337                                       i->GXin.EvCheck.amCounter);
   2338 
   2339     /* Reserve a bundle, fill it after the do_load_or_store_machine_word.
   2340        since we are not sure how many bundles it takes. */
   2341     UChar* p1 = p;
   2342     p += 8;
   2343     /* bgez t9, nofail */
   2344 
   2345     /* lw/ld r9, amFailAddr */
   2346     p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 11,
   2347                                       i->GXin.EvCheck.amFailAddr);
   2348 
   2349     mkInsnBin(p1, mkTileGxInsn(TILEGX_OPC_BGEZ, 2,
   2350                                11, 2 + (p - p1) / 8));
   2351 
   2352     /* jalr r11 */
   2353 
   2354     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2355 
   2356     /* nop */
   2357     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2358 
   2359     /* nofail: */
   2360 
   2361     /* Crosscheck */
   2362     vassert(evCheckSzB_TILEGX() == (UChar*)p - (UChar*)p0);
   2363     goto done;
   2364   }
   2365 
   2366   case GXin_ProfInc: {
   2367     /* Generate a code template to increment a memory location whose
   2368        address will be known later as an immediate value. This code
   2369        template will be patched once the memory location is known.
   2370        For now we do this with address == 0x65556555. */
   2371     /* 64-bit:
   2372        move r11, 0x6555655565556555ULL
   2373        ld r51, r11
   2374        addi r51, r51, 1
   2375        st  r11, r51
   2376     */
   2377 
   2378     /* move r11, 0x6555655565556555ULL */
   2379     p = mkLoadImm_EXACTLY4(p, /*r*/ 11, 0x6555655565556555ULL);
   2380 
   2381     /* ld r51, r11 */
   2382 
   2383     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_LD, 2, 51, 11));
   2384 
   2385     /* addi r51, r51, 1 */
   2386 
   2387     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ADDI, 3, 51, 51, 1));
   2388 
   2389     /* st r11, r51 */
   2390 
   2391     p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_ST, 2, 11, 51));
   2392 
   2393     /* Tell the caller .. */
   2394     vassert(!(*is_profInc));
   2395     *is_profInc = True;
   2396     goto done;
   2397   }
   2398 
   2399   case GXin_Load: {
   2400     TILEGXAMode *am_addr = i->GXin.Load.src;
   2401     if (am_addr->tag == GXam_IR) {
   2402       UInt r_dst = iregNo(i->GXin.Load.dst);
   2403       UInt opc, sz = i->GXin.Load.sz;
   2404       if ((sz == 4 || sz == 8)) {
   2405         /* should be guaranteed to us by iselWordExpr_AMode */
   2406         vassert(0 == (am_addr->GXam.IR.index & 3));
   2407       }
   2408 
   2409       // Note: Valgrind memory load has no sign-extend. We extend explicitly.
   2410       switch (sz) {
   2411       case 1:
   2412         opc = TILEGX_OPC_LD1U;
   2413         break;
   2414       case 2:
   2415         opc = TILEGX_OPC_LD2U;
   2416         break;
   2417       case 4:
   2418         opc = TILEGX_OPC_LD4U;
   2419         break;
   2420       case 8:
   2421         opc = TILEGX_OPC_LD;
   2422         break;
   2423       default:
   2424         goto bad;
   2425       }
   2426 
   2427       p = doAMode_IR(p, opc, r_dst, am_addr);
   2428       goto done;
   2429 
   2430     }
   2431   }
   2432 
   2433   case GXin_Store: {
   2434     TILEGXAMode *am_addr = i->GXin.Store.dst;
   2435     if (am_addr->tag == GXam_IR) {
   2436       UInt r_src = iregNo(i->GXin.Store.src);
   2437       UInt opc, sz = i->GXin.Store.sz;
   2438       switch (sz) {
   2439       case 1:
   2440         opc = TILEGX_OPC_ST1;
   2441         break;
   2442       case 2:
   2443         opc = TILEGX_OPC_ST2;
   2444         break;
   2445       case 4:
   2446         opc = TILEGX_OPC_ST4;
   2447         break;
   2448       case 8:
   2449         opc = TILEGX_OPC_ST;
   2450         break;
   2451       default:
   2452         goto bad;
   2453       }
   2454 
   2455       p = doAMode_IR(p, opc, r_src, am_addr);
   2456       goto done;
   2457     } else {
   2458       vassert(0);
   2459     }
   2460   }
   2461 
   2462   case GXin_RdWrLR: {
   2463     UInt reg = iregNo(i->GXin.RdWrLR.gpr);
   2464     Bool wrLR = i->GXin.RdWrLR.wrLR;
   2465     if (wrLR)
   2466       p = mkMoveReg(p, 55, reg);
   2467     else
   2468       p = mkMoveReg(p, reg, 55);
   2469     goto done;
   2470   }
   2471 
   2472   default:
   2473     goto bad;
   2474   }
   2475 
   2476  bad:
   2477   vex_printf("\n=> ");
   2478   vpanic("emit_TILEGXInstr");
   2479   /*NOTREACHED*/
   2480 
   2481  done:
   2482   instr_bytes = p - &buf[0];
   2483   /* Instr byte count must be modular of 8. */
   2484   vassert(0 == (instr_bytes & 0x7));
   2485 
   2486   if (  0) {
   2487     Int k;
   2488     for (k = 0; k < instr_bytes; k += 8)
   2489       decode_and_display((ULong *)(Addr)&buf[k], 1, 0);
   2490   }
   2491 
   2492   /* Limit the JIT size. */
   2493   vassert(instr_bytes <= 256);
   2494   return instr_bytes;
   2495 }
   2496 
   2497 
   2498 Int evCheckSzB_TILEGX ( void )
   2499 {
   2500   UInt kInstrSize = 8;
   2501   return 10*kInstrSize;
   2502 }
   2503 
   2504 VexInvalRange chainXDirect_TILEGX ( VexEndness endness_host,
   2505                                     void* place_to_chain,
   2506                                     const void* disp_cp_chain_me_EXPECTED,
   2507                                     const void* place_to_jump_to,
   2508                                     Bool  mode64 )
   2509 {
   2510   vassert(mode64);
   2511   vassert(endness_host == VexEndnessLE);
   2512   /* What we're expecting to see is:
   2513      move r11, disp_cp_chain_me_to_EXPECTED
   2514      jalr r11
   2515      nop
   2516      viz
   2517      <32 bytes generated by mkLoadImm_EXACTLY4>
   2518      jalr r11
   2519      nop
   2520   */
   2521   UChar* p = (UChar*)place_to_chain;
   2522   vassert(0 == (7 & (HWord)p));
   2523 
   2524 #ifdef TILEGX_DEBUG
   2525   vex_printf("chainXDirect_TILEGX: disp_cp_chain_me_EXPECTED=%p\n",
   2526              disp_cp_chain_me_EXPECTED);
   2527   decode_and_display(p, 6, p);
   2528 
   2529   vex_printf("chainXDirect_TILEGX: place_to_jump_to=%p\n",
   2530              place_to_jump_to);
   2531 #endif
   2532 
   2533   /* And what we want to change it to is either:
   2534      move r11, place_to_jump_to
   2535      jalr r11
   2536      nop
   2537      viz
   2538      <32 bytes generated by mkLoadImm_EXACTLY4>
   2539      jalr r11
   2540      nop
   2541 
   2542      The replacement has the same length as the original.
   2543   */
   2544 
   2545   p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2546                          (Addr)place_to_jump_to);
   2547 
   2548 
   2549   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2550 
   2551   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2552 
   2553 #ifdef TILEGX_DEBUG
   2554   decode_and_display((UChar*)place_to_chain, 8, place_to_chain);
   2555 #endif
   2556 
   2557   Int len = p - (UChar*)place_to_chain;
   2558   vassert(len == 48); /* stay sane */
   2559   VexInvalRange vir = {(HWord)place_to_chain, len};
   2560   return vir;
   2561 }
   2562 
   2563 VexInvalRange unchainXDirect_TILEGX ( VexEndness endness_host,
   2564                                       void* place_to_unchain,
   2565                                       const void* place_to_jump_to_EXPECTED,
   2566                                       const void* disp_cp_chain_me,
   2567                                       Bool  mode64 )
   2568 {
   2569   vassert(mode64);
   2570   vassert(endness_host == VexEndnessLE);
   2571   /* What we're expecting to see is:
   2572      move r11, place_to_jump_to_EXPECTED
   2573      jalr r11
   2574      nop
   2575      viz
   2576      <32 bytes generated by mkLoadImm_EXACTLY4>
   2577      jalr r11
   2578      nop
   2579   */
   2580   UChar* p = (UChar*)place_to_unchain;
   2581   vassert(0 == (7 & (HWord)p));
   2582 
   2583   /* And what we want to change it to is:
   2584      move r11, disp_cp_chain_me
   2585      jalr r11
   2586      nop
   2587      viz
   2588      <32 bytes generated by mkLoadImm_EXACTLY4>
   2589      jalr r11
   2590      nop
   2591      The replacement has the same length as the original.
   2592   */
   2593   p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2594                          (Addr)disp_cp_chain_me);
   2595 
   2596 
   2597   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_JALR, 1, 11));
   2598 
   2599   p = mkInsnBin(p, mkTileGxInsn(TILEGX_OPC_NOP, 0));
   2600 
   2601   Int len = p - (UChar*)place_to_unchain;
   2602   vassert(len == 48); /* stay sane */
   2603   VexInvalRange vir = {(HWord)place_to_unchain, len};
   2604   return vir;
   2605 }
   2606 
   2607 /* Patch the counter address into a profile inc point, as previously
   2608    created by the GXin_ProfInc case for emit_TILEGXInstr. */
   2609 VexInvalRange patchProfInc_TILEGX ( VexEndness endness_host,
   2610                                     void*  place_to_patch,
   2611                                     const ULong* location_of_counter,
   2612                                     Bool mode64 )
   2613 {
   2614   vassert(mode64);
   2615   vassert(endness_host == VexEndnessLE);
   2616   UChar* p = (UChar*)place_to_patch;
   2617   vassert(0 == (7 & (HWord)p));
   2618 
   2619   p = mkLoadImm_EXACTLY4(p, /*r*/ 11,
   2620                          (Addr)location_of_counter);
   2621 
   2622   VexInvalRange vir = {(HWord)p, 32};
   2623   return vir;
   2624 }
   2625 
   2626 /*---------------------------------------------------------------*/
   2627 /*--- end                                    host_tilegx_defs.c ---*/
   2628 /*---------------------------------------------------------------*/
   2629