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