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