1 2 /*---------------------------------------------------------------*/ 3 /*--- begin host_ppc_defs.c ---*/ 4 /*---------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2010 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 #include "libvex_basictypes.h" 37 #include "libvex.h" 38 #include "libvex_trc_values.h" 39 40 #include "main_util.h" 41 #include "host_generic_regs.h" 42 #include "host_ppc_defs.h" 43 44 45 /* --------- Registers. --------- */ 46 47 void ppHRegPPC ( HReg reg ) 48 { 49 Int r; 50 static HChar* ireg32_names[32] 51 = { "%r0", "%r1", "%r2", "%r3", 52 "%r4", "%r5", "%r6", "%r7", 53 "%r8", "%r9", "%r10", "%r11", 54 "%r12", "%r13", "%r14", "%r15", 55 "%r16", "%r17", "%r18", "%r19", 56 "%r20", "%r21", "%r22", "%r23", 57 "%r24", "%r25", "%r26", "%r27", 58 "%r28", "%r29", "%r30", "%r31" }; 59 /* Be generic for all virtual regs. */ 60 if (hregIsVirtual(reg)) { 61 ppHReg(reg); 62 return; 63 } 64 /* But specific for real regs. */ 65 switch (hregClass(reg)) { 66 case HRcInt64: 67 r = hregNumber(reg); 68 vassert(r >= 0 && r < 32); 69 vex_printf("%s", ireg32_names[r]); 70 return; 71 case HRcInt32: 72 r = hregNumber(reg); 73 vassert(r >= 0 && r < 32); 74 vex_printf("%s", ireg32_names[r]); 75 return; 76 case HRcFlt64: 77 r = hregNumber(reg); 78 vassert(r >= 0 && r < 32); 79 vex_printf("%%fr%d", r); 80 return; 81 case HRcVec128: 82 r = hregNumber(reg); 83 vassert(r >= 0 && r < 32); 84 vex_printf("%%v%d", r); 85 return; 86 default: 87 vpanic("ppHRegPPC"); 88 } 89 } 90 91 92 #define MkHRegGPR(_n, _mode64) \ 93 mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False) 94 95 HReg hregPPC_GPR0 ( Bool mode64 ) { return MkHRegGPR( 0, mode64); } 96 HReg hregPPC_GPR1 ( Bool mode64 ) { return MkHRegGPR( 1, mode64); } 97 HReg hregPPC_GPR2 ( Bool mode64 ) { return MkHRegGPR( 2, mode64); } 98 HReg hregPPC_GPR3 ( Bool mode64 ) { return MkHRegGPR( 3, mode64); } 99 HReg hregPPC_GPR4 ( Bool mode64 ) { return MkHRegGPR( 4, mode64); } 100 HReg hregPPC_GPR5 ( Bool mode64 ) { return MkHRegGPR( 5, mode64); } 101 HReg hregPPC_GPR6 ( Bool mode64 ) { return MkHRegGPR( 6, mode64); } 102 HReg hregPPC_GPR7 ( Bool mode64 ) { return MkHRegGPR( 7, mode64); } 103 HReg hregPPC_GPR8 ( Bool mode64 ) { return MkHRegGPR( 8, mode64); } 104 HReg hregPPC_GPR9 ( Bool mode64 ) { return MkHRegGPR( 9, mode64); } 105 HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); } 106 HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); } 107 HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); } 108 HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); } 109 HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); } 110 HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); } 111 HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); } 112 HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); } 113 HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); } 114 HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); } 115 HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); } 116 HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); } 117 HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); } 118 HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); } 119 HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); } 120 HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); } 121 HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); } 122 HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); } 123 HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); } 124 HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); } 125 HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); } 126 HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); } 127 128 #undef MK_INT_HREG 129 130 HReg hregPPC_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); } 131 HReg hregPPC_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); } 132 HReg hregPPC_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); } 133 HReg hregPPC_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); } 134 HReg hregPPC_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); } 135 HReg hregPPC_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); } 136 HReg hregPPC_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); } 137 HReg hregPPC_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); } 138 HReg hregPPC_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); } 139 HReg hregPPC_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); } 140 HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); } 141 HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); } 142 HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); } 143 HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); } 144 HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); } 145 HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); } 146 HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); } 147 HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); } 148 HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); } 149 HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); } 150 HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); } 151 HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); } 152 HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); } 153 HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); } 154 HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); } 155 HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); } 156 HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); } 157 HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); } 158 HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); } 159 HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); } 160 HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); } 161 HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); } 162 163 HReg hregPPC_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); } 164 HReg hregPPC_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); } 165 HReg hregPPC_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); } 166 HReg hregPPC_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); } 167 HReg hregPPC_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); } 168 HReg hregPPC_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); } 169 HReg hregPPC_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); } 170 HReg hregPPC_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); } 171 HReg hregPPC_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); } 172 HReg hregPPC_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); } 173 HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); } 174 HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); } 175 HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); } 176 HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); } 177 HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); } 178 HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); } 179 HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); } 180 HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); } 181 HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); } 182 HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); } 183 HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); } 184 HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); } 185 HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); } 186 HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); } 187 HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); } 188 HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); } 189 HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); } 190 HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); } 191 HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); } 192 HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); } 193 HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); } 194 HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); } 195 196 void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 ) 197 { 198 UInt i=0; 199 if (mode64) 200 *nregs = (32-9) + (32-24) + (32-24); 201 else 202 *nregs = (32-7) + (32-24) + (32-24); 203 *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); 204 // GPR0 = scratch reg where poss. - some ops interpret as value zero 205 // GPR1 = stack pointer 206 // GPR2 = TOC pointer 207 (*arr)[i++] = hregPPC_GPR3(mode64); 208 (*arr)[i++] = hregPPC_GPR4(mode64); 209 (*arr)[i++] = hregPPC_GPR5(mode64); 210 (*arr)[i++] = hregPPC_GPR6(mode64); 211 (*arr)[i++] = hregPPC_GPR7(mode64); 212 (*arr)[i++] = hregPPC_GPR8(mode64); 213 (*arr)[i++] = hregPPC_GPR9(mode64); 214 (*arr)[i++] = hregPPC_GPR10(mode64); 215 if (!mode64) { 216 /* in mode64: 217 r11 used for calls by ptr / env ptr for some langs 218 r12 used for exception handling and global linkage code */ 219 (*arr)[i++] = hregPPC_GPR11(mode64); 220 (*arr)[i++] = hregPPC_GPR12(mode64); 221 } 222 // GPR13 = thread specific pointer 223 // GPR14 and above are callee save. Yay. 224 (*arr)[i++] = hregPPC_GPR14(mode64); 225 (*arr)[i++] = hregPPC_GPR15(mode64); 226 (*arr)[i++] = hregPPC_GPR16(mode64); 227 (*arr)[i++] = hregPPC_GPR17(mode64); 228 (*arr)[i++] = hregPPC_GPR18(mode64); 229 (*arr)[i++] = hregPPC_GPR19(mode64); 230 (*arr)[i++] = hregPPC_GPR20(mode64); 231 (*arr)[i++] = hregPPC_GPR21(mode64); 232 (*arr)[i++] = hregPPC_GPR22(mode64); 233 (*arr)[i++] = hregPPC_GPR23(mode64); 234 (*arr)[i++] = hregPPC_GPR24(mode64); 235 (*arr)[i++] = hregPPC_GPR25(mode64); 236 (*arr)[i++] = hregPPC_GPR26(mode64); 237 (*arr)[i++] = hregPPC_GPR27(mode64); 238 (*arr)[i++] = hregPPC_GPR28(mode64); 239 // GPR29 is reserved for the dispatcher 240 // GPR30 is reserved as AltiVec spill reg temporary 241 // GPR31 is reserved for the GuestStatePtr 242 243 /* Don't waste the reg-allocs's time trawling through zillions of 244 FP registers - they mostly will never be used. We'll tolerate 245 the occasional extra spill instead. */ 246 /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save. 247 So use them. */ 248 (*arr)[i++] = hregPPC_FPR14(); 249 (*arr)[i++] = hregPPC_FPR15(); 250 (*arr)[i++] = hregPPC_FPR16(); 251 (*arr)[i++] = hregPPC_FPR17(); 252 (*arr)[i++] = hregPPC_FPR18(); 253 (*arr)[i++] = hregPPC_FPR19(); 254 (*arr)[i++] = hregPPC_FPR20(); 255 (*arr)[i++] = hregPPC_FPR21(); 256 257 /* Same deal re Altivec */ 258 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save. 259 So use them. */ 260 /* NB, vr29 is used as a scratch temporary -- do not allocate */ 261 (*arr)[i++] = hregPPC_VR20(); 262 (*arr)[i++] = hregPPC_VR21(); 263 (*arr)[i++] = hregPPC_VR22(); 264 (*arr)[i++] = hregPPC_VR23(); 265 (*arr)[i++] = hregPPC_VR24(); 266 (*arr)[i++] = hregPPC_VR25(); 267 (*arr)[i++] = hregPPC_VR26(); 268 (*arr)[i++] = hregPPC_VR27(); 269 270 vassert(i == *nregs); 271 } 272 273 274 /* --------- Condition codes, Intel encoding. --------- */ 275 276 HChar* showPPCCondCode ( PPCCondCode cond ) 277 { 278 if (cond.test == Pct_ALWAYS) return "always"; 279 280 switch (cond.flag) { 281 case Pcf_7SO: 282 return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0"; 283 case Pcf_7EQ: 284 return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0"; 285 case Pcf_7GT: 286 return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0"; 287 case Pcf_7LT: 288 return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0"; 289 default: vpanic("ppPPCCondCode"); 290 } 291 } 292 293 /* construct condition code */ 294 PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag ) 295 { 296 PPCCondCode cc; 297 cc.flag = flag; 298 cc.test = test; 299 return cc; 300 } 301 302 /* false->true, true->false */ 303 PPCCondTest invertCondTest ( PPCCondTest ct ) 304 { 305 vassert(ct != Pct_ALWAYS); 306 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE; 307 } 308 309 310 /* --------- PPCAMode: memory address expressions. --------- */ 311 312 PPCAMode* PPCAMode_IR ( Int idx, HReg base ) { 313 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode)); 314 vassert(idx >= -0x8000 && idx < 0x8000); 315 am->tag = Pam_IR; 316 am->Pam.IR.base = base; 317 am->Pam.IR.index = idx; 318 return am; 319 } 320 PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) { 321 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode)); 322 am->tag = Pam_RR; 323 am->Pam.RR.base = base; 324 am->Pam.RR.index = idx; 325 return am; 326 } 327 328 PPCAMode* dopyPPCAMode ( PPCAMode* am ) { 329 switch (am->tag) { 330 case Pam_IR: 331 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base ); 332 case Pam_RR: 333 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base ); 334 default: 335 vpanic("dopyPPCAMode"); 336 } 337 } 338 339 void ppPPCAMode ( PPCAMode* am ) { 340 switch (am->tag) { 341 case Pam_IR: 342 if (am->Pam.IR.index == 0) 343 vex_printf("0("); 344 else 345 vex_printf("%d(", (Int)am->Pam.IR.index); 346 ppHRegPPC(am->Pam.IR.base); 347 vex_printf(")"); 348 return; 349 case Pam_RR: 350 ppHRegPPC(am->Pam.RR.base); 351 vex_printf(","); 352 ppHRegPPC(am->Pam.RR.index); 353 return; 354 default: 355 vpanic("ppPPCAMode"); 356 } 357 } 358 359 static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) { 360 switch (am->tag) { 361 case Pam_IR: 362 addHRegUse(u, HRmRead, am->Pam.IR.base); 363 return; 364 case Pam_RR: 365 addHRegUse(u, HRmRead, am->Pam.RR.base); 366 addHRegUse(u, HRmRead, am->Pam.RR.index); 367 return; 368 default: 369 vpanic("addRegUsage_PPCAMode"); 370 } 371 } 372 373 static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) { 374 switch (am->tag) { 375 case Pam_IR: 376 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base); 377 return; 378 case Pam_RR: 379 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base); 380 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index); 381 return; 382 default: 383 vpanic("mapRegs_PPCAMode"); 384 } 385 } 386 387 /* --------- Operand, which can be a reg or a u16/s16. --------- */ 388 389 PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) { 390 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH)); 391 op->tag = Prh_Imm; 392 op->Prh.Imm.syned = syned; 393 op->Prh.Imm.imm16 = imm16; 394 /* If this is a signed value, ensure it's not -32768, so that we 395 are guaranteed always to be able to negate if needed. */ 396 if (syned) 397 vassert(imm16 != 0x8000); 398 vassert(syned == True || syned == False); 399 return op; 400 } 401 PPCRH* PPCRH_Reg ( HReg reg ) { 402 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH)); 403 op->tag = Prh_Reg; 404 op->Prh.Reg.reg = reg; 405 return op; 406 } 407 408 void ppPPCRH ( PPCRH* op ) { 409 switch (op->tag) { 410 case Prh_Imm: 411 if (op->Prh.Imm.syned) 412 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16); 413 else 414 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16); 415 return; 416 case Prh_Reg: 417 ppHRegPPC(op->Prh.Reg.reg); 418 return; 419 default: 420 vpanic("ppPPCRH"); 421 } 422 } 423 424 /* An PPCRH can only be used in a "read" context (what would it mean 425 to write or modify a literal?) and so we enumerate its registers 426 accordingly. */ 427 static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) { 428 switch (op->tag) { 429 case Prh_Imm: 430 return; 431 case Prh_Reg: 432 addHRegUse(u, HRmRead, op->Prh.Reg.reg); 433 return; 434 default: 435 vpanic("addRegUsage_PPCRH"); 436 } 437 } 438 439 static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) { 440 switch (op->tag) { 441 case Prh_Imm: 442 return; 443 case Prh_Reg: 444 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg); 445 return; 446 default: 447 vpanic("mapRegs_PPCRH"); 448 } 449 } 450 451 452 /* --------- Operand, which can be a reg or a u32/64. --------- */ 453 454 PPCRI* PPCRI_Imm ( ULong imm64 ) { 455 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI)); 456 op->tag = Pri_Imm; 457 op->Pri.Imm = imm64; 458 return op; 459 } 460 PPCRI* PPCRI_Reg ( HReg reg ) { 461 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI)); 462 op->tag = Pri_Reg; 463 op->Pri.Reg = reg; 464 return op; 465 } 466 467 void ppPPCRI ( PPCRI* dst ) { 468 switch (dst->tag) { 469 case Pri_Imm: 470 vex_printf("0x%llx", dst->Pri.Imm); 471 break; 472 case Pri_Reg: 473 ppHRegPPC(dst->Pri.Reg); 474 break; 475 default: 476 vpanic("ppPPCRI"); 477 } 478 } 479 480 /* An PPCRI can only be used in a "read" context (what would it 481 mean to write or modify a literal?) and so we enumerate its 482 registers accordingly. */ 483 static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) { 484 switch (dst->tag) { 485 case Pri_Imm: 486 return; 487 case Pri_Reg: 488 addHRegUse(u, HRmRead, dst->Pri.Reg); 489 return; 490 default: 491 vpanic("addRegUsage_PPCRI"); 492 } 493 } 494 495 static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) { 496 switch (dst->tag) { 497 case Pri_Imm: 498 return; 499 case Pri_Reg: 500 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg); 501 return; 502 default: 503 vpanic("mapRegs_PPCRI"); 504 } 505 } 506 507 508 /* --------- Operand, which can be a vector reg or a simm5. --------- */ 509 510 PPCVI5s* PPCVI5s_Imm ( Char simm5 ) { 511 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s)); 512 op->tag = Pvi_Imm; 513 op->Pvi.Imm5s = simm5; 514 vassert(simm5 >= -16 && simm5 <= 15); 515 return op; 516 } 517 PPCVI5s* PPCVI5s_Reg ( HReg reg ) { 518 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s)); 519 op->tag = Pvi_Reg; 520 op->Pvi.Reg = reg; 521 vassert(hregClass(reg) == HRcVec128); 522 return op; 523 } 524 525 void ppPPCVI5s ( PPCVI5s* src ) { 526 switch (src->tag) { 527 case Pvi_Imm: 528 vex_printf("%d", (Int)src->Pvi.Imm5s); 529 break; 530 case Pvi_Reg: 531 ppHRegPPC(src->Pvi.Reg); 532 break; 533 default: 534 vpanic("ppPPCVI5s"); 535 } 536 } 537 538 /* An PPCVI5s can only be used in a "read" context (what would it 539 mean to write or modify a literal?) and so we enumerate its 540 registers accordingly. */ 541 static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) { 542 switch (dst->tag) { 543 case Pvi_Imm: 544 return; 545 case Pvi_Reg: 546 addHRegUse(u, HRmRead, dst->Pvi.Reg); 547 return; 548 default: 549 vpanic("addRegUsage_PPCVI5s"); 550 } 551 } 552 553 static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) { 554 switch (dst->tag) { 555 case Pvi_Imm: 556 return; 557 case Pvi_Reg: 558 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg); 559 return; 560 default: 561 vpanic("mapRegs_PPCVI5s"); 562 } 563 } 564 565 566 /* --------- Instructions. --------- */ 567 568 HChar* showPPCUnaryOp ( PPCUnaryOp op ) { 569 switch (op) { 570 case Pun_NOT: return "not"; 571 case Pun_NEG: return "neg"; 572 case Pun_CLZ32: return "cntlzw"; 573 case Pun_CLZ64: return "cntlzd"; 574 case Pun_EXTSW: return "extsw"; 575 default: vpanic("showPPCUnaryOp"); 576 } 577 } 578 579 HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) { 580 switch (op) { 581 case Palu_ADD: return immR ? "addi" : "add"; 582 case Palu_SUB: return immR ? "subi" : "sub"; 583 case Palu_AND: return immR ? "andi." : "and"; 584 case Palu_OR: return immR ? "ori" : "or"; 585 case Palu_XOR: return immR ? "xori" : "xor"; 586 default: vpanic("showPPCAluOp"); 587 } 588 } 589 590 HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) { 591 switch (op) { 592 case Pshft_SHL: return sz32 ? (immR ? "slwi" : "slw") : 593 (immR ? "sldi" : "sld"); 594 case Pshft_SHR: return sz32 ? (immR ? "srwi" : "srw") : 595 (immR ? "srdi" : "srd"); 596 case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") : 597 (immR ? "sradi" : "srad"); 598 default: vpanic("showPPCShftOp"); 599 } 600 } 601 602 HChar* showPPCFpOp ( PPCFpOp op ) { 603 switch (op) { 604 case Pfp_ADDD: return "fadd"; 605 case Pfp_SUBD: return "fsub"; 606 case Pfp_MULD: return "fmul"; 607 case Pfp_DIVD: return "fdiv"; 608 case Pfp_MADDD: return "fmadd"; 609 case Pfp_MSUBD: return "fmsub"; 610 case Pfp_MADDS: return "fmadds"; 611 case Pfp_MSUBS: return "fmsubs"; 612 case Pfp_ADDS: return "fadds"; 613 case Pfp_SUBS: return "fsubs"; 614 case Pfp_MULS: return "fmuls"; 615 case Pfp_DIVS: return "fdivs"; 616 case Pfp_SQRT: return "fsqrt"; 617 case Pfp_ABS: return "fabs"; 618 case Pfp_NEG: return "fneg"; 619 case Pfp_MOV: return "fmr"; 620 case Pfp_RES: return "fres"; 621 case Pfp_RSQRTE: return "frsqrte"; 622 case Pfp_FRIM: return "frim"; 623 case Pfp_FRIN: return "frin"; 624 case Pfp_FRIP: return "frip"; 625 case Pfp_FRIZ: return "friz"; 626 default: vpanic("showPPCFpOp"); 627 } 628 } 629 630 HChar* showPPCAvOp ( PPCAvOp op ) { 631 switch (op) { 632 633 /* Unary */ 634 case Pav_MOV: return "vmr"; /* Mov */ 635 636 case Pav_AND: return "vand"; /* Bitwise */ 637 case Pav_OR: return "vor"; 638 case Pav_XOR: return "vxor"; 639 case Pav_NOT: return "vnot"; 640 641 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */ 642 case Pav_UNPCKH16S: return "vupkhsh"; 643 case Pav_UNPCKL8S: return "vupklsb"; 644 case Pav_UNPCKL16S: return "vupklsh"; 645 case Pav_UNPCKHPIX: return "vupkhpx"; 646 case Pav_UNPCKLPIX: return "vupklpx"; 647 648 /* Integer binary */ 649 case Pav_ADDU: return "vaddu_m"; // b,h,w 650 case Pav_QADDU: return "vaddu_s"; // b,h,w 651 case Pav_QADDS: return "vadds_s"; // b,h,w 652 653 case Pav_SUBU: return "vsubu_m"; // b,h,w 654 case Pav_QSUBU: return "vsubu_s"; // b,h,w 655 case Pav_QSUBS: return "vsubs_s"; // b,h,w 656 657 case Pav_OMULU: return "vmulou"; // b,h 658 case Pav_OMULS: return "vmulos"; // b,h 659 case Pav_EMULU: return "vmuleu"; // b,h 660 case Pav_EMULS: return "vmules"; // b,h 661 662 case Pav_AVGU: return "vavgu"; // b,h,w 663 case Pav_AVGS: return "vavgs"; // b,h,w 664 665 case Pav_MAXU: return "vmaxu"; // b,h,w 666 case Pav_MAXS: return "vmaxs"; // b,h,w 667 668 case Pav_MINU: return "vminu"; // b,h,w 669 case Pav_MINS: return "vmins"; // b,h,w 670 671 /* Compare (always affects CR field 6) */ 672 case Pav_CMPEQU: return "vcmpequ"; // b,h,w 673 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w 674 case Pav_CMPGTS: return "vcmpgts"; // b,h,w 675 676 /* Shift */ 677 case Pav_SHL: return "vsl"; // ' ',b,h,w 678 case Pav_SHR: return "vsr"; // ' ',b,h,w 679 case Pav_SAR: return "vsra"; // b,h,w 680 case Pav_ROTL: return "vrl"; // b,h,w 681 682 /* Pack */ 683 case Pav_PACKUU: return "vpku_um"; // h,w 684 case Pav_QPACKUU: return "vpku_us"; // h,w 685 case Pav_QPACKSU: return "vpks_us"; // h,w 686 case Pav_QPACKSS: return "vpks_ss"; // h,w 687 case Pav_PACKPXL: return "vpkpx"; 688 689 /* Merge */ 690 case Pav_MRGHI: return "vmrgh"; // b,h,w 691 case Pav_MRGLO: return "vmrgl"; // b,h,w 692 693 default: vpanic("showPPCAvOp"); 694 } 695 } 696 697 HChar* showPPCAvFpOp ( PPCAvFpOp op ) { 698 switch (op) { 699 /* Floating Point Binary */ 700 case Pavfp_ADDF: return "vaddfp"; 701 case Pavfp_SUBF: return "vsubfp"; 702 case Pavfp_MULF: return "vmaddfp"; 703 case Pavfp_MAXF: return "vmaxfp"; 704 case Pavfp_MINF: return "vminfp"; 705 case Pavfp_CMPEQF: return "vcmpeqfp"; 706 case Pavfp_CMPGTF: return "vcmpgtfp"; 707 case Pavfp_CMPGEF: return "vcmpgefp"; 708 709 /* Floating Point Unary */ 710 case Pavfp_RCPF: return "vrefp"; 711 case Pavfp_RSQRTF: return "vrsqrtefp"; 712 case Pavfp_CVTU2F: return "vcfux"; 713 case Pavfp_CVTS2F: return "vcfsx"; 714 case Pavfp_QCVTF2U: return "vctuxs"; 715 case Pavfp_QCVTF2S: return "vctsxs"; 716 case Pavfp_ROUNDM: return "vrfim"; 717 case Pavfp_ROUNDP: return "vrfip"; 718 case Pavfp_ROUNDN: return "vrfin"; 719 case Pavfp_ROUNDZ: return "vrfiz"; 720 721 default: vpanic("showPPCAvFpOp"); 722 } 723 } 724 725 PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 ) 726 { 727 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 728 i->tag = Pin_LI; 729 i->Pin.LI.dst = dst; 730 i->Pin.LI.imm64 = imm64; 731 if (!mode64) 732 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 ); 733 return i; 734 } 735 PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst, 736 HReg srcL, PPCRH* srcR ) { 737 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 738 i->tag = Pin_Alu; 739 i->Pin.Alu.op = op; 740 i->Pin.Alu.dst = dst; 741 i->Pin.Alu.srcL = srcL; 742 i->Pin.Alu.srcR = srcR; 743 return i; 744 } 745 PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32, 746 HReg dst, HReg srcL, PPCRH* srcR ) { 747 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 748 i->tag = Pin_Shft; 749 i->Pin.Shft.op = op; 750 i->Pin.Shft.sz32 = sz32; 751 i->Pin.Shft.dst = dst; 752 i->Pin.Shft.srcL = srcL; 753 i->Pin.Shft.srcR = srcR; 754 return i; 755 } 756 PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC, 757 HReg dst, HReg srcL, HReg srcR ) { 758 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 759 i->tag = Pin_AddSubC; 760 i->Pin.AddSubC.isAdd = isAdd; 761 i->Pin.AddSubC.setC = setC; 762 i->Pin.AddSubC.dst = dst; 763 i->Pin.AddSubC.srcL = srcL; 764 i->Pin.AddSubC.srcR = srcR; 765 return i; 766 } 767 PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32, 768 UInt crfD, HReg srcL, PPCRH* srcR ) { 769 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 770 i->tag = Pin_Cmp; 771 i->Pin.Cmp.syned = syned; 772 i->Pin.Cmp.sz32 = sz32; 773 i->Pin.Cmp.crfD = crfD; 774 i->Pin.Cmp.srcL = srcL; 775 i->Pin.Cmp.srcR = srcR; 776 return i; 777 } 778 PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) { 779 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 780 i->tag = Pin_Unary; 781 i->Pin.Unary.op = op; 782 i->Pin.Unary.dst = dst; 783 i->Pin.Unary.src = src; 784 return i; 785 } 786 PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32, 787 HReg dst, HReg srcL, HReg srcR ) { 788 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 789 i->tag = Pin_MulL; 790 i->Pin.MulL.syned = syned; 791 i->Pin.MulL.hi = hi; 792 i->Pin.MulL.sz32 = sz32; 793 i->Pin.MulL.dst = dst; 794 i->Pin.MulL.srcL = srcL; 795 i->Pin.MulL.srcR = srcR; 796 /* if doing the low word, the signedness is irrelevant, but tie it 797 down anyway. */ 798 if (!hi) vassert(!syned); 799 return i; 800 } 801 PPCInstr* PPCInstr_Div ( Bool syned, Bool sz32, 802 HReg dst, HReg srcL, HReg srcR ) { 803 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 804 i->tag = Pin_Div; 805 i->Pin.Div.syned = syned; 806 i->Pin.Div.sz32 = sz32; 807 i->Pin.Div.dst = dst; 808 i->Pin.Div.srcL = srcL; 809 i->Pin.Div.srcR = srcR; 810 return i; 811 } 812 PPCInstr* PPCInstr_Call ( PPCCondCode cond, 813 Addr64 target, UInt argiregs ) { 814 UInt mask; 815 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 816 i->tag = Pin_Call; 817 i->Pin.Call.cond = cond; 818 i->Pin.Call.target = target; 819 i->Pin.Call.argiregs = argiregs; 820 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */ 821 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10); 822 vassert(0 == (argiregs & ~mask)); 823 return i; 824 } 825 PPCInstr* PPCInstr_Goto ( IRJumpKind jk, 826 PPCCondCode cond, PPCRI* dst ) { 827 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 828 i->tag = Pin_Goto; 829 i->Pin.Goto.cond = cond; 830 i->Pin.Goto.dst = dst; 831 i->Pin.Goto.jk = jk; 832 return i; 833 } 834 PPCInstr* PPCInstr_CMov ( PPCCondCode cond, 835 HReg dst, PPCRI* src ) { 836 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 837 i->tag = Pin_CMov; 838 i->Pin.CMov.cond = cond; 839 i->Pin.CMov.src = src; 840 i->Pin.CMov.dst = dst; 841 vassert(cond.test != Pct_ALWAYS); 842 return i; 843 } 844 PPCInstr* PPCInstr_Load ( UChar sz, 845 HReg dst, PPCAMode* src, Bool mode64 ) { 846 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 847 i->tag = Pin_Load; 848 i->Pin.Load.sz = sz; 849 i->Pin.Load.src = src; 850 i->Pin.Load.dst = dst; 851 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 852 if (sz == 8) vassert(mode64); 853 return i; 854 } 855 PPCInstr* PPCInstr_LoadL ( UChar sz, 856 HReg dst, HReg src, Bool mode64 ) 857 { 858 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 859 i->tag = Pin_LoadL; 860 i->Pin.LoadL.sz = sz; 861 i->Pin.LoadL.src = src; 862 i->Pin.LoadL.dst = dst; 863 vassert(sz == 4 || sz == 8); 864 if (sz == 8) vassert(mode64); 865 return i; 866 } 867 PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src, 868 Bool mode64 ) { 869 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 870 i->tag = Pin_Store; 871 i->Pin.Store.sz = sz; 872 i->Pin.Store.src = src; 873 i->Pin.Store.dst = dst; 874 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 875 if (sz == 8) vassert(mode64); 876 return i; 877 } 878 PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) { 879 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 880 i->tag = Pin_StoreC; 881 i->Pin.StoreC.sz = sz; 882 i->Pin.StoreC.src = src; 883 i->Pin.StoreC.dst = dst; 884 vassert(sz == 4 || sz == 8); 885 if (sz == 8) vassert(mode64); 886 return i; 887 } 888 PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) { 889 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 890 i->tag = Pin_Set; 891 i->Pin.Set.cond = cond; 892 i->Pin.Set.dst = dst; 893 return i; 894 } 895 PPCInstr* PPCInstr_MfCR ( HReg dst ) 896 { 897 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 898 i->tag = Pin_MfCR; 899 i->Pin.MfCR.dst = dst; 900 return i; 901 } 902 PPCInstr* PPCInstr_MFence ( void ) 903 { 904 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 905 i->tag = Pin_MFence; 906 return i; 907 } 908 909 PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) { 910 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 911 i->tag = Pin_FpUnary; 912 i->Pin.FpUnary.op = op; 913 i->Pin.FpUnary.dst = dst; 914 i->Pin.FpUnary.src = src; 915 return i; 916 } 917 PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst, 918 HReg srcL, HReg srcR ) { 919 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 920 i->tag = Pin_FpBinary; 921 i->Pin.FpBinary.op = op; 922 i->Pin.FpBinary.dst = dst; 923 i->Pin.FpBinary.srcL = srcL; 924 i->Pin.FpBinary.srcR = srcR; 925 return i; 926 } 927 PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML, 928 HReg srcMR, HReg srcAcc ) 929 { 930 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 931 i->tag = Pin_FpMulAcc; 932 i->Pin.FpMulAcc.op = op; 933 i->Pin.FpMulAcc.dst = dst; 934 i->Pin.FpMulAcc.srcML = srcML; 935 i->Pin.FpMulAcc.srcMR = srcMR; 936 i->Pin.FpMulAcc.srcAcc = srcAcc; 937 return i; 938 } 939 PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz, 940 HReg reg, PPCAMode* addr ) { 941 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 942 i->tag = Pin_FpLdSt; 943 i->Pin.FpLdSt.isLoad = isLoad; 944 i->Pin.FpLdSt.sz = sz; 945 i->Pin.FpLdSt.reg = reg; 946 i->Pin.FpLdSt.addr = addr; 947 vassert(sz == 4 || sz == 8); 948 return i; 949 } 950 PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data ) 951 { 952 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 953 i->tag = Pin_FpSTFIW; 954 i->Pin.FpSTFIW.addr = addr; 955 i->Pin.FpSTFIW.data = data; 956 return i; 957 } 958 PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) { 959 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 960 i->tag = Pin_FpRSP; 961 i->Pin.FpRSP.dst = dst; 962 i->Pin.FpRSP.src = src; 963 return i; 964 } 965 PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, 966 HReg dst, HReg src ) { 967 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 968 i->tag = Pin_FpCftI; 969 i->Pin.FpCftI.fromI = fromI; 970 i->Pin.FpCftI.int32 = int32; 971 i->Pin.FpCftI.dst = dst; 972 i->Pin.FpCftI.src = src; 973 vassert(!(int32 && fromI)); /* no such insn ("fcfiw"). */ 974 return i; 975 } 976 PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) { 977 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 978 i->tag = Pin_FpCMov; 979 i->Pin.FpCMov.cond = cond; 980 i->Pin.FpCMov.dst = dst; 981 i->Pin.FpCMov.src = src; 982 vassert(cond.test != Pct_ALWAYS); 983 return i; 984 } 985 PPCInstr* PPCInstr_FpLdFPSCR ( HReg src ) { 986 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 987 i->tag = Pin_FpLdFPSCR; 988 i->Pin.FpLdFPSCR.src = src; 989 return i; 990 } 991 PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) { 992 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 993 i->tag = Pin_FpCmp; 994 i->Pin.FpCmp.dst = dst; 995 i->Pin.FpCmp.srcL = srcL; 996 i->Pin.FpCmp.srcR = srcR; 997 return i; 998 } 999 1000 /* Read/Write Link Register */ 1001 PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) { 1002 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1003 i->tag = Pin_RdWrLR; 1004 i->Pin.RdWrLR.wrLR = wrLR; 1005 i->Pin.RdWrLR.gpr = gpr; 1006 return i; 1007 } 1008 1009 /* AltiVec */ 1010 PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz, 1011 HReg reg, PPCAMode* addr ) { 1012 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1013 i->tag = Pin_AvLdSt; 1014 i->Pin.AvLdSt.isLoad = isLoad; 1015 i->Pin.AvLdSt.sz = sz; 1016 i->Pin.AvLdSt.reg = reg; 1017 i->Pin.AvLdSt.addr = addr; 1018 return i; 1019 } 1020 PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) { 1021 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1022 i->tag = Pin_AvUnary; 1023 i->Pin.AvUnary.op = op; 1024 i->Pin.AvUnary.dst = dst; 1025 i->Pin.AvUnary.src = src; 1026 return i; 1027 } 1028 PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst, 1029 HReg srcL, HReg srcR ) { 1030 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1031 i->tag = Pin_AvBinary; 1032 i->Pin.AvBinary.op = op; 1033 i->Pin.AvBinary.dst = dst; 1034 i->Pin.AvBinary.srcL = srcL; 1035 i->Pin.AvBinary.srcR = srcR; 1036 return i; 1037 } 1038 PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst, 1039 HReg srcL, HReg srcR ) { 1040 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1041 i->tag = Pin_AvBin8x16; 1042 i->Pin.AvBin8x16.op = op; 1043 i->Pin.AvBin8x16.dst = dst; 1044 i->Pin.AvBin8x16.srcL = srcL; 1045 i->Pin.AvBin8x16.srcR = srcR; 1046 return i; 1047 } 1048 PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst, 1049 HReg srcL, HReg srcR ) { 1050 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1051 i->tag = Pin_AvBin16x8; 1052 i->Pin.AvBin16x8.op = op; 1053 i->Pin.AvBin16x8.dst = dst; 1054 i->Pin.AvBin16x8.srcL = srcL; 1055 i->Pin.AvBin16x8.srcR = srcR; 1056 return i; 1057 } 1058 PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst, 1059 HReg srcL, HReg srcR ) { 1060 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1061 i->tag = Pin_AvBin32x4; 1062 i->Pin.AvBin32x4.op = op; 1063 i->Pin.AvBin32x4.dst = dst; 1064 i->Pin.AvBin32x4.srcL = srcL; 1065 i->Pin.AvBin32x4.srcR = srcR; 1066 return i; 1067 } 1068 PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvOp op, HReg dst, 1069 HReg srcL, HReg srcR ) { 1070 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1071 i->tag = Pin_AvBin32Fx4; 1072 i->Pin.AvBin32Fx4.op = op; 1073 i->Pin.AvBin32Fx4.dst = dst; 1074 i->Pin.AvBin32Fx4.srcL = srcL; 1075 i->Pin.AvBin32Fx4.srcR = srcR; 1076 return i; 1077 } 1078 PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvOp op, HReg dst, HReg src ) { 1079 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1080 i->tag = Pin_AvUn32Fx4; 1081 i->Pin.AvUn32Fx4.op = op; 1082 i->Pin.AvUn32Fx4.dst = dst; 1083 i->Pin.AvUn32Fx4.src = src; 1084 return i; 1085 } 1086 PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) { 1087 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1088 i->tag = Pin_AvPerm; 1089 i->Pin.AvPerm.dst = dst; 1090 i->Pin.AvPerm.srcL = srcL; 1091 i->Pin.AvPerm.srcR = srcR; 1092 i->Pin.AvPerm.ctl = ctl; 1093 return i; 1094 } 1095 PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) { 1096 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1097 i->tag = Pin_AvSel; 1098 i->Pin.AvSel.ctl = ctl; 1099 i->Pin.AvSel.dst = dst; 1100 i->Pin.AvSel.srcL = srcL; 1101 i->Pin.AvSel.srcR = srcR; 1102 return i; 1103 } 1104 PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst, 1105 HReg srcL, HReg srcR ) { 1106 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1107 i->tag = Pin_AvShlDbl; 1108 i->Pin.AvShlDbl.shift = shift; 1109 i->Pin.AvShlDbl.dst = dst; 1110 i->Pin.AvShlDbl.srcL = srcL; 1111 i->Pin.AvShlDbl.srcR = srcR; 1112 return i; 1113 } 1114 PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) { 1115 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1116 i->tag = Pin_AvSplat; 1117 i->Pin.AvSplat.sz = sz; 1118 i->Pin.AvSplat.dst = dst; 1119 i->Pin.AvSplat.src = src; 1120 return i; 1121 } 1122 PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) { 1123 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1124 i->tag = Pin_AvCMov; 1125 i->Pin.AvCMov.cond = cond; 1126 i->Pin.AvCMov.dst = dst; 1127 i->Pin.AvCMov.src = src; 1128 vassert(cond.test != Pct_ALWAYS); 1129 return i; 1130 } 1131 PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) { 1132 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr)); 1133 i->tag = Pin_AvLdVSCR; 1134 i->Pin.AvLdVSCR.src = src; 1135 return i; 1136 } 1137 1138 1139 /* Pretty Print instructions */ 1140 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) { 1141 vex_printf("li_word "); 1142 ppHRegPPC(dst); 1143 if (!mode64) { 1144 vex_printf(",0x%08x", (UInt)imm); 1145 } else { 1146 vex_printf(",0x%016llx", imm); 1147 } 1148 } 1149 1150 static void ppMovReg ( HReg dst, HReg src ) { 1151 if (hregNumber(dst) != hregNumber(src)) { 1152 vex_printf("mr "); 1153 ppHRegPPC(dst); 1154 vex_printf(","); 1155 ppHRegPPC(src); 1156 } 1157 } 1158 1159 void ppPPCInstr ( PPCInstr* i, Bool mode64 ) 1160 { 1161 switch (i->tag) { 1162 case Pin_LI: 1163 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64); 1164 break; 1165 case Pin_Alu: { 1166 HReg r_srcL = i->Pin.Alu.srcL; 1167 PPCRH* rh_srcR = i->Pin.Alu.srcR; 1168 /* special-case "mr" */ 1169 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs 1170 rh_srcR->tag == Prh_Reg && 1171 rh_srcR->Prh.Reg.reg == r_srcL) { 1172 vex_printf("mr "); 1173 ppHRegPPC(i->Pin.Alu.dst); 1174 vex_printf(","); 1175 ppHRegPPC(r_srcL); 1176 return; 1177 } 1178 /* special-case "li" */ 1179 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm 1180 rh_srcR->tag == Prh_Imm && 1181 hregNumber(r_srcL) == 0) { 1182 vex_printf("li "); 1183 ppHRegPPC(i->Pin.Alu.dst); 1184 vex_printf(","); 1185 ppPPCRH(rh_srcR); 1186 return; 1187 } 1188 /* generic */ 1189 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op, 1190 toBool(rh_srcR->tag == Prh_Imm))); 1191 ppHRegPPC(i->Pin.Alu.dst); 1192 vex_printf(","); 1193 ppHRegPPC(r_srcL); 1194 vex_printf(","); 1195 ppPPCRH(rh_srcR); 1196 return; 1197 } 1198 case Pin_Shft: { 1199 HReg r_srcL = i->Pin.Shft.srcL; 1200 PPCRH* rh_srcR = i->Pin.Shft.srcR; 1201 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op, 1202 toBool(rh_srcR->tag == Prh_Imm), 1203 i->Pin.Shft.sz32)); 1204 ppHRegPPC(i->Pin.Shft.dst); 1205 vex_printf(","); 1206 ppHRegPPC(r_srcL); 1207 vex_printf(","); 1208 ppPPCRH(rh_srcR); 1209 return; 1210 } 1211 case Pin_AddSubC: 1212 vex_printf("%s%s ", 1213 i->Pin.AddSubC.isAdd ? "add" : "sub", 1214 i->Pin.AddSubC.setC ? "c" : "e"); 1215 ppHRegPPC(i->Pin.AddSubC.dst); 1216 vex_printf(","); 1217 ppHRegPPC(i->Pin.AddSubC.srcL); 1218 vex_printf(","); 1219 ppHRegPPC(i->Pin.AddSubC.srcR); 1220 return; 1221 case Pin_Cmp: 1222 vex_printf("%s%c%s %%cr%u,", 1223 i->Pin.Cmp.syned ? "cmp" : "cmpl", 1224 i->Pin.Cmp.sz32 ? 'w' : 'd', 1225 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "", 1226 i->Pin.Cmp.crfD); 1227 ppHRegPPC(i->Pin.Cmp.srcL); 1228 vex_printf(","); 1229 ppPPCRH(i->Pin.Cmp.srcR); 1230 return; 1231 case Pin_Unary: 1232 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op)); 1233 ppHRegPPC(i->Pin.Unary.dst); 1234 vex_printf(","); 1235 ppHRegPPC(i->Pin.Unary.src); 1236 return; 1237 case Pin_MulL: 1238 vex_printf("mul%c%c%s ", 1239 i->Pin.MulL.hi ? 'h' : 'l', 1240 i->Pin.MulL.sz32 ? 'w' : 'd', 1241 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : ""); 1242 ppHRegPPC(i->Pin.MulL.dst); 1243 vex_printf(","); 1244 ppHRegPPC(i->Pin.MulL.srcL); 1245 vex_printf(","); 1246 ppHRegPPC(i->Pin.MulL.srcR); 1247 return; 1248 case Pin_Div: 1249 vex_printf("div%c%s ", 1250 i->Pin.Div.sz32 ? 'w' : 'd', 1251 i->Pin.Div.syned ? "" : "u"); 1252 ppHRegPPC(i->Pin.Div.dst); 1253 vex_printf(","); 1254 ppHRegPPC(i->Pin.Div.srcL); 1255 vex_printf(","); 1256 ppHRegPPC(i->Pin.Div.srcR); 1257 return; 1258 case Pin_Call: { 1259 Int n; 1260 vex_printf("call: "); 1261 if (i->Pin.Call.cond.test != Pct_ALWAYS) { 1262 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond)); 1263 } 1264 vex_printf("{ "); 1265 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64); 1266 vex_printf(" ; mtctr r10 ; bctrl ["); 1267 for (n = 0; n < 32; n++) { 1268 if (i->Pin.Call.argiregs & (1<<n)) { 1269 vex_printf("r%d", n); 1270 if ((i->Pin.Call.argiregs >> n) > 1) 1271 vex_printf(","); 1272 } 1273 } 1274 vex_printf("] }"); 1275 break; 1276 } 1277 case Pin_Goto: 1278 vex_printf("goto: "); 1279 if (i->Pin.Goto.cond.test != Pct_ALWAYS) { 1280 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Goto.cond)); 1281 } 1282 vex_printf("{ "); 1283 if (i->Pin.Goto.jk != Ijk_Boring 1284 && i->Pin.Goto.jk != Ijk_Call 1285 && i->Pin.Goto.jk != Ijk_Ret) { 1286 vex_printf("li %%r31,$"); 1287 ppIRJumpKind(i->Pin.Goto.jk); 1288 vex_printf(" ; "); 1289 } 1290 if (i->Pin.Goto.dst->tag == Pri_Imm) { 1291 ppLoadImm(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Imm, 1292 mode64); 1293 } else { 1294 ppMovReg(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Reg); 1295 } 1296 vex_printf(" ; blr }"); 1297 return; 1298 case Pin_CMov: 1299 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond)); 1300 ppHRegPPC(i->Pin.CMov.dst); 1301 vex_printf(","); 1302 ppPPCRI(i->Pin.CMov.src); 1303 vex_printf(": "); 1304 if (i->Pin.CMov.cond.test != Pct_ALWAYS) { 1305 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond)); 1306 } 1307 vex_printf("{ "); 1308 if (i->Pin.CMov.src->tag == Pri_Imm) { 1309 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64); 1310 } else { 1311 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg); 1312 } 1313 vex_printf(" }"); 1314 return; 1315 case Pin_Load: { 1316 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR); 1317 UChar sz = i->Pin.Load.sz; 1318 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd'; 1319 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" ); 1320 ppHRegPPC(i->Pin.Load.dst); 1321 vex_printf(","); 1322 ppPPCAMode(i->Pin.Load.src); 1323 return; 1324 } 1325 case Pin_LoadL: 1326 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd'); 1327 ppHRegPPC(i->Pin.LoadL.dst); 1328 vex_printf(",%%r0,"); 1329 ppHRegPPC(i->Pin.LoadL.src); 1330 return; 1331 case Pin_Store: { 1332 UChar sz = i->Pin.Store.sz; 1333 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR); 1334 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd'; 1335 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" ); 1336 ppHRegPPC(i->Pin.Store.src); 1337 vex_printf(","); 1338 ppPPCAMode(i->Pin.Store.dst); 1339 return; 1340 } 1341 case Pin_StoreC: 1342 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd'); 1343 ppHRegPPC(i->Pin.StoreC.src); 1344 vex_printf(",%%r0,"); 1345 ppHRegPPC(i->Pin.StoreC.dst); 1346 return; 1347 case Pin_Set: { 1348 PPCCondCode cc = i->Pin.Set.cond; 1349 vex_printf("set (%s),", showPPCCondCode(cc)); 1350 ppHRegPPC(i->Pin.Set.dst); 1351 if (cc.test == Pct_ALWAYS) { 1352 vex_printf(": { li "); 1353 ppHRegPPC(i->Pin.Set.dst); 1354 vex_printf(",1 }"); 1355 } else { 1356 vex_printf(": { mfcr r0 ; rlwinm "); 1357 ppHRegPPC(i->Pin.Set.dst); 1358 vex_printf(",r0,%u,31,31", cc.flag+1); 1359 if (cc.test == Pct_FALSE) { 1360 vex_printf("; xori "); 1361 ppHRegPPC(i->Pin.Set.dst); 1362 vex_printf(","); 1363 ppHRegPPC(i->Pin.Set.dst); 1364 vex_printf(",1"); 1365 } 1366 vex_printf(" }"); 1367 } 1368 return; 1369 } 1370 case Pin_MfCR: 1371 vex_printf("mfcr "); 1372 ppHRegPPC(i->Pin.MfCR.dst); 1373 break; 1374 case Pin_MFence: 1375 vex_printf("mfence (=sync)"); 1376 return; 1377 1378 case Pin_FpUnary: 1379 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op)); 1380 ppHRegPPC(i->Pin.FpUnary.dst); 1381 vex_printf(","); 1382 ppHRegPPC(i->Pin.FpUnary.src); 1383 return; 1384 case Pin_FpBinary: 1385 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op)); 1386 ppHRegPPC(i->Pin.FpBinary.dst); 1387 vex_printf(","); 1388 ppHRegPPC(i->Pin.FpBinary.srcL); 1389 vex_printf(","); 1390 ppHRegPPC(i->Pin.FpBinary.srcR); 1391 return; 1392 case Pin_FpMulAcc: 1393 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op)); 1394 ppHRegPPC(i->Pin.FpMulAcc.dst); 1395 vex_printf(","); 1396 ppHRegPPC(i->Pin.FpMulAcc.srcML); 1397 vex_printf(","); 1398 ppHRegPPC(i->Pin.FpMulAcc.srcMR); 1399 vex_printf(","); 1400 ppHRegPPC(i->Pin.FpMulAcc.srcAcc); 1401 return; 1402 case Pin_FpLdSt: { 1403 UChar sz = i->Pin.FpLdSt.sz; 1404 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR); 1405 if (i->Pin.FpLdSt.isLoad) { 1406 vex_printf("lf%c%s ", 1407 (sz==4 ? 's' : 'd'), 1408 idxd ? "x" : "" ); 1409 ppHRegPPC(i->Pin.FpLdSt.reg); 1410 vex_printf(","); 1411 ppPPCAMode(i->Pin.FpLdSt.addr); 1412 } else { 1413 vex_printf("stf%c%s ", 1414 (sz==4 ? 's' : 'd'), 1415 idxd ? "x" : "" ); 1416 ppHRegPPC(i->Pin.FpLdSt.reg); 1417 vex_printf(","); 1418 ppPPCAMode(i->Pin.FpLdSt.addr); 1419 } 1420 return; 1421 } 1422 case Pin_FpSTFIW: 1423 vex_printf("stfiwz "); 1424 ppHRegPPC(i->Pin.FpSTFIW.data); 1425 vex_printf(",0("); 1426 ppHRegPPC(i->Pin.FpSTFIW.addr); 1427 vex_printf(")"); 1428 return; 1429 case Pin_FpRSP: 1430 vex_printf("frsp "); 1431 ppHRegPPC(i->Pin.FpRSP.dst); 1432 vex_printf(","); 1433 ppHRegPPC(i->Pin.FpRSP.src); 1434 return; 1435 case Pin_FpCftI: { 1436 HChar* str = "fc???"; 1437 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) 1438 str = "fctid"; 1439 else 1440 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) 1441 str = "fctiw"; 1442 else 1443 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) 1444 str = "fcfid"; 1445 vex_printf("%s ", str); 1446 ppHRegPPC(i->Pin.FpCftI.dst); 1447 vex_printf(","); 1448 ppHRegPPC(i->Pin.FpCftI.src); 1449 return; 1450 } 1451 case Pin_FpCMov: 1452 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond)); 1453 ppHRegPPC(i->Pin.FpCMov.dst); 1454 vex_printf(","); 1455 ppHRegPPC(i->Pin.FpCMov.src); 1456 vex_printf(": "); 1457 vex_printf("if (fr_dst != fr_src) { "); 1458 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) { 1459 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond)); 1460 } 1461 vex_printf("fmr "); 1462 ppHRegPPC(i->Pin.FpCMov.dst); 1463 vex_printf(","); 1464 ppHRegPPC(i->Pin.FpCMov.src); 1465 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) 1466 vex_printf(" }"); 1467 vex_printf(" }"); 1468 return; 1469 case Pin_FpLdFPSCR: 1470 vex_printf("mtfsf 0xFF,"); 1471 ppHRegPPC(i->Pin.FpLdFPSCR.src); 1472 return; 1473 case Pin_FpCmp: 1474 vex_printf("fcmpo %%cr1,"); 1475 ppHRegPPC(i->Pin.FpCmp.srcL); 1476 vex_printf(","); 1477 ppHRegPPC(i->Pin.FpCmp.srcR); 1478 vex_printf("; mfcr "); 1479 ppHRegPPC(i->Pin.FpCmp.dst); 1480 vex_printf("; rlwinm "); 1481 ppHRegPPC(i->Pin.FpCmp.dst); 1482 vex_printf(","); 1483 ppHRegPPC(i->Pin.FpCmp.dst); 1484 vex_printf(",8,28,31"); 1485 return; 1486 1487 case Pin_RdWrLR: 1488 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr"); 1489 ppHRegPPC(i->Pin.RdWrLR.gpr); 1490 return; 1491 1492 case Pin_AvLdSt: { 1493 UChar sz = i->Pin.AvLdSt.sz; 1494 HChar* str_size; 1495 if (i->Pin.AvLdSt.addr->tag == Pam_IR) { 1496 ppLoadImm(hregPPC_GPR30(mode64), 1497 i->Pin.AvLdSt.addr->Pam.RR.index, mode64); 1498 vex_printf(" ; "); 1499 } 1500 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : ""; 1501 if (i->Pin.AvLdSt.isLoad) 1502 vex_printf("lv%sx ", str_size); 1503 else 1504 vex_printf("stv%sx ", str_size); 1505 ppHRegPPC(i->Pin.AvLdSt.reg); 1506 vex_printf(","); 1507 if (i->Pin.AvLdSt.addr->tag == Pam_IR) 1508 vex_printf("%%r30"); 1509 else 1510 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index); 1511 vex_printf(","); 1512 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base); 1513 return; 1514 } 1515 case Pin_AvUnary: 1516 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op)); 1517 ppHRegPPC(i->Pin.AvUnary.dst); 1518 vex_printf(","); 1519 ppHRegPPC(i->Pin.AvUnary.src); 1520 return; 1521 case Pin_AvBinary: 1522 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op)); 1523 ppHRegPPC(i->Pin.AvBinary.dst); 1524 vex_printf(","); 1525 ppHRegPPC(i->Pin.AvBinary.srcL); 1526 vex_printf(","); 1527 ppHRegPPC(i->Pin.AvBinary.srcR); 1528 return; 1529 case Pin_AvBin8x16: 1530 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op)); 1531 ppHRegPPC(i->Pin.AvBin8x16.dst); 1532 vex_printf(","); 1533 ppHRegPPC(i->Pin.AvBin8x16.srcL); 1534 vex_printf(","); 1535 ppHRegPPC(i->Pin.AvBin8x16.srcR); 1536 return; 1537 case Pin_AvBin16x8: 1538 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op)); 1539 ppHRegPPC(i->Pin.AvBin16x8.dst); 1540 vex_printf(","); 1541 ppHRegPPC(i->Pin.AvBin16x8.srcL); 1542 vex_printf(","); 1543 ppHRegPPC(i->Pin.AvBin16x8.srcR); 1544 return; 1545 case Pin_AvBin32x4: 1546 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op)); 1547 ppHRegPPC(i->Pin.AvBin32x4.dst); 1548 vex_printf(","); 1549 ppHRegPPC(i->Pin.AvBin32x4.srcL); 1550 vex_printf(","); 1551 ppHRegPPC(i->Pin.AvBin32x4.srcR); 1552 return; 1553 case Pin_AvBin32Fx4: 1554 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op)); 1555 ppHRegPPC(i->Pin.AvBin32Fx4.dst); 1556 vex_printf(","); 1557 ppHRegPPC(i->Pin.AvBin32Fx4.srcL); 1558 vex_printf(","); 1559 ppHRegPPC(i->Pin.AvBin32Fx4.srcR); 1560 return; 1561 case Pin_AvUn32Fx4: 1562 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op)); 1563 ppHRegPPC(i->Pin.AvUn32Fx4.dst); 1564 vex_printf(","); 1565 ppHRegPPC(i->Pin.AvUn32Fx4.src); 1566 return; 1567 case Pin_AvPerm: 1568 vex_printf("vperm "); 1569 ppHRegPPC(i->Pin.AvPerm.dst); 1570 vex_printf(","); 1571 ppHRegPPC(i->Pin.AvPerm.srcL); 1572 vex_printf(","); 1573 ppHRegPPC(i->Pin.AvPerm.srcR); 1574 vex_printf(","); 1575 ppHRegPPC(i->Pin.AvPerm.ctl); 1576 return; 1577 1578 case Pin_AvSel: 1579 vex_printf("vsel "); 1580 ppHRegPPC(i->Pin.AvSel.dst); 1581 vex_printf(","); 1582 ppHRegPPC(i->Pin.AvSel.srcL); 1583 vex_printf(","); 1584 ppHRegPPC(i->Pin.AvSel.srcR); 1585 vex_printf(","); 1586 ppHRegPPC(i->Pin.AvSel.ctl); 1587 return; 1588 1589 case Pin_AvShlDbl: 1590 vex_printf("vsldoi "); 1591 ppHRegPPC(i->Pin.AvShlDbl.dst); 1592 vex_printf(","); 1593 ppHRegPPC(i->Pin.AvShlDbl.srcL); 1594 vex_printf(","); 1595 ppHRegPPC(i->Pin.AvShlDbl.srcR); 1596 vex_printf(",%d", i->Pin.AvShlDbl.shift); 1597 return; 1598 1599 case Pin_AvSplat: { 1600 UChar sz = i->Pin.AvSplat.sz; 1601 UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' ); 1602 vex_printf("vsplt%s%c ", 1603 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz); 1604 ppHRegPPC(i->Pin.AvSplat.dst); 1605 vex_printf(","); 1606 ppPPCVI5s(i->Pin.AvSplat.src); 1607 if (i->Pin.AvSplat.src->tag == Pvi_Reg) 1608 vex_printf(", %d", (128/sz)-1); /* louis lane */ 1609 return; 1610 } 1611 1612 case Pin_AvCMov: 1613 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond)); 1614 ppHRegPPC(i->Pin.AvCMov.dst); 1615 vex_printf(","); 1616 ppHRegPPC(i->Pin.AvCMov.src); 1617 vex_printf(": "); 1618 vex_printf("if (v_dst != v_src) { "); 1619 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) { 1620 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond)); 1621 } 1622 vex_printf("vmr "); 1623 ppHRegPPC(i->Pin.AvCMov.dst); 1624 vex_printf(","); 1625 ppHRegPPC(i->Pin.AvCMov.src); 1626 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) 1627 vex_printf(" }"); 1628 vex_printf(" }"); 1629 return; 1630 1631 case Pin_AvLdVSCR: 1632 vex_printf("mtvscr "); 1633 ppHRegPPC(i->Pin.AvLdVSCR.src); 1634 return; 1635 1636 default: 1637 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag); 1638 vpanic("ppPPCInstr"); 1639 } 1640 } 1641 1642 /* --------- Helpers for register allocation. --------- */ 1643 1644 void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 ) 1645 { 1646 initHRegUsage(u); 1647 switch (i->tag) { 1648 case Pin_LI: 1649 addHRegUse(u, HRmWrite, i->Pin.LI.dst); 1650 break; 1651 case Pin_Alu: 1652 addHRegUse(u, HRmRead, i->Pin.Alu.srcL); 1653 addRegUsage_PPCRH(u, i->Pin.Alu.srcR); 1654 addHRegUse(u, HRmWrite, i->Pin.Alu.dst); 1655 return; 1656 case Pin_Shft: 1657 addHRegUse(u, HRmRead, i->Pin.Shft.srcL); 1658 addRegUsage_PPCRH(u, i->Pin.Shft.srcR); 1659 addHRegUse(u, HRmWrite, i->Pin.Shft.dst); 1660 return; 1661 case Pin_AddSubC: 1662 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst); 1663 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL); 1664 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR); 1665 return; 1666 case Pin_Cmp: 1667 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL); 1668 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR); 1669 return; 1670 case Pin_Unary: 1671 addHRegUse(u, HRmWrite, i->Pin.Unary.dst); 1672 addHRegUse(u, HRmRead, i->Pin.Unary.src); 1673 return; 1674 case Pin_MulL: 1675 addHRegUse(u, HRmWrite, i->Pin.MulL.dst); 1676 addHRegUse(u, HRmRead, i->Pin.MulL.srcL); 1677 addHRegUse(u, HRmRead, i->Pin.MulL.srcR); 1678 return; 1679 case Pin_Div: 1680 addHRegUse(u, HRmWrite, i->Pin.Div.dst); 1681 addHRegUse(u, HRmRead, i->Pin.Div.srcL); 1682 addHRegUse(u, HRmRead, i->Pin.Div.srcR); 1683 return; 1684 case Pin_Call: { 1685 UInt argir; 1686 /* This is a bit subtle. */ 1687 /* First off, claim it trashes all the caller-saved regs 1688 which fall within the register allocator's jurisdiction. 1689 These I believe to be: 1690 mode32: r3 to r12 1691 mode64: r3 to r10 1692 */ 1693 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP 1694 or Altivec registers. We get away with this ONLY because 1695 getAllocatableRegs_PPC gives the allocator callee-saved fp 1696 and Altivec regs, and no caller-save ones. */ 1697 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64)); 1698 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64)); 1699 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64)); 1700 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64)); 1701 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64)); 1702 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64)); 1703 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64)); 1704 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64)); 1705 if (!mode64) { 1706 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64)); 1707 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64)); 1708 } 1709 1710 /* Now we have to state any parameter-carrying registers 1711 which might be read. This depends on the argiregs field. */ 1712 argir = i->Pin.Call.argiregs; 1713 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64)); 1714 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64)); 1715 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64)); 1716 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64)); 1717 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64)); 1718 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64)); 1719 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64)); 1720 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64)); 1721 1722 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6) 1723 |(1<<7)|(1<<8)|(1<<9)|(1<<10)))); 1724 1725 /* Finally, there is the issue that the insn trashes a 1726 register because the literal target address has to be 1727 loaded into a register. %r10 seems a suitable victim. 1728 (Can't use %r0, as some insns interpret it as value zero). */ 1729 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64)); 1730 /* Upshot of this is that the assembler really must use %r10, 1731 and no other, as a destination temporary. */ 1732 return; 1733 } 1734 case Pin_Goto: 1735 addRegUsage_PPCRI(u, i->Pin.Goto.dst); 1736 /* GPR3 holds destination address from Pin_Goto */ 1737 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64)); 1738 if (i->Pin.Goto.jk != Ijk_Boring 1739 && i->Pin.Goto.jk != Ijk_Call 1740 && i->Pin.Goto.jk != Ijk_Ret) 1741 /* note, this is irrelevant since the guest state pointer 1742 register is not actually available to the allocator. 1743 But still .. */ 1744 addHRegUse(u, HRmWrite, GuestStatePtr(mode64)); 1745 return; 1746 case Pin_CMov: 1747 addRegUsage_PPCRI(u, i->Pin.CMov.src); 1748 addHRegUse(u, HRmWrite, i->Pin.CMov.dst); 1749 return; 1750 case Pin_Load: 1751 addRegUsage_PPCAMode(u, i->Pin.Load.src); 1752 addHRegUse(u, HRmWrite, i->Pin.Load.dst); 1753 return; 1754 case Pin_LoadL: 1755 addHRegUse(u, HRmRead, i->Pin.LoadL.src); 1756 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst); 1757 return; 1758 case Pin_Store: 1759 addHRegUse(u, HRmRead, i->Pin.Store.src); 1760 addRegUsage_PPCAMode(u, i->Pin.Store.dst); 1761 return; 1762 case Pin_StoreC: 1763 addHRegUse(u, HRmRead, i->Pin.StoreC.src); 1764 addHRegUse(u, HRmRead, i->Pin.StoreC.dst); 1765 return; 1766 case Pin_Set: 1767 addHRegUse(u, HRmWrite, i->Pin.Set.dst); 1768 return; 1769 case Pin_MfCR: 1770 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst); 1771 return; 1772 case Pin_MFence: 1773 return; 1774 1775 case Pin_FpUnary: 1776 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst); 1777 addHRegUse(u, HRmRead, i->Pin.FpUnary.src); 1778 return; 1779 case Pin_FpBinary: 1780 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst); 1781 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL); 1782 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR); 1783 return; 1784 case Pin_FpMulAcc: 1785 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst); 1786 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML); 1787 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR); 1788 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc); 1789 return; 1790 case Pin_FpLdSt: 1791 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead), 1792 i->Pin.FpLdSt.reg); 1793 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr); 1794 return; 1795 case Pin_FpSTFIW: 1796 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr); 1797 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data); 1798 return; 1799 case Pin_FpRSP: 1800 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst); 1801 addHRegUse(u, HRmRead, i->Pin.FpRSP.src); 1802 return; 1803 case Pin_FpCftI: 1804 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst); 1805 addHRegUse(u, HRmRead, i->Pin.FpCftI.src); 1806 return; 1807 case Pin_FpCMov: 1808 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst); 1809 addHRegUse(u, HRmRead, i->Pin.FpCMov.src); 1810 return; 1811 case Pin_FpLdFPSCR: 1812 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src); 1813 return; 1814 case Pin_FpCmp: 1815 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst); 1816 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL); 1817 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR); 1818 return; 1819 1820 case Pin_RdWrLR: 1821 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite), 1822 i->Pin.RdWrLR.gpr); 1823 return; 1824 1825 case Pin_AvLdSt: 1826 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead), 1827 i->Pin.AvLdSt.reg); 1828 if (i->Pin.AvLdSt.addr->tag == Pam_IR) 1829 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); 1830 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr); 1831 return; 1832 case Pin_AvUnary: 1833 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst); 1834 addHRegUse(u, HRmRead, i->Pin.AvUnary.src); 1835 return; 1836 case Pin_AvBinary: 1837 if (i->Pin.AvBinary.op == Pav_XOR 1838 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcL 1839 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcR) { 1840 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */ 1841 /* (as opposed to a rite of passage :-) */ 1842 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst); 1843 } else { 1844 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst); 1845 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL); 1846 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR); 1847 } 1848 return; 1849 case Pin_AvBin8x16: 1850 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst); 1851 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL); 1852 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR); 1853 return; 1854 case Pin_AvBin16x8: 1855 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst); 1856 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL); 1857 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR); 1858 return; 1859 case Pin_AvBin32x4: 1860 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst); 1861 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL); 1862 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR); 1863 return; 1864 case Pin_AvBin32Fx4: 1865 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst); 1866 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL); 1867 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR); 1868 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF) 1869 addHRegUse(u, HRmWrite, hregPPC_VR29()); 1870 return; 1871 case Pin_AvUn32Fx4: 1872 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst); 1873 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src); 1874 return; 1875 case Pin_AvPerm: 1876 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst); 1877 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL); 1878 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR); 1879 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl); 1880 return; 1881 case Pin_AvSel: 1882 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst); 1883 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl); 1884 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL); 1885 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR); 1886 return; 1887 case Pin_AvShlDbl: 1888 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst); 1889 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL); 1890 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR); 1891 return; 1892 case Pin_AvSplat: 1893 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst); 1894 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src); 1895 return; 1896 case Pin_AvCMov: 1897 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst); 1898 addHRegUse(u, HRmRead, i->Pin.AvCMov.src); 1899 return; 1900 case Pin_AvLdVSCR: 1901 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src); 1902 return; 1903 1904 default: 1905 ppPPCInstr(i, mode64); 1906 vpanic("getRegUsage_PPCInstr"); 1907 } 1908 } 1909 1910 /* local helper */ 1911 static void mapReg( HRegRemap* m, HReg* r ) 1912 { 1913 *r = lookupHRegRemap(m, *r); 1914 } 1915 1916 void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 ) 1917 { 1918 switch (i->tag) { 1919 case Pin_LI: 1920 mapReg(m, &i->Pin.LI.dst); 1921 return; 1922 case Pin_Alu: 1923 mapReg(m, &i->Pin.Alu.dst); 1924 mapReg(m, &i->Pin.Alu.srcL); 1925 mapRegs_PPCRH(m, i->Pin.Alu.srcR); 1926 return; 1927 case Pin_Shft: 1928 mapReg(m, &i->Pin.Shft.dst); 1929 mapReg(m, &i->Pin.Shft.srcL); 1930 mapRegs_PPCRH(m, i->Pin.Shft.srcR); 1931 return; 1932 case Pin_AddSubC: 1933 mapReg(m, &i->Pin.AddSubC.dst); 1934 mapReg(m, &i->Pin.AddSubC.srcL); 1935 mapReg(m, &i->Pin.AddSubC.srcR); 1936 return; 1937 case Pin_Cmp: 1938 mapReg(m, &i->Pin.Cmp.srcL); 1939 mapRegs_PPCRH(m, i->Pin.Cmp.srcR); 1940 return; 1941 case Pin_Unary: 1942 mapReg(m, &i->Pin.Unary.dst); 1943 mapReg(m, &i->Pin.Unary.src); 1944 return; 1945 case Pin_MulL: 1946 mapReg(m, &i->Pin.MulL.dst); 1947 mapReg(m, &i->Pin.MulL.srcL); 1948 mapReg(m, &i->Pin.MulL.srcR); 1949 return; 1950 case Pin_Div: 1951 mapReg(m, &i->Pin.Div.dst); 1952 mapReg(m, &i->Pin.Div.srcL); 1953 mapReg(m, &i->Pin.Div.srcR); 1954 return; 1955 case Pin_Call: 1956 return; 1957 case Pin_Goto: 1958 mapRegs_PPCRI(m, i->Pin.Goto.dst); 1959 return; 1960 case Pin_CMov: 1961 mapRegs_PPCRI(m, i->Pin.CMov.src); 1962 mapReg(m, &i->Pin.CMov.dst); 1963 return; 1964 case Pin_Load: 1965 mapRegs_PPCAMode(m, i->Pin.Load.src); 1966 mapReg(m, &i->Pin.Load.dst); 1967 return; 1968 case Pin_LoadL: 1969 mapReg(m, &i->Pin.LoadL.src); 1970 mapReg(m, &i->Pin.LoadL.dst); 1971 return; 1972 case Pin_Store: 1973 mapReg(m, &i->Pin.Store.src); 1974 mapRegs_PPCAMode(m, i->Pin.Store.dst); 1975 return; 1976 case Pin_StoreC: 1977 mapReg(m, &i->Pin.StoreC.src); 1978 mapReg(m, &i->Pin.StoreC.dst); 1979 return; 1980 case Pin_Set: 1981 mapReg(m, &i->Pin.Set.dst); 1982 return; 1983 case Pin_MfCR: 1984 mapReg(m, &i->Pin.MfCR.dst); 1985 return; 1986 case Pin_MFence: 1987 return; 1988 case Pin_FpUnary: 1989 mapReg(m, &i->Pin.FpUnary.dst); 1990 mapReg(m, &i->Pin.FpUnary.src); 1991 return; 1992 case Pin_FpBinary: 1993 mapReg(m, &i->Pin.FpBinary.dst); 1994 mapReg(m, &i->Pin.FpBinary.srcL); 1995 mapReg(m, &i->Pin.FpBinary.srcR); 1996 return; 1997 case Pin_FpMulAcc: 1998 mapReg(m, &i->Pin.FpMulAcc.dst); 1999 mapReg(m, &i->Pin.FpMulAcc.srcML); 2000 mapReg(m, &i->Pin.FpMulAcc.srcMR); 2001 mapReg(m, &i->Pin.FpMulAcc.srcAcc); 2002 return; 2003 case Pin_FpLdSt: 2004 mapReg(m, &i->Pin.FpLdSt.reg); 2005 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr); 2006 return; 2007 case Pin_FpSTFIW: 2008 mapReg(m, &i->Pin.FpSTFIW.addr); 2009 mapReg(m, &i->Pin.FpSTFIW.data); 2010 return; 2011 case Pin_FpRSP: 2012 mapReg(m, &i->Pin.FpRSP.dst); 2013 mapReg(m, &i->Pin.FpRSP.src); 2014 return; 2015 case Pin_FpCftI: 2016 mapReg(m, &i->Pin.FpCftI.dst); 2017 mapReg(m, &i->Pin.FpCftI.src); 2018 return; 2019 case Pin_FpCMov: 2020 mapReg(m, &i->Pin.FpCMov.dst); 2021 mapReg(m, &i->Pin.FpCMov.src); 2022 return; 2023 case Pin_FpLdFPSCR: 2024 mapReg(m, &i->Pin.FpLdFPSCR.src); 2025 return; 2026 case Pin_FpCmp: 2027 mapReg(m, &i->Pin.FpCmp.dst); 2028 mapReg(m, &i->Pin.FpCmp.srcL); 2029 mapReg(m, &i->Pin.FpCmp.srcR); 2030 return; 2031 case Pin_RdWrLR: 2032 mapReg(m, &i->Pin.RdWrLR.gpr); 2033 return; 2034 case Pin_AvLdSt: 2035 mapReg(m, &i->Pin.AvLdSt.reg); 2036 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr); 2037 return; 2038 case Pin_AvUnary: 2039 mapReg(m, &i->Pin.AvUnary.dst); 2040 mapReg(m, &i->Pin.AvUnary.src); 2041 return; 2042 case Pin_AvBinary: 2043 mapReg(m, &i->Pin.AvBinary.dst); 2044 mapReg(m, &i->Pin.AvBinary.srcL); 2045 mapReg(m, &i->Pin.AvBinary.srcR); 2046 return; 2047 case Pin_AvBin8x16: 2048 mapReg(m, &i->Pin.AvBin8x16.dst); 2049 mapReg(m, &i->Pin.AvBin8x16.srcL); 2050 mapReg(m, &i->Pin.AvBin8x16.srcR); 2051 return; 2052 case Pin_AvBin16x8: 2053 mapReg(m, &i->Pin.AvBin16x8.dst); 2054 mapReg(m, &i->Pin.AvBin16x8.srcL); 2055 mapReg(m, &i->Pin.AvBin16x8.srcR); 2056 return; 2057 case Pin_AvBin32x4: 2058 mapReg(m, &i->Pin.AvBin32x4.dst); 2059 mapReg(m, &i->Pin.AvBin32x4.srcL); 2060 mapReg(m, &i->Pin.AvBin32x4.srcR); 2061 return; 2062 case Pin_AvBin32Fx4: 2063 mapReg(m, &i->Pin.AvBin32Fx4.dst); 2064 mapReg(m, &i->Pin.AvBin32Fx4.srcL); 2065 mapReg(m, &i->Pin.AvBin32Fx4.srcR); 2066 return; 2067 case Pin_AvUn32Fx4: 2068 mapReg(m, &i->Pin.AvUn32Fx4.dst); 2069 mapReg(m, &i->Pin.AvUn32Fx4.src); 2070 return; 2071 case Pin_AvPerm: 2072 mapReg(m, &i->Pin.AvPerm.dst); 2073 mapReg(m, &i->Pin.AvPerm.srcL); 2074 mapReg(m, &i->Pin.AvPerm.srcR); 2075 mapReg(m, &i->Pin.AvPerm.ctl); 2076 return; 2077 case Pin_AvSel: 2078 mapReg(m, &i->Pin.AvSel.dst); 2079 mapReg(m, &i->Pin.AvSel.srcL); 2080 mapReg(m, &i->Pin.AvSel.srcR); 2081 mapReg(m, &i->Pin.AvSel.ctl); 2082 return; 2083 case Pin_AvShlDbl: 2084 mapReg(m, &i->Pin.AvShlDbl.dst); 2085 mapReg(m, &i->Pin.AvShlDbl.srcL); 2086 mapReg(m, &i->Pin.AvShlDbl.srcR); 2087 return; 2088 case Pin_AvSplat: 2089 mapReg(m, &i->Pin.AvSplat.dst); 2090 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src); 2091 return; 2092 case Pin_AvCMov: 2093 mapReg(m, &i->Pin.AvCMov.dst); 2094 mapReg(m, &i->Pin.AvCMov.src); 2095 return; 2096 case Pin_AvLdVSCR: 2097 mapReg(m, &i->Pin.AvLdVSCR.src); 2098 return; 2099 2100 default: 2101 ppPPCInstr(i, mode64); 2102 vpanic("mapRegs_PPCInstr"); 2103 } 2104 } 2105 2106 /* Figure out if i represents a reg-reg move, and if so assign the 2107 source and destination to *src and *dst. If in doubt say No. Used 2108 by the register allocator to do move coalescing. 2109 */ 2110 Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst ) 2111 { 2112 /* Moves between integer regs */ 2113 if (i->tag == Pin_Alu) { 2114 // or Rd,Rs,Rs == mr Rd,Rs 2115 if (i->Pin.Alu.op != Palu_OR) 2116 return False; 2117 if (i->Pin.Alu.srcR->tag != Prh_Reg) 2118 return False; 2119 if (i->Pin.Alu.srcR->Prh.Reg.reg != i->Pin.Alu.srcL) 2120 return False; 2121 *src = i->Pin.Alu.srcL; 2122 *dst = i->Pin.Alu.dst; 2123 return True; 2124 } 2125 /* Moves between FP regs */ 2126 if (i->tag == Pin_FpUnary) { 2127 if (i->Pin.FpUnary.op != Pfp_MOV) 2128 return False; 2129 *src = i->Pin.FpUnary.src; 2130 *dst = i->Pin.FpUnary.dst; 2131 return True; 2132 } 2133 return False; 2134 } 2135 2136 2137 /* Generate ppc spill/reload instructions under the direction of the 2138 register allocator. Note it's critical these don't write the 2139 condition codes. */ 2140 2141 void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2, 2142 HReg rreg, Int offsetB, Bool mode64 ) 2143 { 2144 PPCAMode* am; 2145 vassert(!hregIsVirtual(rreg)); 2146 *i1 = *i2 = NULL; 2147 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) ); 2148 switch (hregClass(rreg)) { 2149 case HRcInt64: 2150 vassert(mode64); 2151 *i1 = PPCInstr_Store( 8, am, rreg, mode64 ); 2152 return; 2153 case HRcInt32: 2154 vassert(!mode64); 2155 *i1 = PPCInstr_Store( 4, am, rreg, mode64 ); 2156 return; 2157 case HRcFlt64: 2158 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am ); 2159 return; 2160 case HRcVec128: 2161 // XXX: GPR30 used as spill register to kludge AltiVec 2162 // AMode_IR 2163 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am ); 2164 return; 2165 default: 2166 ppHRegClass(hregClass(rreg)); 2167 vpanic("genSpill_PPC: unimplemented regclass"); 2168 } 2169 } 2170 2171 void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2, 2172 HReg rreg, Int offsetB, Bool mode64 ) 2173 { 2174 PPCAMode* am; 2175 vassert(!hregIsVirtual(rreg)); 2176 *i1 = *i2 = NULL; 2177 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) ); 2178 switch (hregClass(rreg)) { 2179 case HRcInt64: 2180 vassert(mode64); 2181 *i1 = PPCInstr_Load( 8, rreg, am, mode64 ); 2182 return; 2183 case HRcInt32: 2184 vassert(!mode64); 2185 *i1 = PPCInstr_Load( 4, rreg, am, mode64 ); 2186 return; 2187 case HRcFlt64: 2188 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am ); 2189 return; 2190 case HRcVec128: 2191 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR 2192 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am ); 2193 return; 2194 default: 2195 ppHRegClass(hregClass(rreg)); 2196 vpanic("genReload_PPC: unimplemented regclass"); 2197 } 2198 } 2199 2200 2201 /* --------- The ppc assembler (bleh.) --------- */ 2202 2203 static UInt iregNo ( HReg r, Bool mode64 ) 2204 { 2205 UInt n; 2206 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32); 2207 vassert(!hregIsVirtual(r)); 2208 n = hregNumber(r); 2209 vassert(n <= 32); 2210 return n; 2211 } 2212 2213 static UInt fregNo ( HReg fr ) 2214 { 2215 UInt n; 2216 vassert(hregClass(fr) == HRcFlt64); 2217 vassert(!hregIsVirtual(fr)); 2218 n = hregNumber(fr); 2219 vassert(n <= 32); 2220 return n; 2221 } 2222 2223 static UInt vregNo ( HReg v ) 2224 { 2225 UInt n; 2226 vassert(hregClass(v) == HRcVec128); 2227 vassert(!hregIsVirtual(v)); 2228 n = hregNumber(v); 2229 vassert(n <= 32); 2230 return n; 2231 } 2232 2233 /* Emit 32bit instruction big-endianly */ 2234 static UChar* emit32 ( UChar* p, UInt w32 ) 2235 { 2236 *p++ = toUChar((w32 >> 24) & 0x000000FF); 2237 *p++ = toUChar((w32 >> 16) & 0x000000FF); 2238 *p++ = toUChar((w32 >> 8) & 0x000000FF); 2239 *p++ = toUChar((w32) & 0x000000FF); 2240 return p; 2241 } 2242 2243 /* The following mkForm[...] functions refer to ppc instruction forms 2244 as per PPC32 p576 2245 */ 2246 2247 static UChar* mkFormD ( UChar* p, UInt opc1, 2248 UInt r1, UInt r2, UInt imm ) 2249 { 2250 UInt theInstr; 2251 vassert(opc1 < 0x40); 2252 vassert(r1 < 0x20); 2253 vassert(r2 < 0x20); 2254 imm = imm & 0xFFFF; 2255 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm)); 2256 return emit32(p, theInstr); 2257 } 2258 2259 static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2, 2260 UInt imm1, UInt imm2, UInt opc2 ) 2261 { 2262 UInt theInstr; 2263 vassert(opc1 < 0x40); 2264 vassert(r1 < 0x20); 2265 vassert(r2 < 0x20); 2266 vassert(imm1 < 0x40); 2267 vassert(imm2 < 0x40); 2268 vassert(opc2 < 0x08); 2269 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5); 2270 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2271 ((imm1 & 0x1F)<<11) | (imm2<<5) | 2272 (opc2<<2) | ((imm1 >> 5)<<1)); 2273 return emit32(p, theInstr); 2274 } 2275 2276 static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2, 2277 UInt r3, UInt opc2, UInt b0 ) 2278 { 2279 UInt theInstr; 2280 vassert(opc1 < 0x40); 2281 vassert(r1 < 0x20); 2282 vassert(r2 < 0x20); 2283 vassert(r3 < 0x20); 2284 vassert(opc2 < 0x400); 2285 vassert(b0 < 0x2); 2286 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2287 (r3<<11) | (opc2<<1) | (b0)); 2288 return emit32(p, theInstr); 2289 } 2290 2291 static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2, 2292 UInt r3, UInt b10, UInt opc2, UInt b0 ) 2293 { 2294 UInt theInstr; 2295 vassert(opc1 < 0x40); 2296 vassert(r1 < 0x20); 2297 vassert(r2 < 0x20); 2298 vassert(r3 < 0x20); 2299 vassert(b10 < 0x2); 2300 vassert(opc2 < 0x200); 2301 vassert(b0 < 0x2); 2302 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2303 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0)); 2304 return emit32(p, theInstr); 2305 } 2306 2307 static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2, 2308 UInt f3, UInt opc2, UInt b0 ) 2309 { 2310 UInt theInstr; 2311 vassert(opc1 < 0x40); 2312 vassert(f1 < 0x20); 2313 vassert(f2 < 0x20); 2314 vassert(f3 < 0x20); 2315 vassert(opc2 < 0x400); 2316 vassert(b0 < 0x2); 2317 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | 2318 (f3<<11) | (opc2<<1) | (b0)); 2319 return emit32(p, theInstr); 2320 } 2321 2322 // Note: for split field ops, give mnemonic arg 2323 static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 ) 2324 { 2325 UInt theInstr; 2326 vassert(r1 < 0x20); 2327 vassert(f2 < 0x20); 2328 vassert(opc2 < 0x400); 2329 switch (opc2) { 2330 case 144: // mtcrf 2331 vassert(f2 < 0x100); 2332 f2 = f2 << 1; 2333 break; 2334 case 339: // mfspr 2335 case 371: // mftb 2336 case 467: // mtspr 2337 vassert(f2 < 0x400); 2338 // re-arrange split field 2339 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); 2340 break; 2341 default: vpanic("mkFormXFX(ppch)"); 2342 } 2343 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1)); 2344 return emit32(p, theInstr); 2345 } 2346 2347 // Only used by mtfsf 2348 static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg ) 2349 { 2350 UInt theInstr; 2351 vassert(FM < 0x100); 2352 vassert(freg < 0x20); 2353 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1)); 2354 return emit32(p, theInstr); 2355 } 2356 2357 static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2, 2358 UInt imm, UInt opc2, UInt b0 ) 2359 { 2360 UInt theInstr; 2361 vassert(opc1 < 0x40); 2362 vassert(r1 < 0x20); 2363 vassert(r2 < 0x20); 2364 vassert(imm < 0x40); 2365 vassert(opc2 < 0x400); 2366 vassert(b0 < 0x2); 2367 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2368 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0)); 2369 return emit32(p, theInstr); 2370 } 2371 2372 2373 #if 0 2374 // 'b' 2375 static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK ) 2376 { 2377 UInt theInstr; 2378 vassert(LI < 0x1000000); 2379 vassert(AA < 0x2); 2380 vassert(LK < 0x2); 2381 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK)); 2382 return emit32(p, theInstr); 2383 } 2384 #endif 2385 2386 // 'bc' 2387 static UChar* mkFormB ( UChar* p, UInt BO, UInt BI, 2388 UInt BD, UInt AA, UInt LK ) 2389 { 2390 UInt theInstr; 2391 vassert(BO < 0x20); 2392 vassert(BI < 0x20); 2393 vassert(BD < 0x4000); 2394 vassert(AA < 0x2); 2395 vassert(LK < 0x2); 2396 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | 2397 (BD<<2) | (AA<<1) | (LK)); 2398 return emit32(p, theInstr); 2399 } 2400 2401 // rotates 2402 static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2, 2403 UInt f3, UInt MB, UInt ME, UInt Rc ) 2404 { 2405 UInt theInstr; 2406 vassert(opc1 < 0x40); 2407 vassert(r1 < 0x20); 2408 vassert(r2 < 0x20); 2409 vassert(f3 < 0x20); 2410 vassert(MB < 0x20); 2411 vassert(ME < 0x20); 2412 vassert(Rc < 0x2); 2413 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2414 (f3<<11) | (MB<<6) | (ME<<1) | (Rc)); 2415 return emit32(p, theInstr); 2416 } 2417 2418 static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2, 2419 UInt r3, UInt r4, UInt opc2, UInt b0 ) 2420 { 2421 UInt theInstr; 2422 vassert(opc1 < 0x40); 2423 vassert(r1 < 0x20); 2424 vassert(r2 < 0x20); 2425 vassert(r3 < 0x20); 2426 vassert(r4 < 0x20); 2427 vassert(opc2 < 0x20); 2428 vassert(b0 < 0x2 ); 2429 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | 2430 (r4<<6) | (opc2<<1) | (b0)); 2431 return emit32(p, theInstr); 2432 } 2433 2434 static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, 2435 PPCAMode* am, Bool mode64 ) 2436 { 2437 UInt rA, idx; 2438 vassert(am->tag == Pam_IR); 2439 vassert(am->Pam.IR.index < 0x10000); 2440 2441 rA = iregNo(am->Pam.IR.base, mode64); 2442 idx = am->Pam.IR.index; 2443 2444 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only 2445 vassert(mode64); 2446 /* stay sane with DS form: lowest 2 bits must be 00. This 2447 should be guaranteed to us by iselWordExpr_AMode. */ 2448 vassert(0 == (idx & 3)); 2449 } 2450 p = mkFormD(p, opc1, rSD, rA, idx); 2451 return p; 2452 } 2453 2454 static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2, 2455 UInt rSD, PPCAMode* am, Bool mode64 ) 2456 { 2457 UInt rA, rB; 2458 vassert(am->tag == Pam_RR); 2459 2460 rA = iregNo(am->Pam.RR.base, mode64); 2461 rB = iregNo(am->Pam.RR.index, mode64); 2462 2463 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0); 2464 return p; 2465 } 2466 2467 2468 /* Load imm to r_dst */ 2469 static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 ) 2470 { 2471 vassert(r_dst < 0x20); 2472 2473 if (!mode64) { 2474 /* In 32-bit mode, make sure the top 32 bits of imm are a sign 2475 extension of the bottom 32 bits, so that the range tests 2476 below work correctly. */ 2477 UInt u32 = (UInt)imm; 2478 Int s32 = (Int)u32; 2479 Long s64 = (Long)s32; 2480 imm = (ULong)s64; 2481 } 2482 2483 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) { 2484 // sign-extendable from 16 bits 2485 2486 // addi r_dst,0,imm => li r_dst,imm 2487 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF); 2488 } else { 2489 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) { 2490 // sign-extendable from 32 bits 2491 2492 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16) 2493 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF); 2494 // ori r_dst, r_dst, (imm & 0xFFFF) 2495 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF); 2496 } else { 2497 // full 64bit immediate load: 5 (five!) insns. 2498 vassert(mode64); 2499 2500 // load high word 2501 2502 // lis r_dst, (imm>>48) & 0xFFFF 2503 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF); 2504 2505 // ori r_dst, r_dst, (imm>>32) & 0xFFFF 2506 if ((imm>>32) & 0xFFFF) 2507 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF); 2508 2509 // shift r_dst low word to high word => rldicr 2510 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1); 2511 2512 // load low word 2513 2514 // oris r_dst, r_dst, (imm>>16) & 0xFFFF 2515 if ((imm>>16) & 0xFFFF) 2516 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF); 2517 2518 // ori r_dst, r_dst, (imm) & 0xFFFF 2519 if (imm & 0xFFFF) 2520 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF); 2521 } 2522 } 2523 return p; 2524 } 2525 2526 /* Move r_dst to r_src */ 2527 static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src ) 2528 { 2529 vassert(r_dst < 0x20); 2530 vassert(r_src < 0x20); 2531 2532 if (r_dst != r_src) { 2533 /* or r_dst, r_src, r_src */ 2534 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 ); 2535 } 2536 return p; 2537 } 2538 2539 static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2, 2540 UInt r3, UInt opc2 ) 2541 { 2542 UInt theInstr; 2543 vassert(opc1 < 0x40); 2544 vassert(r1 < 0x20); 2545 vassert(r2 < 0x20); 2546 vassert(r3 < 0x20); 2547 vassert(opc2 < 0x800); 2548 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2); 2549 return emit32(p, theInstr); 2550 } 2551 2552 static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, 2553 UInt r3, UInt Rc, UInt opc2 ) 2554 { 2555 UInt theInstr; 2556 vassert(opc1 < 0x40); 2557 vassert(r1 < 0x20); 2558 vassert(r2 < 0x20); 2559 vassert(r3 < 0x20); 2560 vassert(Rc < 0x2); 2561 vassert(opc2 < 0x400); 2562 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2563 (r3<<11) | (Rc<<10) | opc2); 2564 return emit32(p, theInstr); 2565 } 2566 2567 static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2, 2568 UInt r3, UInt r4, UInt opc2 ) 2569 { 2570 UInt theInstr; 2571 vassert(opc1 < 0x40); 2572 vassert(r1 < 0x20); 2573 vassert(r2 < 0x20); 2574 vassert(r3 < 0x20); 2575 vassert(r4 < 0x20); 2576 vassert(opc2 < 0x40); 2577 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | 2578 (r3<<11) | (r4<<6) | opc2); 2579 return emit32(p, theInstr); 2580 } 2581 2582 2583 2584 /* Emit an instruction into buf and return the number of bytes used. 2585 Note that buf is not the insn's final place, and therefore it is 2586 imperative to emit position-independent code. 2587 2588 Note, dispatch should always be NULL since ppc32/64 backends 2589 use a call-return scheme to get from the dispatcher to generated 2590 code and back. 2591 */ 2592 Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i, 2593 Bool mode64, void* dispatch ) 2594 { 2595 UChar* p = &buf[0]; 2596 UChar* ptmp = p; 2597 vassert(nbuf >= 32); 2598 2599 if (0) { 2600 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n"); 2601 } 2602 2603 switch (i->tag) { 2604 2605 case Pin_LI: 2606 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64), 2607 i->Pin.LI.imm64, mode64); 2608 goto done; 2609 2610 case Pin_Alu: { 2611 PPCRH* srcR = i->Pin.Alu.srcR; 2612 Bool immR = toBool(srcR->tag == Prh_Imm); 2613 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64); 2614 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64); 2615 UInt r_srcR = immR ? (-1)/*bogus*/ : 2616 iregNo(srcR->Prh.Reg.reg, mode64); 2617 2618 switch (i->Pin.Alu.op) { 2619 case Palu_ADD: 2620 if (immR) { 2621 /* addi (PPC32 p350) */ 2622 vassert(srcR->Prh.Imm.syned); 2623 vassert(srcR->Prh.Imm.imm16 != 0x8000); 2624 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16); 2625 } else { 2626 /* add (PPC32 p347) */ 2627 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0); 2628 } 2629 break; 2630 2631 case Palu_SUB: 2632 if (immR) { 2633 /* addi (PPC32 p350), but with negated imm */ 2634 vassert(srcR->Prh.Imm.syned); 2635 vassert(srcR->Prh.Imm.imm16 != 0x8000); 2636 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16)); 2637 } else { 2638 /* subf (PPC32 p537), with args the "wrong" way round */ 2639 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0); 2640 } 2641 break; 2642 2643 case Palu_AND: 2644 if (immR) { 2645 /* andi. (PPC32 p358) */ 2646 vassert(!srcR->Prh.Imm.syned); 2647 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16); 2648 } else { 2649 /* and (PPC32 p356) */ 2650 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0); 2651 } 2652 break; 2653 2654 case Palu_OR: 2655 if (immR) { 2656 /* ori (PPC32 p497) */ 2657 vassert(!srcR->Prh.Imm.syned); 2658 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16); 2659 } else { 2660 /* or (PPC32 p495) */ 2661 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0); 2662 } 2663 break; 2664 2665 case Palu_XOR: 2666 if (immR) { 2667 /* xori (PPC32 p550) */ 2668 vassert(!srcR->Prh.Imm.syned); 2669 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16); 2670 } else { 2671 /* xor (PPC32 p549) */ 2672 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0); 2673 } 2674 break; 2675 2676 default: 2677 goto bad; 2678 } 2679 goto done; 2680 } 2681 2682 case Pin_Shft: { 2683 PPCRH* srcR = i->Pin.Shft.srcR; 2684 Bool sz32 = i->Pin.Shft.sz32; 2685 Bool immR = toBool(srcR->tag == Prh_Imm); 2686 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64); 2687 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64); 2688 UInt r_srcR = immR ? (-1)/*bogus*/ : 2689 iregNo(srcR->Prh.Reg.reg, mode64); 2690 if (!mode64) 2691 vassert(sz32); 2692 2693 switch (i->Pin.Shft.op) { 2694 case Pshft_SHL: 2695 if (sz32) { 2696 if (immR) { 2697 /* rd = rs << n, 1 <= n <= 31 2698 is 2699 rlwinm rd,rs,n,0,31-n (PPC32 p501) 2700 */ 2701 UInt n = srcR->Prh.Imm.imm16; 2702 vassert(!srcR->Prh.Imm.syned); 2703 vassert(n > 0 && n < 32); 2704 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0); 2705 } else { 2706 /* slw (PPC32 p505) */ 2707 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0); 2708 } 2709 } else { 2710 if (immR) { 2711 /* rd = rs << n, 1 <= n <= 63 2712 is 2713 rldicr rd,rs,n,63-n (PPC64 p559) 2714 */ 2715 UInt n = srcR->Prh.Imm.imm16; 2716 vassert(!srcR->Prh.Imm.syned); 2717 vassert(n > 0 && n < 64); 2718 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1); 2719 } else { 2720 /* sld (PPC64 p568) */ 2721 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0); 2722 } 2723 } 2724 break; 2725 2726 case Pshft_SHR: 2727 if (sz32) { 2728 if (immR) { 2729 /* rd = rs >>u n, 1 <= n <= 31 2730 is 2731 rlwinm rd,rs,32-n,n,31 (PPC32 p501) 2732 */ 2733 UInt n = srcR->Prh.Imm.imm16; 2734 vassert(!srcR->Prh.Imm.syned); 2735 vassert(n > 0 && n < 32); 2736 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0); 2737 } else { 2738 /* srw (PPC32 p508) */ 2739 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0); 2740 } 2741 } else { 2742 if (immR) { 2743 /* rd = rs >>u n, 1 <= n <= 63 2744 is 2745 rldicl rd,rs,64-n,n (PPC64 p558) 2746 */ 2747 UInt n = srcR->Prh.Imm.imm16; 2748 vassert(!srcR->Prh.Imm.syned); 2749 vassert(n > 0 && n < 64); 2750 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0); 2751 } else { 2752 /* srd (PPC64 p574) */ 2753 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0); 2754 } 2755 } 2756 break; 2757 2758 case Pshft_SAR: 2759 if (sz32) { 2760 if (immR) { 2761 /* srawi (PPC32 p507) */ 2762 UInt n = srcR->Prh.Imm.imm16; 2763 vassert(!srcR->Prh.Imm.syned); 2764 /* In 64-bit mode, we allow right shifts by zero bits 2765 as that is a handy way to sign extend the lower 32 2766 bits into the upper 32 bits. */ 2767 if (mode64) 2768 vassert(n >= 0 && n < 32); 2769 else 2770 vassert(n > 0 && n < 32); 2771 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0); 2772 } else { 2773 /* sraw (PPC32 p506) */ 2774 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0); 2775 } 2776 } else { 2777 if (immR) { 2778 /* sradi (PPC64 p571) */ 2779 UInt n = srcR->Prh.Imm.imm16; 2780 vassert(!srcR->Prh.Imm.syned); 2781 vassert(n > 0 && n < 64); 2782 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0); 2783 } else { 2784 /* srad (PPC32 p570) */ 2785 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0); 2786 } 2787 } 2788 break; 2789 2790 default: 2791 goto bad; 2792 } 2793 goto done; 2794 } 2795 2796 case Pin_AddSubC: { 2797 Bool isAdd = i->Pin.AddSubC.isAdd; 2798 Bool setC = i->Pin.AddSubC.setC; 2799 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64); 2800 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64); 2801 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64); 2802 2803 if (isAdd) { 2804 if (setC) /* addc (PPC32 p348) */ 2805 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0); 2806 else /* adde (PPC32 p349) */ 2807 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0); 2808 } else { 2809 /* subfX, with args the "wrong" way round */ 2810 if (setC) /* subfc (PPC32 p538) */ 2811 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0); 2812 else /* subfe (PPC32 p539) */ 2813 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0); 2814 } 2815 goto done; 2816 } 2817 2818 case Pin_Cmp: { 2819 Bool syned = i->Pin.Cmp.syned; 2820 Bool sz32 = i->Pin.Cmp.sz32; 2821 UInt fld1 = i->Pin.Cmp.crfD << 2; 2822 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64); 2823 UInt r_srcR, imm_srcR; 2824 PPCRH* srcR = i->Pin.Cmp.srcR; 2825 2826 if (!mode64) // cmp double word invalid for mode32 2827 vassert(sz32); 2828 else if (!sz32) // mode64 && cmp64: set L=1 2829 fld1 |= 1; 2830 2831 switch (srcR->tag) { 2832 case Prh_Imm: 2833 vassert(syned == srcR->Prh.Imm.syned); 2834 imm_srcR = srcR->Prh.Imm.imm16; 2835 if (syned) { // cmpw/di (signed) (PPC32 p368) 2836 vassert(imm_srcR != 0x8000); 2837 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR); 2838 } else { // cmplw/di (unsigned) (PPC32 p370) 2839 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR); 2840 } 2841 break; 2842 case Prh_Reg: 2843 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64); 2844 if (syned) // cmpwi (signed) (PPC32 p367) 2845 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0); 2846 else // cmplwi (unsigned) (PPC32 p379) 2847 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0); 2848 break; 2849 default: 2850 goto bad; 2851 } 2852 goto done; 2853 } 2854 2855 case Pin_Unary: { 2856 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64); 2857 UInt r_src = iregNo(i->Pin.Unary.src, mode64); 2858 2859 switch (i->Pin.Unary.op) { 2860 case Pun_NOT: // nor r_dst,r_src,r_src 2861 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0); 2862 break; 2863 case Pun_NEG: // neg r_dst,r_src 2864 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0); 2865 break; 2866 case Pun_CLZ32: // cntlzw r_dst, r_src 2867 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0); 2868 break; 2869 case Pun_CLZ64: // cntlzd r_dst, r_src 2870 vassert(mode64); 2871 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0); 2872 break; 2873 case Pun_EXTSW: // extsw r_dst, r_src 2874 vassert(mode64); 2875 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0); 2876 break; 2877 default: goto bad; 2878 } 2879 goto done; 2880 } 2881 2882 case Pin_MulL: { 2883 Bool syned = i->Pin.MulL.syned; 2884 Bool sz32 = i->Pin.MulL.sz32; 2885 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64); 2886 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64); 2887 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64); 2888 2889 if (!mode64) 2890 vassert(sz32); 2891 2892 if (i->Pin.MulL.hi) { 2893 // mul hi words, must consider sign 2894 if (sz32) { 2895 if (syned) // mulhw r_dst,r_srcL,r_srcR 2896 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0); 2897 else // mulhwu r_dst,r_srcL,r_srcR 2898 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0); 2899 } else { 2900 if (syned) // mulhd r_dst,r_srcL,r_srcR 2901 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0); 2902 else // mulhdu r_dst,r_srcL,r_srcR 2903 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0); 2904 } 2905 } else { 2906 // mul low word, sign is irrelevant 2907 vassert(!i->Pin.MulL.syned); 2908 if (sz32) // mullw r_dst,r_srcL,r_srcR 2909 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0); 2910 else // mulld r_dst,r_srcL,r_srcR 2911 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0); 2912 } 2913 goto done; 2914 } 2915 2916 case Pin_Div: { 2917 Bool syned = i->Pin.Div.syned; 2918 Bool sz32 = i->Pin.Div.sz32; 2919 UInt r_dst = iregNo(i->Pin.Div.dst, mode64); 2920 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64); 2921 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64); 2922 2923 if (!mode64) 2924 vassert(sz32); 2925 2926 if (sz32) { 2927 if (syned) // divw r_dst,r_srcL,r_srcR 2928 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0); 2929 else // divwu r_dst,r_srcL,r_srcR 2930 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0); 2931 } else { 2932 if (syned) // divd r_dst,r_srcL,r_srcR 2933 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0); 2934 else // divdu r_dst,r_srcL,r_srcR 2935 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0); 2936 } 2937 goto done; 2938 } 2939 2940 case Pin_Call: { 2941 PPCCondCode cond = i->Pin.Call.cond; 2942 UInt r_dst = 10; 2943 /* As per detailed comment for Pin_Call in 2944 getRegUsage_PPCInstr above, %r10 is used as an address temp */ 2945 2946 /* jump over the following insns if condition does not hold */ 2947 if (cond.test != Pct_ALWAYS) { 2948 /* jmp fwds if !condition */ 2949 /* don't know how many bytes to jump over yet... 2950 make space for a jump instruction and fill in later. */ 2951 ptmp = p; /* fill in this bit later */ 2952 p += 4; // p += 4 2953 } 2954 2955 /* load target to r_dst */ // p += 4|8|20 2956 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64); 2957 2958 /* mtspr 9,r_dst => move r_dst to count register */ 2959 p = mkFormXFX(p, r_dst, 9, 467); // p += 4 2960 2961 /* bctrl => branch to count register (and save to lr) */ 2962 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4 2963 2964 /* Fix up the conditional jump, if there was one. */ 2965 if (cond.test != Pct_ALWAYS) { 2966 Int delta = p - ptmp; 2967 vassert(delta >= 16 && delta <= 32); 2968 /* bc !ct,cf,delta */ 2969 mkFormB(ptmp, invertCondTest(cond.test), 2970 cond.flag, (delta>>2), 0, 0); 2971 } 2972 goto done; 2973 } 2974 2975 case Pin_Goto: { 2976 UInt trc = 0; 2977 UChar r_ret = 3; /* Put target addr into %r3 */ 2978 PPCCondCode cond = i->Pin.Goto.cond; 2979 UInt r_dst; 2980 ULong imm_dst; 2981 2982 vassert(dispatch == NULL); 2983 2984 /* First off, if this is conditional, create a conditional 2985 jump over the rest of it. */ 2986 if (cond.test != Pct_ALWAYS) { 2987 /* jmp fwds if !condition */ 2988 /* don't know how many bytes to jump over yet... 2989 make space for a jump instruction and fill in later. */ 2990 ptmp = p; /* fill in this bit later */ 2991 p += 4; 2992 } 2993 2994 // cond succeeds... 2995 2996 /* If a non-boring, set GuestStatePtr appropriately. */ 2997 switch (i->Pin.Goto.jk) { 2998 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break; 2999 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break; 3000 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break; 3001 case Ijk_YieldNoRedir: trc = VEX_TRC_JMP_YIELD_NOREDIR; break; 3002 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break; 3003 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break; 3004 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break; 3005 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break; 3006 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break; 3007 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break; 3008 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break; 3009 case Ijk_SigBUS: trc = VEX_TRC_JMP_SIGBUS; break; 3010 case Ijk_Ret: 3011 case Ijk_Call: 3012 case Ijk_Boring: 3013 break; 3014 default: 3015 ppIRJumpKind(i->Pin.Goto.jk); 3016 vpanic("emit_PPCInstr.Pin_Goto: unknown jump kind"); 3017 } 3018 if (trc !=0) { 3019 vassert(trc < 0x10000); 3020 /* addi r31,0,trc */ 3021 p = mkFormD(p, 14, 31, 0, trc); // p += 4 3022 } 3023 3024 /* Get the destination address into %r_ret */ 3025 if (i->Pin.Goto.dst->tag == Pri_Imm) { 3026 imm_dst = i->Pin.Goto.dst->Pri.Imm; 3027 p = mkLoadImm(p, r_ret, imm_dst, mode64); // p += 4|8|20 3028 } else { 3029 vassert(i->Pin.Goto.dst->tag == Pri_Reg); 3030 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg, mode64); 3031 p = mkMoveReg(p, r_ret, r_dst); // p += 4 3032 } 3033 3034 /* blr */ 3035 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4 3036 3037 /* Fix up the conditional jump, if there was one. */ 3038 if (cond.test != Pct_ALWAYS) { 3039 Int delta = p - ptmp; 3040 vassert(delta >= 12 && delta <= 32); 3041 /* bc !ct,cf,delta */ 3042 mkFormB(ptmp, invertCondTest(cond.test), 3043 cond.flag, delta>>2, 0, 0); 3044 } 3045 goto done; 3046 } 3047 3048 case Pin_CMov: { 3049 UInt r_dst, r_src; 3050 ULong imm_src; 3051 PPCCondCode cond; 3052 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS); 3053 3054 r_dst = iregNo(i->Pin.CMov.dst, mode64); 3055 cond = i->Pin.CMov.cond; 3056 3057 /* branch (if cond fails) over move instrs */ 3058 if (cond.test != Pct_ALWAYS) { 3059 /* don't know how many bytes to jump over yet... 3060 make space for a jump instruction and fill in later. */ 3061 ptmp = p; /* fill in this bit later */ 3062 p += 4; 3063 } 3064 3065 // cond true: move src => dst 3066 switch (i->Pin.CMov.src->tag) { 3067 case Pri_Imm: 3068 imm_src = i->Pin.CMov.src->Pri.Imm; 3069 p = mkLoadImm(p, r_dst, imm_src, mode64); // p += 4|8|20 3070 break; 3071 case Pri_Reg: 3072 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64); 3073 p = mkMoveReg(p, r_dst, r_src); // p += 4 3074 break; 3075 default: goto bad; 3076 } 3077 3078 /* Fix up the conditional jump, if there was one. */ 3079 if (cond.test != Pct_ALWAYS) { 3080 Int delta = p - ptmp; 3081 vassert(delta >= 8 && delta <= 24); 3082 /* bc !ct,cf,delta */ 3083 mkFormB(ptmp, invertCondTest(cond.test), 3084 cond.flag, (delta>>2), 0, 0); 3085 } 3086 goto done; 3087 } 3088 3089 case Pin_Load: { 3090 PPCAMode* am_addr = i->Pin.Load.src; 3091 UInt r_dst = iregNo(i->Pin.Load.dst, mode64); 3092 UInt opc1, opc2, sz = i->Pin.Load.sz; 3093 switch (am_addr->tag) { 3094 case Pam_IR: 3095 if (mode64 && (sz == 4 || sz == 8)) { 3096 /* should be guaranteed to us by iselWordExpr_AMode */ 3097 vassert(0 == (am_addr->Pam.IR.index & 3)); 3098 } 3099 switch(sz) { 3100 case 1: opc1 = 34; break; 3101 case 2: opc1 = 40; break; 3102 case 4: opc1 = 32; break; 3103 case 8: opc1 = 58; vassert(mode64); break; 3104 default: goto bad; 3105 } 3106 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64); 3107 goto done; 3108 case Pam_RR: 3109 switch(sz) { 3110 case 1: opc2 = 87; break; 3111 case 2: opc2 = 279; break; 3112 case 4: opc2 = 23; break; 3113 case 8: opc2 = 21; vassert(mode64); break; 3114 default: goto bad; 3115 } 3116 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64); 3117 goto done; 3118 default: 3119 goto bad; 3120 } 3121 } 3122 3123 case Pin_LoadL: { 3124 if (i->Pin.LoadL.sz == 4) { 3125 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64), 3126 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0); 3127 goto done; 3128 } 3129 if (i->Pin.LoadL.sz == 8 && mode64) { 3130 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64), 3131 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0); 3132 goto done; 3133 } 3134 goto bad; 3135 } 3136 3137 case Pin_Set: { 3138 /* Make the destination register be 1 or 0, depending on whether 3139 the relevant condition holds. */ 3140 UInt r_dst = iregNo(i->Pin.Set.dst, mode64); 3141 PPCCondCode cond = i->Pin.Set.cond; 3142 UInt rot_imm, r_tmp; 3143 3144 if (cond.test == Pct_ALWAYS) { 3145 // Just load 1 to dst => li dst,1 3146 p = mkFormD(p, 14, r_dst, 0, 1); 3147 } else { 3148 rot_imm = 1 + cond.flag; 3149 r_tmp = 0; // Not set in getAllocable, so no need to declare. 3150 3151 // r_tmp = CR => mfcr r_tmp 3152 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0); 3153 3154 // r_dst = flag (rotate left and mask) 3155 // => rlwinm r_dst,r_tmp,rot_imm,31,31 3156 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0); 3157 3158 if (cond.test == Pct_FALSE) { 3159 // flip bit => xori r_dst,r_dst,1 3160 p = mkFormD(p, 26, r_dst, r_dst, 1); 3161 } 3162 } 3163 goto done; 3164 } 3165 3166 case Pin_MfCR: 3167 // mfcr dst 3168 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0); 3169 goto done; 3170 3171 case Pin_MFence: { 3172 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616 3173 // CAB: Should this be isync? 3174 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467 3175 goto done; 3176 } 3177 3178 case Pin_Store: { 3179 PPCAMode* am_addr = i->Pin.Store.dst; 3180 UInt r_src = iregNo(i->Pin.Store.src, mode64); 3181 UInt opc1, opc2, sz = i->Pin.Store.sz; 3182 switch (i->Pin.Store.dst->tag) { 3183 case Pam_IR: 3184 if (mode64 && (sz == 4 || sz == 8)) { 3185 /* should be guaranteed to us by iselWordExpr_AMode */ 3186 vassert(0 == (am_addr->Pam.IR.index & 3)); 3187 } 3188 switch(sz) { 3189 case 1: opc1 = 38; break; 3190 case 2: opc1 = 44; break; 3191 case 4: opc1 = 36; break; 3192 case 8: vassert(mode64); 3193 opc1 = 62; break; 3194 default: 3195 goto bad; 3196 } 3197 p = doAMode_IR(p, opc1, r_src, am_addr, mode64); 3198 goto done; 3199 case Pam_RR: 3200 switch(sz) { 3201 case 1: opc2 = 215; break; 3202 case 2: opc2 = 407; break; 3203 case 4: opc2 = 151; break; 3204 case 8: vassert(mode64); 3205 opc2 = 149; break; 3206 default: 3207 goto bad; 3208 } 3209 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64); 3210 goto done; 3211 default: 3212 goto bad; 3213 } 3214 goto done; 3215 } 3216 3217 case Pin_StoreC: { 3218 if (i->Pin.StoreC.sz == 4) { 3219 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64), 3220 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1); 3221 goto done; 3222 } 3223 if (i->Pin.StoreC.sz == 8 && mode64) { 3224 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64), 3225 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1); 3226 goto done; 3227 } 3228 goto bad; 3229 } 3230 3231 case Pin_FpUnary: { 3232 UInt fr_dst = fregNo(i->Pin.FpUnary.dst); 3233 UInt fr_src = fregNo(i->Pin.FpUnary.src); 3234 switch (i->Pin.FpUnary.op) { 3235 case Pfp_RSQRTE: // frsqrtre, PPC32 p424 3236 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 ); 3237 break; 3238 case Pfp_RES: // fres, PPC32 p421 3239 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 ); 3240 break; 3241 case Pfp_SQRT: // fsqrt, PPC32 p427 3242 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 ); 3243 break; 3244 case Pfp_ABS: // fabs, PPC32 p399 3245 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0); 3246 break; 3247 case Pfp_NEG: // fneg, PPC32 p416 3248 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0); 3249 break; 3250 case Pfp_MOV: // fmr, PPC32 p410 3251 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0); 3252 break; 3253 case Pfp_FRIM: // frim, PPC ISA 2.05 p137 3254 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0); 3255 break; 3256 case Pfp_FRIP: // frip, PPC ISA 2.05 p137 3257 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0); 3258 break; 3259 case Pfp_FRIN: // frin, PPC ISA 2.05 p137 3260 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0); 3261 break; 3262 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137 3263 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0); 3264 break; 3265 default: 3266 goto bad; 3267 } 3268 goto done; 3269 } 3270 3271 case Pin_FpBinary: { 3272 UInt fr_dst = fregNo(i->Pin.FpBinary.dst); 3273 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL); 3274 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR); 3275 switch (i->Pin.FpBinary.op) { 3276 case Pfp_ADDD: // fadd, PPC32 p400 3277 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 ); 3278 break; 3279 case Pfp_ADDS: // fadds, PPC32 p401 3280 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 ); 3281 break; 3282 case Pfp_SUBD: // fsub, PPC32 p429 3283 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 ); 3284 break; 3285 case Pfp_SUBS: // fsubs, PPC32 p430 3286 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 ); 3287 break; 3288 case Pfp_MULD: // fmul, PPC32 p413 3289 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 ); 3290 break; 3291 case Pfp_MULS: // fmuls, PPC32 p414 3292 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 ); 3293 break; 3294 case Pfp_DIVD: // fdiv, PPC32 p406 3295 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 ); 3296 break; 3297 case Pfp_DIVS: // fdivs, PPC32 p407 3298 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 ); 3299 break; 3300 default: 3301 goto bad; 3302 } 3303 goto done; 3304 } 3305 3306 case Pin_FpMulAcc: { 3307 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst); 3308 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML); 3309 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR); 3310 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc); 3311 switch (i->Pin.FpMulAcc.op) { 3312 case Pfp_MADDD: // fmadd, PPC32 p408 3313 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 ); 3314 break; 3315 case Pfp_MADDS: // fmadds, PPC32 p409 3316 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 ); 3317 break; 3318 case Pfp_MSUBD: // fmsub, PPC32 p411 3319 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 ); 3320 break; 3321 case Pfp_MSUBS: // fmsubs, PPC32 p412 3322 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 ); 3323 break; 3324 default: 3325 goto bad; 3326 } 3327 goto done; 3328 } 3329 3330 case Pin_FpLdSt: { 3331 PPCAMode* am_addr = i->Pin.FpLdSt.addr; 3332 UInt f_reg = fregNo(i->Pin.FpLdSt.reg); 3333 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR); 3334 UChar sz = i->Pin.FpLdSt.sz; 3335 UInt opc; 3336 vassert(sz == 4 || sz == 8); 3337 3338 if (i->Pin.FpLdSt.isLoad) { // Load from memory 3339 if (idxd) { // lf[s|d]x, PPC32 p444|440 3340 opc = (sz == 4) ? 535 : 599; 3341 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64); 3342 } else { // lf[s|d], PPC32 p441|437 3343 opc = (sz == 4) ? 48 : 50; 3344 p = doAMode_IR(p, opc, f_reg, am_addr, mode64); 3345 } 3346 } else { // Store to memory 3347 if (idxd) { // stf[s|d]x, PPC32 p521|516 3348 opc = (sz == 4) ? 663 : 727; 3349 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64); 3350 } else { // stf[s|d], PPC32 p518|513 3351 opc = (sz == 4) ? 52 : 54; 3352 p = doAMode_IR(p, opc, f_reg, am_addr, mode64); 3353 } 3354 } 3355 goto done; 3356 } 3357 3358 case Pin_FpSTFIW: { 3359 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64); 3360 UInt fr_data = fregNo(i->Pin.FpSTFIW.data); 3361 // stfiwx (store fp64[lo32] as int32), PPC32 p517 3362 // Use rA==0, so that EA == rB == ir_addr 3363 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0); 3364 goto done; 3365 } 3366 3367 case Pin_FpRSP: { 3368 UInt fr_dst = fregNo(i->Pin.FpRSP.dst); 3369 UInt fr_src = fregNo(i->Pin.FpRSP.src); 3370 // frsp, PPC32 p423 3371 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0); 3372 goto done; 3373 } 3374 3375 case Pin_FpCftI: { 3376 UInt fr_dst = fregNo(i->Pin.FpCftI.dst); 3377 UInt fr_src = fregNo(i->Pin.FpCftI.src); 3378 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) { 3379 // fctiw (conv f64 to i32), PPC32 p404 3380 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0); 3381 goto done; 3382 } 3383 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) { 3384 // fctid (conv f64 to i64), PPC64 p437 3385 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0); 3386 goto done; 3387 } 3388 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) { 3389 // fcfid (conv i64 to f64), PPC64 p434 3390 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0); 3391 goto done; 3392 } 3393 goto bad; 3394 } 3395 3396 case Pin_FpCMov: { 3397 UInt fr_dst = fregNo(i->Pin.FpCMov.dst); 3398 UInt fr_src = fregNo(i->Pin.FpCMov.src); 3399 PPCCondCode cc = i->Pin.FpCMov.cond; 3400 3401 if (fr_dst == fr_src) goto done; 3402 3403 vassert(cc.test != Pct_ALWAYS); 3404 3405 /* jmp fwds if !condition */ 3406 if (cc.test != Pct_ALWAYS) { 3407 /* bc !ct,cf,n_bytes>>2 */ 3408 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0); 3409 } 3410 3411 // fmr, PPC32 p410 3412 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0); 3413 goto done; 3414 } 3415 3416 case Pin_FpLdFPSCR: { 3417 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src); 3418 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480 3419 goto done; 3420 } 3421 3422 case Pin_FpCmp: { 3423 UChar crfD = 1; 3424 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64); 3425 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL); 3426 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR); 3427 vassert(crfD < 8); 3428 // fcmpo, PPC32 p402 3429 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0); 3430 3431 // mfcr (mv CR to r_dst), PPC32 p467 3432 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0); 3433 3434 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501 3435 // => rotate field 1 to bottomw of word, masking out upper 28 3436 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0); 3437 goto done; 3438 } 3439 3440 case Pin_RdWrLR: { 3441 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64); 3442 /* wrLR==True ? mtlr r4 : mflr r4 */ 3443 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339); 3444 goto done; 3445 } 3446 3447 3448 /* AltiVec */ 3449 case Pin_AvLdSt: { 3450 UInt opc2, v_reg, r_idx, r_base; 3451 UChar sz = i->Pin.AvLdSt.sz; 3452 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR); 3453 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16); 3454 3455 v_reg = vregNo(i->Pin.AvLdSt.reg); 3456 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64); 3457 3458 // Only have AltiVec AMode_RR: kludge AMode_IR 3459 if (!idxd) { 3460 r_idx = 30; // XXX: Using r30 as temp 3461 p = mkLoadImm(p, r_idx, 3462 i->Pin.AvLdSt.addr->Pam.IR.index, mode64); 3463 } else { 3464 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64); 3465 } 3466 3467 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16) 3468 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103; 3469 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0); 3470 } else { // Store to memory (1,2,4,16) 3471 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231; 3472 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0); 3473 } 3474 goto done; 3475 } 3476 3477 case Pin_AvUnary: { 3478 UInt v_dst = vregNo(i->Pin.AvUnary.dst); 3479 UInt v_src = vregNo(i->Pin.AvUnary.src); 3480 UInt opc2; 3481 switch (i->Pin.AvUnary.op) { 3482 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS 3483 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS 3484 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb 3485 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh 3486 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb 3487 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh 3488 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx 3489 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx 3490 default: 3491 goto bad; 3492 } 3493 switch (i->Pin.AvUnary.op) { 3494 case Pav_MOV: 3495 case Pav_NOT: 3496 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 ); 3497 break; 3498 default: 3499 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 ); 3500 break; 3501 } 3502 goto done; 3503 } 3504 3505 case Pin_AvBinary: { 3506 UInt v_dst = vregNo(i->Pin.AvBinary.dst); 3507 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL); 3508 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR); 3509 UInt opc2; 3510 if (i->Pin.AvBinary.op == Pav_SHL) { 3511 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo 3512 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl 3513 goto done; 3514 } 3515 if (i->Pin.AvBinary.op == Pav_SHR) { 3516 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro 3517 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr 3518 goto done; 3519 } 3520 switch (i->Pin.AvBinary.op) { 3521 /* Bitwise */ 3522 case Pav_AND: opc2 = 1028; break; // vand 3523 case Pav_OR: opc2 = 1156; break; // vor 3524 case Pav_XOR: opc2 = 1220; break; // vxor 3525 default: 3526 goto bad; 3527 } 3528 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 ); 3529 goto done; 3530 } 3531 3532 case Pin_AvBin8x16: { 3533 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst); 3534 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL); 3535 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR); 3536 UInt opc2; 3537 switch (i->Pin.AvBin8x16.op) { 3538 3539 case Pav_ADDU: opc2 = 0; break; // vaddubm 3540 case Pav_QADDU: opc2 = 512; break; // vaddubs 3541 case Pav_QADDS: opc2 = 768; break; // vaddsbs 3542 3543 case Pav_SUBU: opc2 = 1024; break; // vsububm 3544 case Pav_QSUBU: opc2 = 1536; break; // vsububs 3545 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs 3546 3547 case Pav_OMULU: opc2 = 8; break; // vmuloub 3548 case Pav_OMULS: opc2 = 264; break; // vmulosb 3549 case Pav_EMULU: opc2 = 520; break; // vmuleub 3550 case Pav_EMULS: opc2 = 776; break; // vmulesb 3551 3552 case Pav_AVGU: opc2 = 1026; break; // vavgub 3553 case Pav_AVGS: opc2 = 1282; break; // vavgsb 3554 case Pav_MAXU: opc2 = 2; break; // vmaxub 3555 case Pav_MAXS: opc2 = 258; break; // vmaxsb 3556 case Pav_MINU: opc2 = 514; break; // vminub 3557 case Pav_MINS: opc2 = 770; break; // vminsb 3558 3559 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb 3560 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub 3561 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb 3562 3563 case Pav_SHL: opc2 = 260; break; // vslb 3564 case Pav_SHR: opc2 = 516; break; // vsrb 3565 case Pav_SAR: opc2 = 772; break; // vsrab 3566 case Pav_ROTL: opc2 = 4; break; // vrlb 3567 3568 case Pav_MRGHI: opc2 = 12; break; // vmrghb 3569 case Pav_MRGLO: opc2 = 268; break; // vmrglb 3570 3571 default: 3572 goto bad; 3573 } 3574 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 ); 3575 goto done; 3576 } 3577 3578 case Pin_AvBin16x8: { 3579 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst); 3580 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL); 3581 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR); 3582 UInt opc2; 3583 switch (i->Pin.AvBin16x8.op) { 3584 3585 case Pav_ADDU: opc2 = 64; break; // vadduhm 3586 case Pav_QADDU: opc2 = 576; break; // vadduhs 3587 case Pav_QADDS: opc2 = 832; break; // vaddshs 3588 3589 case Pav_SUBU: opc2 = 1088; break; // vsubuhm 3590 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs 3591 case Pav_QSUBS: opc2 = 1856; break; // vsubshs 3592 3593 case Pav_OMULU: opc2 = 72; break; // vmulouh 3594 case Pav_OMULS: opc2 = 328; break; // vmulosh 3595 case Pav_EMULU: opc2 = 584; break; // vmuleuh 3596 case Pav_EMULS: opc2 = 840; break; // vmulesh 3597 3598 case Pav_AVGU: opc2 = 1090; break; // vavguh 3599 case Pav_AVGS: opc2 = 1346; break; // vavgsh 3600 case Pav_MAXU: opc2 = 66; break; // vmaxuh 3601 case Pav_MAXS: opc2 = 322; break; // vmaxsh 3602 case Pav_MINS: opc2 = 834; break; // vminsh 3603 case Pav_MINU: opc2 = 578; break; // vminuh 3604 3605 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh 3606 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh 3607 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh 3608 3609 case Pav_SHL: opc2 = 324; break; // vslh 3610 case Pav_SHR: opc2 = 580; break; // vsrh 3611 case Pav_SAR: opc2 = 836; break; // vsrah 3612 case Pav_ROTL: opc2 = 68; break; // vrlh 3613 3614 case Pav_PACKUU: opc2 = 14; break; // vpkuhum 3615 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus 3616 case Pav_QPACKSU: opc2 = 270; break; // vpkshus 3617 case Pav_QPACKSS: opc2 = 398; break; // vpkshss 3618 case Pav_PACKPXL: opc2 = 782; break; // vpkpx 3619 3620 case Pav_MRGHI: opc2 = 76; break; // vmrghh 3621 case Pav_MRGLO: opc2 = 332; break; // vmrglh 3622 3623 default: 3624 goto bad; 3625 } 3626 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 ); 3627 goto done; 3628 } 3629 3630 case Pin_AvBin32x4: { 3631 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst); 3632 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL); 3633 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR); 3634 UInt opc2; 3635 switch (i->Pin.AvBin32x4.op) { 3636 3637 case Pav_ADDU: opc2 = 128; break; // vadduwm 3638 case Pav_QADDU: opc2 = 640; break; // vadduws 3639 case Pav_QADDS: opc2 = 896; break; // vaddsws 3640 3641 case Pav_SUBU: opc2 = 1152; break; // vsubuwm 3642 case Pav_QSUBU: opc2 = 1664; break; // vsubuws 3643 case Pav_QSUBS: opc2 = 1920; break; // vsubsws 3644 3645 case Pav_AVGU: opc2 = 1154; break; // vavguw 3646 case Pav_AVGS: opc2 = 1410; break; // vavgsw 3647 3648 case Pav_MAXU: opc2 = 130; break; // vmaxuw 3649 case Pav_MAXS: opc2 = 386; break; // vmaxsw 3650 3651 case Pav_MINS: opc2 = 898; break; // vminsw 3652 case Pav_MINU: opc2 = 642; break; // vminuw 3653 3654 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw 3655 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw 3656 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw 3657 3658 case Pav_SHL: opc2 = 388; break; // vslw 3659 case Pav_SHR: opc2 = 644; break; // vsrw 3660 case Pav_SAR: opc2 = 900; break; // vsraw 3661 case Pav_ROTL: opc2 = 132; break; // vrlw 3662 3663 case Pav_PACKUU: opc2 = 78; break; // vpkuwum 3664 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus 3665 case Pav_QPACKSU: opc2 = 334; break; // vpkswus 3666 case Pav_QPACKSS: opc2 = 462; break; // vpkswss 3667 3668 case Pav_MRGHI: opc2 = 140; break; // vmrghw 3669 case Pav_MRGLO: opc2 = 396; break; // vmrglw 3670 3671 default: 3672 goto bad; 3673 } 3674 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 ); 3675 goto done; 3676 } 3677 3678 case Pin_AvBin32Fx4: { 3679 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst); 3680 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL); 3681 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR); 3682 switch (i->Pin.AvBin32Fx4.op) { 3683 3684 case Pavfp_ADDF: 3685 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp 3686 break; 3687 case Pavfp_SUBF: 3688 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp 3689 break; 3690 case Pavfp_MAXF: 3691 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp 3692 break; 3693 case Pavfp_MINF: 3694 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp 3695 break; 3696 3697 case Pavfp_MULF: { 3698 /* Make a vmulfp from a vmaddfp: 3699 load -0.0 (0x8000_0000) to each 32-bit word of vB 3700 this makes the add a noop. 3701 */ 3702 UInt vB = 29; // XXX: Using v29 for temp do not change 3703 // without also changing 3704 // getRegUsage_PPCInstr 3705 UInt konst = 0x1F; 3706 3707 // Better way to load -0.0 (0x80000000) ? 3708 // vspltisw vB,0x1F (0x1F => each word of vB) 3709 p = mkFormVX( p, 4, vB, konst, 0, 908 ); 3710 3711 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000 3712 p = mkFormVX( p, 4, vB, vB, vB, 388 ); 3713 3714 // Finally, do the multiply: 3715 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 ); 3716 break; 3717 } 3718 case Pavfp_CMPEQF: // vcmpeqfp 3719 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); 3720 break; 3721 case Pavfp_CMPGTF: // vcmpgtfp 3722 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 ); 3723 break; 3724 case Pavfp_CMPGEF: // vcmpgefp 3725 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 ); 3726 break; 3727 3728 default: 3729 goto bad; 3730 } 3731 goto done; 3732 } 3733 3734 case Pin_AvUn32Fx4: { 3735 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst); 3736 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src); 3737 UInt opc2; 3738 switch (i->Pin.AvUn32Fx4.op) { 3739 case Pavfp_RCPF: opc2 = 266; break; // vrefp 3740 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp 3741 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux 3742 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx 3743 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs 3744 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs 3745 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim 3746 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip 3747 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin 3748 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz 3749 default: 3750 goto bad; 3751 } 3752 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 ); 3753 goto done; 3754 } 3755 3756 case Pin_AvPerm: { // vperm 3757 UInt v_dst = vregNo(i->Pin.AvPerm.dst); 3758 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL); 3759 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR); 3760 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl); 3761 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 ); 3762 goto done; 3763 } 3764 3765 case Pin_AvSel: { // vsel 3766 UInt v_ctl = vregNo(i->Pin.AvSel.ctl); 3767 UInt v_dst = vregNo(i->Pin.AvSel.dst); 3768 UInt v_srcL = vregNo(i->Pin.AvSel.srcL); 3769 UInt v_srcR = vregNo(i->Pin.AvSel.srcR); 3770 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 ); 3771 goto done; 3772 } 3773 3774 case Pin_AvShlDbl: { // vsldoi 3775 UInt shift = i->Pin.AvShlDbl.shift; 3776 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst); 3777 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL); 3778 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR); 3779 vassert(shift <= 0xF); 3780 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 ); 3781 goto done; 3782 } 3783 3784 case Pin_AvSplat: { // vsplt(is)(b,h,w) 3785 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst); 3786 UChar sz = i->Pin.AvSplat.sz; 3787 UInt v_src, opc2; 3788 vassert(sz == 8 || sz == 16 || sz == 32); 3789 3790 if (i->Pin.AvSplat.src->tag == Pvi_Imm) { 3791 Char simm5; 3792 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32 3793 /* expects 5-bit-signed-imm */ 3794 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s; 3795 vassert(simm5 >= -16 && simm5 <= 15); 3796 simm5 = simm5 & 0x1F; 3797 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 ); 3798 } 3799 else { // Pri_Reg 3800 UInt lowest_lane; 3801 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32 3802 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128); 3803 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg); 3804 lowest_lane = (128/sz)-1; 3805 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 ); 3806 } 3807 goto done; 3808 } 3809 3810 case Pin_AvCMov: { 3811 UInt v_dst = vregNo(i->Pin.AvCMov.dst); 3812 UInt v_src = vregNo(i->Pin.AvCMov.src); 3813 PPCCondCode cc = i->Pin.AvCMov.cond; 3814 3815 if (v_dst == v_src) goto done; 3816 3817 vassert(cc.test != Pct_ALWAYS); 3818 3819 /* jmp fwds 2 insns if !condition */ 3820 if (cc.test != Pct_ALWAYS) { 3821 /* bc !ct,cf,n_bytes>>2 */ 3822 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0); 3823 } 3824 /* vmr */ 3825 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 ); 3826 goto done; 3827 } 3828 3829 case Pin_AvLdVSCR: { // mtvscr 3830 UInt v_src = vregNo(i->Pin.AvLdVSCR.src); 3831 p = mkFormVX( p, 4, 0, 0, v_src, 1604 ); 3832 goto done; 3833 } 3834 3835 default: 3836 goto bad; 3837 } 3838 3839 bad: 3840 vex_printf("\n=> "); 3841 ppPPCInstr(i, mode64); 3842 vpanic("emit_PPCInstr"); 3843 /*NOTREACHED*/ 3844 3845 done: 3846 vassert(p - &buf[0] <= 32); 3847 return p - &buf[0]; 3848 } 3849 3850 /*---------------------------------------------------------------*/ 3851 /*--- end host_ppc_defs.c ---*/ 3852 /*---------------------------------------------------------------*/ 3853