1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*---------------------------------------------------------------*/ 4 /*--- begin host_s390_defs.c ---*/ 5 /*---------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright IBM Corp. 2010-2013 12 Copyright (C) 2012-2013 Florian Krohm (britzel (at) acm.org) 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 27 02110-1301, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 */ 31 32 /* Contributed by Florian Krohm */ 33 34 #include "libvex_basictypes.h" 35 #include "libvex.h" 36 #include "libvex_trc_values.h" 37 #include "libvex_s390x_common.h" 38 39 #include "main_util.h" 40 #include "main_globals.h" 41 #include "host_generic_regs.h" 42 #include "host_s390_defs.h" 43 #include "s390_disasm.h" 44 #include "guest_s390_defs.h" /* S390X_GUEST_OFFSET */ 45 #include <stdarg.h> 46 47 /* KLUDGE: We need to know the hwcaps of the host when generating 48 code. But that info is not passed to emit_S390Instr. Only mode64 is 49 being passed. So, ideally, we want this passed as an argument, too. 50 Until then, we use a global variable. This variable is set as a side 51 effect of iselSB_S390. This is safe because instructions are selected 52 before they are emitted. */ 53 UInt s390_host_hwcaps; 54 55 56 /*------------------------------------------------------------*/ 57 /*--- Forward declarations ---*/ 58 /*------------------------------------------------------------*/ 59 60 static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst); 61 static void s390_insn_map_regs(HRegRemap *, s390_insn *); 62 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *); 63 static UInt s390_tchain_load64_len(void); 64 65 66 /*------------------------------------------------------------*/ 67 /*--- Registers ---*/ 68 /*------------------------------------------------------------*/ 69 70 /* Decompile the given register into a static buffer and return it */ 71 const HChar * 72 s390_hreg_as_string(HReg reg) 73 { 74 static HChar buf[10]; 75 76 static const HChar ireg_names[16][5] = { 77 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", 78 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 79 }; 80 81 static const HChar freg_names[16][5] = { 82 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", 83 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15" 84 }; 85 86 UInt r; /* hregNumber() returns an UInt */ 87 88 r = hregNumber(reg); 89 90 /* Be generic for all virtual regs. */ 91 if (hregIsVirtual(reg)) { 92 buf[0] = '\0'; 93 switch (hregClass(reg)) { 94 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break; 95 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break; 96 default: goto fail; 97 } 98 return buf; 99 } 100 101 /* But specific for real regs. */ 102 vassert(r < 16); 103 104 switch (hregClass(reg)) { 105 case HRcInt64: return ireg_names[r]; 106 case HRcFlt64: return freg_names[r]; 107 default: goto fail; 108 } 109 110 fail: vpanic("s390_hreg_as_string"); 111 } 112 113 114 /* Tell the register allocator which registers can be allocated. */ 115 static void 116 s390_hreg_get_allocable(Int *nregs, HReg **arr) 117 { 118 UInt i; 119 120 /* Total number of allocable registers (all classes) */ 121 *nregs = 16 /* GPRs */ 122 - 1 /* r0 */ 123 - 1 /* r12 scratch register for translation chaining support */ 124 - 1 /* r13 guest state pointer */ 125 - 1 /* r14 link register */ 126 - 1 /* r15 stack pointer */ 127 + 16 /* FPRs */ 128 ; 129 130 *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); 131 132 i = 0; 133 134 /* GPR0 is not available because it is interpreted as 0, when used 135 as a base or index register. */ 136 (*arr)[i++] = mkHReg(1, HRcInt64, False); 137 (*arr)[i++] = mkHReg(2, HRcInt64, False); 138 (*arr)[i++] = mkHReg(3, HRcInt64, False); 139 (*arr)[i++] = mkHReg(4, HRcInt64, False); 140 (*arr)[i++] = mkHReg(5, HRcInt64, False); 141 (*arr)[i++] = mkHReg(6, HRcInt64, False); 142 (*arr)[i++] = mkHReg(7, HRcInt64, False); 143 (*arr)[i++] = mkHReg(8, HRcInt64, False); 144 (*arr)[i++] = mkHReg(9, HRcInt64, False); 145 /* GPR10 and GPR11 are used for instructions that use register pairs. 146 Otherwise, they are available to the allocator */ 147 (*arr)[i++] = mkHReg(10, HRcInt64, False); 148 (*arr)[i++] = mkHReg(11, HRcInt64, False); 149 /* GPR12 is not available because it us used as a scratch register 150 in translation chaining. */ 151 /* GPR13 is not available because it is used as guest state pointer */ 152 /* GPR14 is not available because it is used as link register */ 153 /* GPR15 is not available because it is used as stack pointer */ 154 155 /* Add the available real (non-virtual) FPRs */ 156 (*arr)[i++] = mkHReg(0, HRcFlt64, False); 157 (*arr)[i++] = mkHReg(1, HRcFlt64, False); 158 (*arr)[i++] = mkHReg(2, HRcFlt64, False); 159 (*arr)[i++] = mkHReg(3, HRcFlt64, False); 160 (*arr)[i++] = mkHReg(4, HRcFlt64, False); 161 (*arr)[i++] = mkHReg(5, HRcFlt64, False); 162 (*arr)[i++] = mkHReg(6, HRcFlt64, False); 163 (*arr)[i++] = mkHReg(7, HRcFlt64, False); 164 (*arr)[i++] = mkHReg(8, HRcFlt64, False); 165 (*arr)[i++] = mkHReg(9, HRcFlt64, False); 166 (*arr)[i++] = mkHReg(10, HRcFlt64, False); 167 (*arr)[i++] = mkHReg(11, HRcFlt64, False); 168 (*arr)[i++] = mkHReg(12, HRcFlt64, False); 169 (*arr)[i++] = mkHReg(13, HRcFlt64, False); 170 (*arr)[i++] = mkHReg(14, HRcFlt64, False); 171 (*arr)[i++] = mkHReg(15, HRcFlt64, False); 172 /* FPR12 - FPR15 are also used as register pairs for 128-bit 173 floating point operations */ 174 } 175 176 177 /* Return the real register that holds the guest state pointer */ 178 HReg 179 s390_hreg_guest_state_pointer(void) 180 { 181 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False); 182 } 183 184 185 /* Is VALUE within the domain of a 20-bit signed integer. */ 186 static __inline__ Bool 187 fits_signed_20bit(Int value) 188 { 189 return ((value << 12) >> 12) == value; 190 } 191 192 193 /* Is VALUE within the domain of a 12-bit unsigned integer. */ 194 static __inline__ Bool 195 fits_unsigned_12bit(Int value) 196 { 197 return (value & 0xFFF) == value; 198 } 199 200 /*------------------------------------------------------------*/ 201 /*--- Addressing modes (amodes) ---*/ 202 /*------------------------------------------------------------*/ 203 204 /* Construct a b12 amode. */ 205 s390_amode * 206 s390_amode_b12(Int d, HReg b) 207 { 208 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 209 210 vassert(fits_unsigned_12bit(d)); 211 212 am->tag = S390_AMODE_B12; 213 am->d = d; 214 am->b = b; 215 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */ 216 217 return am; 218 } 219 220 221 /* Construct a b20 amode. */ 222 s390_amode * 223 s390_amode_b20(Int d, HReg b) 224 { 225 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 226 227 vassert(fits_signed_20bit(d)); 228 229 am->tag = S390_AMODE_B20; 230 am->d = d; 231 am->b = b; 232 am->x = mkHReg(0, HRcInt64, False); /* hregNumber(am->x) == 0 */ 233 234 return am; 235 } 236 237 238 /* Construct a bx12 amode. */ 239 s390_amode * 240 s390_amode_bx12(Int d, HReg b, HReg x) 241 { 242 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 243 244 vassert(fits_unsigned_12bit(d)); 245 vassert(hregNumber(b) != 0); 246 vassert(hregNumber(x) != 0); 247 248 am->tag = S390_AMODE_BX12; 249 am->d = d; 250 am->b = b; 251 am->x = x; 252 253 return am; 254 } 255 256 257 /* Construct a bx20 amode. */ 258 s390_amode * 259 s390_amode_bx20(Int d, HReg b, HReg x) 260 { 261 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 262 263 vassert(fits_signed_20bit(d)); 264 vassert(hregNumber(b) != 0); 265 vassert(hregNumber(x) != 0); 266 267 am->tag = S390_AMODE_BX20; 268 am->d = d; 269 am->b = b; 270 am->x = x; 271 272 return am; 273 } 274 275 276 /* Construct an AMODE for accessing the guest state at OFFSET. 277 OFFSET can be at most 3 * sizeof(VexGuestS390XState) + LibVEX_N_SPILL_BYTES 278 which may be too large for a B12 addressing mode. 279 Use a B20 amode as a fallback which will be safe for any offset. 280 */ 281 s390_amode * 282 s390_amode_for_guest_state(Int offset) 283 { 284 if (fits_unsigned_12bit(offset)) 285 return s390_amode_b12(offset, s390_hreg_guest_state_pointer()); 286 287 if (fits_signed_20bit(offset)) 288 return s390_amode_b20(offset, s390_hreg_guest_state_pointer()); 289 290 vpanic("invalid guest state offset"); 291 } 292 293 294 /* Decompile the given amode into a static buffer and return it. */ 295 const HChar * 296 s390_amode_as_string(const s390_amode *am) 297 { 298 static HChar buf[30]; 299 HChar *p; 300 301 buf[0] = '\0'; 302 p = buf; 303 304 switch (am->tag) { 305 case S390_AMODE_B12: 306 case S390_AMODE_B20: 307 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b)); 308 break; 309 310 case S390_AMODE_BX12: 311 case S390_AMODE_BX20: 312 /* s390_hreg_as_string returns pointer to local buffer. Need to 313 split this into two printfs */ 314 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x)); 315 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b)); 316 break; 317 318 default: 319 vpanic("s390_amode_as_string"); 320 } 321 322 return buf; 323 } 324 325 326 /* Helper function for s390_amode_is_sane */ 327 static __inline__ Bool 328 is_virtual_gpr(HReg reg) 329 { 330 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64; 331 } 332 333 334 /* Sanity check for an amode */ 335 Bool 336 s390_amode_is_sane(const s390_amode *am) 337 { 338 switch (am->tag) { 339 case S390_AMODE_B12: 340 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d); 341 342 case S390_AMODE_B20: 343 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d); 344 345 case S390_AMODE_BX12: 346 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) && 347 fits_unsigned_12bit(am->d); 348 349 case S390_AMODE_BX20: 350 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) && 351 fits_signed_20bit(am->d); 352 353 default: 354 vpanic("s390_amode_is_sane"); 355 } 356 } 357 358 359 /* Record the register use of an amode */ 360 static void 361 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am) 362 { 363 switch (am->tag) { 364 case S390_AMODE_B12: 365 case S390_AMODE_B20: 366 addHRegUse(u, HRmRead, am->b); 367 return; 368 369 case S390_AMODE_BX12: 370 case S390_AMODE_BX20: 371 addHRegUse(u, HRmRead, am->b); 372 addHRegUse(u, HRmRead, am->x); 373 return; 374 375 default: 376 vpanic("s390_amode_get_reg_usage"); 377 } 378 } 379 380 381 static void 382 s390_amode_map_regs(HRegRemap *m, s390_amode *am) 383 { 384 switch (am->tag) { 385 case S390_AMODE_B12: 386 case S390_AMODE_B20: 387 am->b = lookupHRegRemap(m, am->b); 388 return; 389 390 case S390_AMODE_BX12: 391 case S390_AMODE_BX20: 392 am->b = lookupHRegRemap(m, am->b); 393 am->x = lookupHRegRemap(m, am->x); 394 return; 395 396 default: 397 vpanic("s390_amode_map_regs"); 398 } 399 } 400 401 402 void 403 ppS390AMode(s390_amode *am) 404 { 405 vex_printf("%s", s390_amode_as_string(am)); 406 } 407 408 void 409 ppS390Instr(s390_insn *insn, Bool mode64) 410 { 411 vex_printf("%s", s390_insn_as_string(insn)); 412 } 413 414 void 415 ppHRegS390(HReg reg) 416 { 417 vex_printf("%s", s390_hreg_as_string(reg)); 418 } 419 420 /*------------------------------------------------------------*/ 421 /*--- Helpers for register allocation ---*/ 422 /*------------------------------------------------------------*/ 423 424 /* Called once per translation. */ 425 void 426 getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64) 427 { 428 s390_hreg_get_allocable(nregs, arr); 429 } 430 431 432 /* Tell the register allocator how the given instruction uses the registers 433 it refers to. */ 434 void 435 getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64) 436 { 437 s390_insn_get_reg_usage(u, insn); 438 } 439 440 441 /* Map the registers of the given instruction */ 442 void 443 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64) 444 { 445 s390_insn_map_regs(m, insn); 446 } 447 448 449 /* Figure out if the given insn represents a reg-reg move, and if so 450 assign the source and destination to *src and *dst. If in doubt say No. 451 Used by the register allocator to do move coalescing. */ 452 Bool 453 isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst) 454 { 455 return s390_insn_is_reg_reg_move(insn, src, dst); 456 } 457 458 459 /* Generate s390 spill/reload instructions under the direction of the 460 register allocator. Note it's critical these don't write the 461 condition codes. This is like an Ist_Put */ 462 void 463 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64) 464 { 465 s390_amode *am; 466 467 vassert(offsetB >= 0); 468 vassert(!hregIsVirtual(rreg)); 469 470 *i1 = *i2 = NULL; 471 472 am = s390_amode_for_guest_state(offsetB); 473 474 switch (hregClass(rreg)) { 475 case HRcInt64: 476 case HRcFlt64: 477 *i1 = s390_insn_store(8, am, rreg); 478 return; 479 480 default: 481 ppHRegClass(hregClass(rreg)); 482 vpanic("genSpill_S390: unimplemented regclass"); 483 } 484 } 485 486 487 /* This is like an Iex_Get */ 488 void 489 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64) 490 { 491 s390_amode *am; 492 493 vassert(offsetB >= 0); 494 vassert(!hregIsVirtual(rreg)); 495 496 *i1 = *i2 = NULL; 497 498 am = s390_amode_for_guest_state(offsetB); 499 500 switch (hregClass(rreg)) { 501 case HRcInt64: 502 case HRcFlt64: 503 *i1 = s390_insn_load(8, rreg, am); 504 return; 505 506 default: 507 ppHRegClass(hregClass(rreg)); 508 vpanic("genReload_S390: unimplemented regclass"); 509 } 510 } 511 512 /* Helper function for s390_insn_get_reg_usage */ 513 static void 514 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op) 515 { 516 switch (op.tag) { 517 case S390_OPND_REG: 518 addHRegUse(u, HRmRead, op.variant.reg); 519 break; 520 521 case S390_OPND_AMODE: 522 s390_amode_get_reg_usage(u, op.variant.am); 523 break; 524 525 case S390_OPND_IMMEDIATE: 526 break; 527 528 default: 529 vpanic("s390_opnd_RMI_get_reg_usage"); 530 } 531 } 532 533 534 /* Tell the register allocator how the given insn uses the registers */ 535 static void 536 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn) 537 { 538 initHRegUsage(u); 539 540 switch (insn->tag) { 541 case S390_INSN_LOAD: 542 addHRegUse(u, HRmWrite, insn->variant.load.dst); 543 s390_amode_get_reg_usage(u, insn->variant.load.src); 544 break; 545 546 case S390_INSN_LOAD_IMMEDIATE: 547 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst); 548 break; 549 550 case S390_INSN_STORE: 551 addHRegUse(u, HRmRead, insn->variant.store.src); 552 s390_amode_get_reg_usage(u, insn->variant.store.dst); 553 break; 554 555 case S390_INSN_MOVE: 556 addHRegUse(u, HRmRead, insn->variant.move.src); 557 addHRegUse(u, HRmWrite, insn->variant.move.dst); 558 break; 559 560 case S390_INSN_MEMCPY: 561 s390_amode_get_reg_usage(u, insn->variant.memcpy.src); 562 s390_amode_get_reg_usage(u, insn->variant.memcpy.dst); 563 break; 564 565 case S390_INSN_COND_MOVE: 566 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src); 567 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst); 568 break; 569 570 case S390_INSN_ALU: 571 addHRegUse(u, HRmWrite, insn->variant.alu.dst); 572 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */ 573 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2); 574 break; 575 576 case S390_INSN_SMUL: 577 case S390_INSN_UMUL: 578 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */ 579 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo); 580 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi); 581 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2); 582 break; 583 584 case S390_INSN_SDIV: 585 case S390_INSN_UDIV: 586 addHRegUse(u, HRmRead, insn->variant.div.op1_lo); 587 addHRegUse(u, HRmRead, insn->variant.div.op1_hi); 588 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo); 589 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi); 590 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2); 591 break; 592 593 case S390_INSN_DIVS: 594 addHRegUse(u, HRmRead, insn->variant.divs.op1); 595 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */ 596 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */ 597 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2); 598 break; 599 600 case S390_INSN_CLZ: 601 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits); 602 addHRegUse(u, HRmWrite, insn->variant.clz.clobber); 603 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src); 604 break; 605 606 case S390_INSN_UNOP: 607 addHRegUse(u, HRmWrite, insn->variant.unop.dst); 608 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src); 609 break; 610 611 case S390_INSN_TEST: 612 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src); 613 break; 614 615 case S390_INSN_CC2BOOL: 616 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst); 617 break; 618 619 case S390_INSN_CAS: 620 addHRegUse(u, HRmRead, insn->variant.cas.op1); 621 s390_amode_get_reg_usage(u, insn->variant.cas.op2); 622 addHRegUse(u, HRmRead, insn->variant.cas.op3); 623 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem); 624 break; 625 626 case S390_INSN_CDAS: { 627 s390_cdas *cdas = insn->variant.cdas.details; 628 629 addHRegUse(u, HRmRead, cdas->op1_high); 630 addHRegUse(u, HRmRead, cdas->op1_low); 631 s390_amode_get_reg_usage(u, cdas->op2); 632 addHRegUse(u, HRmRead, cdas->op3_high); 633 addHRegUse(u, HRmRead, cdas->op3_low); 634 addHRegUse(u, HRmWrite, cdas->old_mem_high); 635 addHRegUse(u, HRmWrite, cdas->old_mem_low); 636 addHRegUse(u, HRmWrite, cdas->scratch); 637 break; 638 } 639 640 case S390_INSN_COMPARE: 641 addHRegUse(u, HRmRead, insn->variant.compare.src1); 642 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2); 643 break; 644 645 case S390_INSN_HELPER_CALL: { 646 UInt i; 647 648 /* Assume that all volatile registers are clobbered. ABI says, 649 volatile registers are: r0 - r5. Valgrind's register allocator 650 does not know about r0, so we can leave that out */ 651 for (i = 1; i <= 5; ++i) { 652 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False)); 653 } 654 655 /* Ditto for floating point registers. f0 - f7 are volatile */ 656 for (i = 0; i <= 7; ++i) { 657 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False)); 658 } 659 660 /* The registers that are used for passing arguments will be read. 661 Not all of them may, but in general we need to assume that. */ 662 for (i = 0; i < insn->variant.helper_call.details->num_args; ++i) { 663 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i), 664 HRcInt64, False)); 665 } 666 667 /* s390_insn_helper_call_emit also reads / writes the link register 668 and stack pointer. But those registers are not visible to the 669 register allocator. So we don't need to do anything for them. */ 670 break; 671 } 672 673 case S390_INSN_BFP_TRIOP: 674 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst); 675 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */ 676 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */ 677 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */ 678 break; 679 680 case S390_INSN_BFP_BINOP: 681 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_hi); 682 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_hi); /* left */ 683 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_hi); /* right */ 684 if (insn->size == 16) { 685 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst_lo); 686 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst_lo); /* left */ 687 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2_lo); /* right */ 688 } 689 break; 690 691 case S390_INSN_BFP_UNOP: 692 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_hi); 693 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_hi); /* operand */ 694 if (insn->size == 16) { 695 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst_lo); 696 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op_lo); /* operand */ 697 } 698 break; 699 700 case S390_INSN_BFP_COMPARE: 701 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst); 702 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_hi); /* left */ 703 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_hi); /* right */ 704 if (insn->size == 16) { 705 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1_lo); /* left */ 706 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2_lo); /* right */ 707 } 708 break; 709 710 case S390_INSN_BFP_CONVERT: 711 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_hi); 712 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo)) 713 addHRegUse(u, HRmWrite, insn->variant.bfp_convert.dst_lo); 714 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_hi); 715 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo)) 716 addHRegUse(u, HRmRead, insn->variant.bfp_convert.op_lo); 717 break; 718 719 case S390_INSN_DFP_BINOP: { 720 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details; 721 722 addHRegUse(u, HRmWrite, dfp_binop->dst_hi); 723 addHRegUse(u, HRmRead, dfp_binop->op2_hi); /* left */ 724 addHRegUse(u, HRmRead, dfp_binop->op3_hi); /* right */ 725 if (insn->size == 16) { 726 addHRegUse(u, HRmWrite, dfp_binop->dst_lo); 727 addHRegUse(u, HRmRead, dfp_binop->op2_lo); /* left */ 728 addHRegUse(u, HRmRead, dfp_binop->op3_lo); /* right */ 729 } 730 break; 731 } 732 733 case S390_INSN_DFP_UNOP: 734 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_hi); 735 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_hi); /* operand */ 736 if (insn->size == 16) { 737 addHRegUse(u, HRmWrite, insn->variant.dfp_unop.dst_lo); 738 addHRegUse(u, HRmRead, insn->variant.dfp_unop.op_lo); /* operand */ 739 } 740 break; 741 742 case S390_INSN_DFP_INTOP: 743 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_hi); 744 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op2); 745 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_hi); 746 if (insn->size == 16) { 747 addHRegUse(u, HRmWrite, insn->variant.dfp_intop.dst_lo); 748 addHRegUse(u, HRmRead, insn->variant.dfp_intop.op3_lo); 749 } 750 break; 751 752 case S390_INSN_DFP_COMPARE: 753 addHRegUse(u, HRmWrite, insn->variant.dfp_compare.dst); 754 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_hi); /* left */ 755 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_hi); /* right */ 756 if (insn->size == 16) { 757 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op1_lo); /* left */ 758 addHRegUse(u, HRmRead, insn->variant.dfp_compare.op2_lo); /* right */ 759 } 760 break; 761 762 case S390_INSN_DFP_CONVERT: 763 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_hi); 764 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo)) 765 addHRegUse(u, HRmWrite, insn->variant.dfp_convert.dst_lo); 766 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_hi); /* operand */ 767 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo)) 768 addHRegUse(u, HRmRead, insn->variant.dfp_convert.op_lo); /* operand */ 769 break; 770 771 case S390_INSN_DFP_REROUND: 772 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_hi); 773 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op2); /* left */ 774 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_hi); /* right */ 775 if (insn->size == 16) { 776 addHRegUse(u, HRmWrite, insn->variant.dfp_reround.dst_lo); 777 addHRegUse(u, HRmRead, insn->variant.dfp_reround.op3_lo); /* right */ 778 } 779 break; 780 781 case S390_INSN_FP_CONVERT: { 782 s390_fp_convert *fp_convert = insn->variant.fp_convert.details; 783 784 addHRegUse(u, HRmWrite, fp_convert->dst_hi); 785 if (! hregIsInvalid(fp_convert->dst_lo)) 786 addHRegUse(u, HRmWrite, fp_convert->dst_lo); 787 addHRegUse(u, HRmRead, fp_convert->op_hi); 788 if (! hregIsInvalid(fp_convert->op_lo)) 789 addHRegUse(u, HRmRead, fp_convert->op_lo); 790 addHRegUse(u, HRmWrite, fp_convert->r1); 791 break; 792 } 793 794 case S390_INSN_MIMM: 795 s390_amode_get_reg_usage(u, insn->variant.mimm.dst); 796 break; 797 798 case S390_INSN_MADD: 799 s390_amode_get_reg_usage(u, insn->variant.madd.dst); 800 break; 801 802 case S390_INSN_MFENCE: 803 break; 804 805 case S390_INSN_SET_FPC_BFPRM: 806 addHRegUse(u, HRmRead, insn->variant.set_fpc_bfprm.mode); 807 break; 808 809 case S390_INSN_SET_FPC_DFPRM: 810 addHRegUse(u, HRmRead, insn->variant.set_fpc_dfprm.mode); 811 break; 812 813 case S390_INSN_EVCHECK: 814 s390_amode_get_reg_usage(u, insn->variant.evcheck.counter); 815 s390_amode_get_reg_usage(u, insn->variant.evcheck.fail_addr); 816 break; 817 818 case S390_INSN_PROFINC: 819 /* Does not use any register visible to the register allocator */ 820 break; 821 822 case S390_INSN_XDIRECT: 823 s390_amode_get_reg_usage(u, insn->variant.xdirect.guest_IA); 824 break; 825 826 case S390_INSN_XINDIR: 827 addHRegUse(u, HRmRead, insn->variant.xindir.dst); 828 s390_amode_get_reg_usage(u, insn->variant.xindir.guest_IA); 829 break; 830 831 case S390_INSN_XASSISTED: 832 addHRegUse(u, HRmRead, insn->variant.xassisted.dst); 833 s390_amode_get_reg_usage(u, insn->variant.xassisted.guest_IA); 834 break; 835 836 default: 837 vpanic("s390_insn_get_reg_usage"); 838 } 839 } 840 841 842 /* Helper function for s390_insn_map_regs */ 843 static void 844 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op) 845 { 846 switch (op->tag) { 847 case S390_OPND_REG: 848 op->variant.reg = lookupHRegRemap(m, op->variant.reg); 849 break; 850 851 case S390_OPND_IMMEDIATE: 852 break; 853 854 case S390_OPND_AMODE: 855 s390_amode_map_regs(m, op->variant.am); 856 break; 857 858 default: 859 vpanic("s390_opnd_RMI_map_regs"); 860 } 861 } 862 863 864 static void 865 s390_insn_map_regs(HRegRemap *m, s390_insn *insn) 866 { 867 switch (insn->tag) { 868 case S390_INSN_LOAD: 869 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst); 870 s390_amode_map_regs(m, insn->variant.load.src); 871 break; 872 873 case S390_INSN_STORE: 874 s390_amode_map_regs(m, insn->variant.store.dst); 875 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src); 876 break; 877 878 case S390_INSN_MOVE: 879 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst); 880 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src); 881 break; 882 883 case S390_INSN_MEMCPY: 884 s390_amode_map_regs(m, insn->variant.memcpy.dst); 885 s390_amode_map_regs(m, insn->variant.memcpy.src); 886 break; 887 888 case S390_INSN_COND_MOVE: 889 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst); 890 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src); 891 break; 892 893 case S390_INSN_LOAD_IMMEDIATE: 894 insn->variant.load_immediate.dst = 895 lookupHRegRemap(m, insn->variant.load_immediate.dst); 896 break; 897 898 case S390_INSN_ALU: 899 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst); 900 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2); 901 break; 902 903 case S390_INSN_SMUL: 904 case S390_INSN_UMUL: 905 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi); 906 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo); 907 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2); 908 break; 909 910 case S390_INSN_SDIV: 911 case S390_INSN_UDIV: 912 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi); 913 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo); 914 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2); 915 break; 916 917 case S390_INSN_DIVS: 918 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1); 919 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem); 920 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2); 921 break; 922 923 case S390_INSN_CLZ: 924 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits); 925 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber); 926 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src); 927 break; 928 929 case S390_INSN_UNOP: 930 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst); 931 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src); 932 break; 933 934 case S390_INSN_TEST: 935 s390_opnd_RMI_map_regs(m, &insn->variant.test.src); 936 break; 937 938 case S390_INSN_CC2BOOL: 939 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst); 940 break; 941 942 case S390_INSN_CAS: 943 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1); 944 s390_amode_map_regs(m, insn->variant.cas.op2); 945 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3); 946 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem); 947 break; 948 949 case S390_INSN_CDAS: { 950 s390_cdas *cdas = insn->variant.cdas.details; 951 952 cdas->op1_high = lookupHRegRemap(m, cdas->op1_high); 953 cdas->op1_low = lookupHRegRemap(m, cdas->op1_low); 954 s390_amode_map_regs(m, cdas->op2); 955 cdas->op3_high = lookupHRegRemap(m, cdas->op3_high); 956 cdas->op3_low = lookupHRegRemap(m, cdas->op3_low); 957 cdas->old_mem_high = lookupHRegRemap(m, cdas->old_mem_high); 958 cdas->old_mem_low = lookupHRegRemap(m, cdas->old_mem_low); 959 cdas->scratch = lookupHRegRemap(m, cdas->scratch); 960 break; 961 } 962 963 case S390_INSN_COMPARE: 964 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1); 965 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2); 966 break; 967 968 case S390_INSN_HELPER_CALL: 969 /* s390_insn_helper_call_emit also reads / writes the link register 970 and stack pointer. But those registers are not visible to the 971 register allocator. So we don't need to do anything for them. 972 As for the arguments of the helper call -- they will be loaded into 973 non-virtual registers. Again, we don't need to do anything for those 974 here. */ 975 break; 976 977 case S390_INSN_BFP_TRIOP: 978 insn->variant.bfp_triop.dst = 979 lookupHRegRemap(m, insn->variant.bfp_triop.dst); 980 insn->variant.bfp_triop.op2 = 981 lookupHRegRemap(m, insn->variant.bfp_triop.op2); 982 insn->variant.bfp_triop.op3 = 983 lookupHRegRemap(m, insn->variant.bfp_triop.op3); 984 break; 985 986 case S390_INSN_BFP_BINOP: 987 insn->variant.bfp_binop.dst_hi = 988 lookupHRegRemap(m, insn->variant.bfp_binop.dst_hi); 989 insn->variant.bfp_binop.op2_hi = 990 lookupHRegRemap(m, insn->variant.bfp_binop.op2_hi); 991 if (insn->size == 16) { 992 insn->variant.bfp_binop.dst_lo = 993 lookupHRegRemap(m, insn->variant.bfp_binop.dst_lo); 994 insn->variant.bfp_binop.op2_lo = 995 lookupHRegRemap(m, insn->variant.bfp_binop.op2_lo); 996 } 997 break; 998 999 case S390_INSN_BFP_UNOP: 1000 insn->variant.bfp_unop.dst_hi = 1001 lookupHRegRemap(m, insn->variant.bfp_unop.dst_hi); 1002 insn->variant.bfp_unop.op_hi = 1003 lookupHRegRemap(m, insn->variant.bfp_unop.op_hi); 1004 if (insn->size == 16) { 1005 insn->variant.bfp_unop.dst_lo = 1006 lookupHRegRemap(m, insn->variant.bfp_unop.dst_lo); 1007 insn->variant.bfp_unop.op_lo = 1008 lookupHRegRemap(m, insn->variant.bfp_unop.op_lo); 1009 } 1010 break; 1011 1012 case S390_INSN_BFP_COMPARE: 1013 insn->variant.bfp_compare.dst = 1014 lookupHRegRemap(m, insn->variant.bfp_compare.dst); 1015 insn->variant.bfp_compare.op1_hi = 1016 lookupHRegRemap(m, insn->variant.bfp_compare.op1_hi); 1017 insn->variant.bfp_compare.op2_hi = 1018 lookupHRegRemap(m, insn->variant.bfp_compare.op2_hi); 1019 if (insn->size == 16) { 1020 insn->variant.bfp_compare.op1_lo = 1021 lookupHRegRemap(m, insn->variant.bfp_compare.op1_lo); 1022 insn->variant.bfp_compare.op2_lo = 1023 lookupHRegRemap(m, insn->variant.bfp_compare.op2_lo); 1024 } 1025 break; 1026 1027 case S390_INSN_BFP_CONVERT: 1028 insn->variant.bfp_convert.dst_hi = 1029 lookupHRegRemap(m, insn->variant.bfp_convert.dst_hi); 1030 if (! hregIsInvalid(insn->variant.bfp_convert.dst_lo)) 1031 insn->variant.bfp_convert.dst_lo = 1032 lookupHRegRemap(m, insn->variant.bfp_convert.dst_lo); 1033 insn->variant.bfp_convert.op_hi = 1034 lookupHRegRemap(m, insn->variant.bfp_convert.op_hi); 1035 if (! hregIsInvalid(insn->variant.bfp_convert.op_lo)) 1036 insn->variant.bfp_convert.op_lo = 1037 lookupHRegRemap(m, insn->variant.bfp_convert.op_lo); 1038 break; 1039 1040 case S390_INSN_DFP_BINOP: { 1041 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details; 1042 1043 dfp_binop->dst_hi = lookupHRegRemap(m, dfp_binop->dst_hi); 1044 dfp_binop->op2_hi = lookupHRegRemap(m, dfp_binop->op2_hi); 1045 dfp_binop->op3_hi = lookupHRegRemap(m, dfp_binop->op3_hi); 1046 if (insn->size == 16) { 1047 dfp_binop->dst_lo = lookupHRegRemap(m, dfp_binop->dst_lo); 1048 dfp_binop->op2_lo = lookupHRegRemap(m, dfp_binop->op2_lo); 1049 dfp_binop->op3_lo = lookupHRegRemap(m, dfp_binop->op3_lo); 1050 } 1051 break; 1052 } 1053 1054 case S390_INSN_DFP_UNOP: 1055 insn->variant.dfp_unop.dst_hi = 1056 lookupHRegRemap(m, insn->variant.dfp_unop.dst_hi); 1057 insn->variant.dfp_unop.op_hi = 1058 lookupHRegRemap(m, insn->variant.dfp_unop.op_hi); 1059 if (insn->size == 16) { 1060 insn->variant.dfp_unop.dst_lo = 1061 lookupHRegRemap(m, insn->variant.dfp_unop.dst_lo); 1062 insn->variant.dfp_unop.op_lo = 1063 lookupHRegRemap(m, insn->variant.dfp_unop.op_lo); 1064 } 1065 break; 1066 1067 case S390_INSN_DFP_INTOP: 1068 insn->variant.dfp_intop.dst_hi = 1069 lookupHRegRemap(m, insn->variant.dfp_intop.dst_hi); 1070 insn->variant.dfp_intop.op2 = 1071 lookupHRegRemap(m, insn->variant.dfp_intop.op2); 1072 insn->variant.dfp_intop.op3_hi = 1073 lookupHRegRemap(m, insn->variant.dfp_intop.op3_hi); 1074 if (insn->size == 16) { 1075 insn->variant.dfp_intop.dst_lo = 1076 lookupHRegRemap(m, insn->variant.dfp_intop.dst_lo); 1077 insn->variant.dfp_intop.op3_lo = 1078 lookupHRegRemap(m, insn->variant.dfp_intop.op3_lo); 1079 } 1080 break; 1081 1082 case S390_INSN_DFP_COMPARE: 1083 insn->variant.dfp_compare.dst = 1084 lookupHRegRemap(m, insn->variant.dfp_compare.dst); 1085 insn->variant.dfp_compare.op1_hi = 1086 lookupHRegRemap(m, insn->variant.dfp_compare.op1_hi); 1087 insn->variant.dfp_compare.op2_hi = 1088 lookupHRegRemap(m, insn->variant.dfp_compare.op2_hi); 1089 if (insn->size == 16) { 1090 insn->variant.dfp_compare.op1_lo = 1091 lookupHRegRemap(m, insn->variant.dfp_compare.op1_lo); 1092 insn->variant.dfp_compare.op2_lo = 1093 lookupHRegRemap(m, insn->variant.dfp_compare.op2_lo); 1094 } 1095 break; 1096 1097 case S390_INSN_DFP_CONVERT: 1098 insn->variant.dfp_convert.dst_hi = 1099 lookupHRegRemap(m, insn->variant.dfp_convert.dst_hi); 1100 if (! hregIsInvalid(insn->variant.dfp_convert.dst_lo)) 1101 insn->variant.dfp_convert.dst_lo = 1102 lookupHRegRemap(m, insn->variant.dfp_convert.dst_lo); 1103 insn->variant.dfp_convert.op_hi = 1104 lookupHRegRemap(m, insn->variant.dfp_convert.op_hi); 1105 if (! hregIsInvalid(insn->variant.dfp_convert.op_lo)) 1106 insn->variant.dfp_convert.op_lo = 1107 lookupHRegRemap(m, insn->variant.dfp_convert.op_lo); 1108 break; 1109 1110 case S390_INSN_DFP_REROUND: 1111 insn->variant.dfp_reround.dst_hi = 1112 lookupHRegRemap(m, insn->variant.dfp_reround.dst_hi); 1113 insn->variant.dfp_reround.op2 = 1114 lookupHRegRemap(m, insn->variant.dfp_reround.op2); 1115 insn->variant.dfp_reround.op3_hi = 1116 lookupHRegRemap(m, insn->variant.dfp_reround.op3_hi); 1117 if (insn->size == 16) { 1118 insn->variant.dfp_reround.dst_lo = 1119 lookupHRegRemap(m, insn->variant.dfp_reround.dst_lo); 1120 insn->variant.dfp_reround.op3_lo = 1121 lookupHRegRemap(m, insn->variant.dfp_reround.op3_lo); 1122 } 1123 break; 1124 1125 case S390_INSN_FP_CONVERT: { 1126 s390_fp_convert *fp_convert = insn->variant.fp_convert.details; 1127 1128 fp_convert->dst_hi = lookupHRegRemap(m, fp_convert->dst_hi); 1129 if (! hregIsInvalid(fp_convert->dst_lo)) 1130 fp_convert->dst_lo = lookupHRegRemap(m, fp_convert->dst_lo); 1131 fp_convert->op_hi = lookupHRegRemap(m, fp_convert->op_hi); 1132 if (! hregIsInvalid(fp_convert->op_lo)) 1133 fp_convert->op_lo = lookupHRegRemap(m, fp_convert->op_lo); 1134 fp_convert->r1 = lookupHRegRemap(m, fp_convert->r1); 1135 break; 1136 } 1137 1138 case S390_INSN_MIMM: 1139 s390_amode_map_regs(m, insn->variant.mimm.dst); 1140 break; 1141 1142 case S390_INSN_MADD: 1143 s390_amode_map_regs(m, insn->variant.madd.dst); 1144 break; 1145 1146 case S390_INSN_MFENCE: 1147 break; 1148 1149 case S390_INSN_SET_FPC_BFPRM: 1150 insn->variant.set_fpc_bfprm.mode = 1151 lookupHRegRemap(m, insn->variant.set_fpc_bfprm.mode); 1152 break; 1153 1154 case S390_INSN_SET_FPC_DFPRM: 1155 insn->variant.set_fpc_dfprm.mode = 1156 lookupHRegRemap(m, insn->variant.set_fpc_dfprm.mode); 1157 break; 1158 1159 case S390_INSN_EVCHECK: 1160 s390_amode_map_regs(m, insn->variant.evcheck.counter); 1161 s390_amode_map_regs(m, insn->variant.evcheck.fail_addr); 1162 break; 1163 1164 case S390_INSN_PROFINC: 1165 /* Does not use any register visible to the register allocator */ 1166 break; 1167 1168 case S390_INSN_XDIRECT: 1169 s390_amode_map_regs(m, insn->variant.xdirect.guest_IA); 1170 break; 1171 1172 case S390_INSN_XINDIR: 1173 s390_amode_map_regs(m, insn->variant.xindir.guest_IA); 1174 insn->variant.xindir.dst = 1175 lookupHRegRemap(m, insn->variant.xindir.dst); 1176 break; 1177 1178 case S390_INSN_XASSISTED: 1179 s390_amode_map_regs(m, insn->variant.xassisted.guest_IA); 1180 insn->variant.xassisted.dst = 1181 lookupHRegRemap(m, insn->variant.xassisted.dst); 1182 break; 1183 1184 default: 1185 vpanic("s390_insn_map_regs"); 1186 } 1187 } 1188 1189 1190 /* Return True, if INSN is a move between two registers of the same class. 1191 In that case assign the source and destination registers to SRC and DST, 1192 respectively. */ 1193 static Bool 1194 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst) 1195 { 1196 if (insn->tag == S390_INSN_MOVE && 1197 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) { 1198 *src = insn->variant.move.src; 1199 *dst = insn->variant.move.dst; 1200 return True; 1201 } 1202 1203 return False; 1204 } 1205 1206 1207 /*------------------------------------------------------------*/ 1208 /*--- Functions to emit a sequence of bytes ---*/ 1209 /*------------------------------------------------------------*/ 1210 1211 static __inline__ UChar * 1212 emit_2bytes(UChar *p, ULong val) 1213 { 1214 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2; 1215 } 1216 1217 1218 static __inline__ UChar * 1219 emit_4bytes(UChar *p, ULong val) 1220 { 1221 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4; 1222 } 1223 1224 1225 static __inline__ UChar * 1226 emit_6bytes(UChar *p, ULong val) 1227 { 1228 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6; 1229 } 1230 1231 1232 /*------------------------------------------------------------*/ 1233 /*--- Functions to emit various instruction formats ---*/ 1234 /*------------------------------------------------------------*/ 1235 1236 static UChar * 1237 emit_RI(UChar *p, UInt op, UChar r1, UShort i2) 1238 { 1239 ULong the_insn = op; 1240 1241 the_insn |= ((ULong)r1) << 20; 1242 the_insn |= ((ULong)i2) << 0; 1243 1244 return emit_4bytes(p, the_insn); 1245 } 1246 1247 1248 static UChar * 1249 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2) 1250 { 1251 ULong the_insn = op; 1252 1253 the_insn |= ((ULong)r1) << 36; 1254 the_insn |= ((ULong)i2) << 0; 1255 1256 return emit_6bytes(p, the_insn); 1257 } 1258 1259 1260 static UChar * 1261 emit_RR(UChar *p, UInt op, UChar r1, UChar r2) 1262 { 1263 ULong the_insn = op; 1264 1265 the_insn |= ((ULong)r1) << 4; 1266 the_insn |= ((ULong)r2) << 0; 1267 1268 return emit_2bytes(p, the_insn); 1269 } 1270 1271 1272 static UChar * 1273 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2) 1274 { 1275 ULong the_insn = op; 1276 1277 the_insn |= ((ULong)r1) << 4; 1278 the_insn |= ((ULong)r2) << 0; 1279 1280 return emit_4bytes(p, the_insn); 1281 } 1282 1283 1284 static UChar * 1285 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2) 1286 { 1287 ULong the_insn = op; 1288 1289 the_insn |= ((ULong)r1) << 12; 1290 the_insn |= ((ULong)r3) << 4; 1291 the_insn |= ((ULong)r2) << 0; 1292 1293 return emit_4bytes(p, the_insn); 1294 } 1295 1296 1297 static UChar * 1298 emit_RRF2(UChar *p, UInt op, UChar m3, UChar m4, UChar r1, UChar r2) 1299 { 1300 ULong the_insn = op; 1301 1302 the_insn |= ((ULong)m3) << 12; 1303 the_insn |= ((ULong)m4) << 8; 1304 the_insn |= ((ULong)r1) << 4; 1305 the_insn |= ((ULong)r2) << 0; 1306 1307 return emit_4bytes(p, the_insn); 1308 } 1309 1310 1311 static UChar * 1312 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2) 1313 { 1314 ULong the_insn = op; 1315 1316 the_insn |= ((ULong)r3) << 12; 1317 the_insn |= ((ULong)r1) << 4; 1318 the_insn |= ((ULong)r2) << 0; 1319 1320 return emit_4bytes(p, the_insn); 1321 } 1322 1323 1324 static UChar * 1325 emit_RRF4(UChar *p, UInt op, UChar r3, UChar m4, UChar r1, UChar r2) 1326 { 1327 ULong the_insn = op; 1328 1329 the_insn |= ((ULong)r3) << 12; 1330 the_insn |= ((ULong)m4) << 8; 1331 the_insn |= ((ULong)r1) << 4; 1332 the_insn |= ((ULong)r2) << 0; 1333 1334 return emit_4bytes(p, the_insn); 1335 } 1336 1337 1338 static UChar * 1339 emit_RRF5(UChar *p, UInt op, UChar m4, UChar r1, UChar r2) 1340 { 1341 ULong the_insn = op; 1342 1343 the_insn |= ((ULong)m4) << 8; 1344 the_insn |= ((ULong)r1) << 4; 1345 the_insn |= ((ULong)r2) << 0; 1346 1347 return emit_4bytes(p, the_insn); 1348 } 1349 1350 1351 static UChar * 1352 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2) 1353 { 1354 ULong the_insn = op; 1355 1356 the_insn |= ((ULong)r1) << 20; 1357 the_insn |= ((ULong)r3) << 16; 1358 the_insn |= ((ULong)b2) << 12; 1359 the_insn |= ((ULong)d2) << 0; 1360 1361 return emit_4bytes(p, the_insn); 1362 } 1363 1364 1365 static UChar * 1366 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1367 { 1368 ULong the_insn = op; 1369 1370 the_insn |= ((ULong)r1) << 36; 1371 the_insn |= ((ULong)r3) << 32; 1372 the_insn |= ((ULong)b2) << 28; 1373 the_insn |= ((ULong)dl2) << 16; 1374 the_insn |= ((ULong)dh2) << 8; 1375 1376 return emit_6bytes(p, the_insn); 1377 } 1378 1379 1380 static UChar * 1381 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2) 1382 { 1383 ULong the_insn = op; 1384 1385 the_insn |= ((ULong)r1) << 20; 1386 the_insn |= ((ULong)x2) << 16; 1387 the_insn |= ((ULong)b2) << 12; 1388 the_insn |= ((ULong)d2) << 0; 1389 1390 return emit_4bytes(p, the_insn); 1391 } 1392 1393 1394 static UChar * 1395 emit_RXF(UChar *p, ULong op, UChar r3, UChar x2, UChar b2, UShort d2, UChar r1) 1396 { 1397 ULong the_insn = op; 1398 1399 the_insn |= ((ULong)r3) << 36; 1400 the_insn |= ((ULong)x2) << 32; 1401 the_insn |= ((ULong)b2) << 28; 1402 the_insn |= ((ULong)d2) << 16; 1403 the_insn |= ((ULong)r1) << 12; 1404 1405 return emit_6bytes(p, the_insn); 1406 } 1407 1408 1409 static UChar * 1410 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1411 { 1412 ULong the_insn = op; 1413 1414 the_insn |= ((ULong)r1) << 36; 1415 the_insn |= ((ULong)x2) << 32; 1416 the_insn |= ((ULong)b2) << 28; 1417 the_insn |= ((ULong)dl2) << 16; 1418 the_insn |= ((ULong)dh2) << 8; 1419 1420 return emit_6bytes(p, the_insn); 1421 } 1422 1423 1424 static UChar * 1425 emit_S(UChar *p, UInt op, UChar b2, UShort d2) 1426 { 1427 ULong the_insn = op; 1428 1429 the_insn |= ((ULong)b2) << 12; 1430 the_insn |= ((ULong)d2) << 0; 1431 1432 return emit_4bytes(p, the_insn); 1433 } 1434 1435 1436 static UChar * 1437 emit_SI(UChar *p, UInt op, UChar i2, UChar b1, UShort d1) 1438 { 1439 ULong the_insn = op; 1440 1441 the_insn |= ((ULong)i2) << 16; 1442 the_insn |= ((ULong)b1) << 12; 1443 the_insn |= ((ULong)d1) << 0; 1444 1445 return emit_4bytes(p, the_insn); 1446 } 1447 1448 1449 static UChar * 1450 emit_SIL(UChar *p, ULong op, UChar b1, UShort d1, UShort i2) 1451 { 1452 ULong the_insn = op; 1453 1454 the_insn |= ((ULong)b1) << 28; 1455 the_insn |= ((ULong)d1) << 16; 1456 the_insn |= ((ULong)i2) << 0; 1457 1458 return emit_6bytes(p, the_insn); 1459 } 1460 1461 1462 static UChar * 1463 emit_SIY(UChar *p, ULong op, UChar i2, UChar b1, UShort dl1, UChar dh1) 1464 { 1465 ULong the_insn = op; 1466 1467 the_insn |= ((ULong)i2) << 32; 1468 the_insn |= ((ULong)b1) << 28; 1469 the_insn |= ((ULong)dl1) << 16; 1470 the_insn |= ((ULong)dh1) << 8; 1471 1472 return emit_6bytes(p, the_insn); 1473 } 1474 1475 1476 static UChar * 1477 emit_SSa(UChar *p, ULong op, UChar l, UChar b1, UShort d1, UChar b2, UShort d2) 1478 { 1479 ULong the_insn = op; 1480 1481 the_insn |= ((ULong)l) << 32; 1482 the_insn |= ((ULong)b1) << 28; 1483 the_insn |= ((ULong)d1) << 16; 1484 the_insn |= ((ULong)b2) << 12; 1485 the_insn |= ((ULong)d2) << 0; 1486 1487 return emit_6bytes(p, the_insn); 1488 } 1489 1490 1491 /*------------------------------------------------------------*/ 1492 /*--- Functions to emit particular instructions ---*/ 1493 /*------------------------------------------------------------*/ 1494 1495 static UChar * 1496 s390_emit_AR(UChar *p, UChar r1, UChar r2) 1497 { 1498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1499 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2); 1500 1501 return emit_RR(p, 0x1a00, r1, r2); 1502 } 1503 1504 1505 static UChar * 1506 s390_emit_AGR(UChar *p, UChar r1, UChar r2) 1507 { 1508 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1509 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2); 1510 1511 return emit_RRE(p, 0xb9080000, r1, r2); 1512 } 1513 1514 1515 static UChar * 1516 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1517 { 1518 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1519 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2); 1520 1521 return emit_RX(p, 0x5a000000, r1, x2, b2, d2); 1522 } 1523 1524 1525 static UChar * 1526 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1527 { 1528 vassert(s390_host_has_ldisp); 1529 1530 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1531 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2); 1532 1533 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2); 1534 } 1535 1536 1537 static UChar * 1538 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1539 { 1540 vassert(s390_host_has_ldisp || dh2 == 0); 1541 1542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1543 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2); 1544 1545 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2); 1546 } 1547 1548 1549 static UChar * 1550 s390_emit_AFI(UChar *p, UChar r1, UInt i2) 1551 { 1552 vassert(s390_host_has_eimm); 1553 1554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1555 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2); 1556 1557 return emit_RIL(p, 0xc20900000000ULL, r1, i2); 1558 } 1559 1560 1561 static UChar * 1562 s390_emit_AGFI(UChar *p, UChar r1, UInt i2) 1563 { 1564 vassert(s390_host_has_eimm); 1565 1566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1567 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2); 1568 1569 return emit_RIL(p, 0xc20800000000ULL, r1, i2); 1570 } 1571 1572 1573 static UChar * 1574 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1575 { 1576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1577 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2); 1578 1579 return emit_RX(p, 0x4a000000, r1, x2, b2, d2); 1580 } 1581 1582 1583 static UChar * 1584 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1585 { 1586 vassert(s390_host_has_ldisp); 1587 1588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1589 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2); 1590 1591 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2); 1592 } 1593 1594 1595 static UChar * 1596 s390_emit_AHI(UChar *p, UChar r1, UShort i2) 1597 { 1598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1599 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2); 1600 1601 return emit_RI(p, 0xa70a0000, r1, i2); 1602 } 1603 1604 1605 static UChar * 1606 s390_emit_AGHI(UChar *p, UChar r1, UShort i2) 1607 { 1608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1609 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2); 1610 1611 return emit_RI(p, 0xa70b0000, r1, i2); 1612 } 1613 1614 1615 static UChar * 1616 s390_emit_AGSI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1) 1617 { 1618 vassert(s390_host_has_gie); 1619 1620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1621 s390_disasm(ENC3(MNM, SDXB, INT), "agsi", dh1, dl1, 0, b1, (Int)(Char)i2); 1622 1623 return emit_SIY(p, 0xeb000000007aULL, i2, b1, dl1, dh1); 1624 } 1625 1626 1627 static UChar * 1628 s390_emit_ASI(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1) 1629 { 1630 vassert(s390_host_has_gie); 1631 1632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1633 s390_disasm(ENC3(MNM, SDXB, INT), "asi", dh1, dl1, 0, b1, (Int)(Char)i2); 1634 1635 return emit_SIY(p, 0xeb000000006aULL, i2, b1, dl1, dh1); 1636 } 1637 1638 1639 static UChar * 1640 s390_emit_NR(UChar *p, UChar r1, UChar r2) 1641 { 1642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1643 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2); 1644 1645 return emit_RR(p, 0x1400, r1, r2); 1646 } 1647 1648 1649 static UChar * 1650 s390_emit_NGR(UChar *p, UChar r1, UChar r2) 1651 { 1652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1653 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2); 1654 1655 return emit_RRE(p, 0xb9800000, r1, r2); 1656 } 1657 1658 1659 static UChar * 1660 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1661 { 1662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1663 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2); 1664 1665 return emit_RX(p, 0x54000000, r1, x2, b2, d2); 1666 } 1667 1668 1669 static UChar * 1670 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1671 { 1672 vassert(s390_host_has_ldisp); 1673 1674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1675 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2); 1676 1677 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2); 1678 } 1679 1680 1681 static UChar * 1682 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1683 { 1684 vassert(s390_host_has_ldisp || dh2 == 0); 1685 1686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1687 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2); 1688 1689 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2); 1690 } 1691 1692 1693 static UChar * 1694 s390_emit_NIHF(UChar *p, UChar r1, UInt i2) 1695 { 1696 vassert(s390_host_has_eimm); 1697 1698 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1699 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2); 1700 1701 return emit_RIL(p, 0xc00a00000000ULL, r1, i2); 1702 } 1703 1704 1705 static UChar * 1706 s390_emit_NILF(UChar *p, UChar r1, UInt i2) 1707 { 1708 vassert(s390_host_has_eimm); 1709 1710 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1711 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2); 1712 1713 return emit_RIL(p, 0xc00b00000000ULL, r1, i2); 1714 } 1715 1716 1717 static UChar * 1718 s390_emit_NILL(UChar *p, UChar r1, UShort i2) 1719 { 1720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1721 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2); 1722 1723 return emit_RI(p, 0xa5070000, r1, i2); 1724 } 1725 1726 1727 static UChar * 1728 s390_emit_BASR(UChar *p, UChar r1, UChar r2) 1729 { 1730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1731 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2); 1732 1733 return emit_RR(p, 0x0d00, r1, r2); 1734 } 1735 1736 1737 static UChar * 1738 s390_emit_BCR(UChar *p, UChar r1, UChar r2) 1739 { 1740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1741 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2); 1742 1743 return emit_RR(p, 0x0700, r1, r2); 1744 } 1745 1746 1747 static UChar * 1748 s390_emit_BRC(UChar *p, UChar r1, UShort i2) 1749 { 1750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1751 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2); 1752 1753 return emit_RI(p, 0xa7040000, r1, i2); 1754 } 1755 1756 1757 static UChar * 1758 s390_emit_BRCL(UChar *p, UChar r1, ULong i2) 1759 { 1760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1761 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRCL, r1, i2); 1762 1763 return emit_RIL(p, 0xc00400000000ULL, r1, i2); 1764 } 1765 1766 1767 static UChar * 1768 s390_emit_CR(UChar *p, UChar r1, UChar r2) 1769 { 1770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1771 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2); 1772 1773 return emit_RR(p, 0x1900, r1, r2); 1774 } 1775 1776 1777 static UChar * 1778 s390_emit_CGR(UChar *p, UChar r1, UChar r2) 1779 { 1780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1781 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2); 1782 1783 return emit_RRE(p, 0xb9200000, r1, r2); 1784 } 1785 1786 1787 static UChar * 1788 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1789 { 1790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1791 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2); 1792 1793 return emit_RX(p, 0x59000000, r1, x2, b2, d2); 1794 } 1795 1796 1797 static UChar * 1798 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1799 { 1800 vassert(s390_host_has_ldisp); 1801 1802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1803 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2); 1804 1805 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2); 1806 } 1807 1808 1809 static UChar * 1810 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1811 { 1812 vassert(s390_host_has_ldisp || dh2 == 0); 1813 1814 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1815 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2); 1816 1817 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2); 1818 } 1819 1820 1821 static UChar * 1822 s390_emit_CFI(UChar *p, UChar r1, UInt i2) 1823 { 1824 vassert(s390_host_has_eimm); 1825 1826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1827 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2); 1828 1829 return emit_RIL(p, 0xc20d00000000ULL, r1, i2); 1830 } 1831 1832 1833 static UChar * 1834 s390_emit_CGFI(UChar *p, UChar r1, UInt i2) 1835 { 1836 vassert(s390_host_has_eimm); 1837 1838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1839 s390_disasm(ENC3(MNM, GPR, INT), "cgfi", r1, i2); 1840 1841 return emit_RIL(p, 0xc20c00000000ULL, r1, i2); 1842 } 1843 1844 1845 static UChar * 1846 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2) 1847 { 1848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1849 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2); 1850 1851 return emit_RS(p, 0xba000000, r1, r3, b2, d2); 1852 } 1853 1854 1855 static UChar * 1856 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1857 { 1858 vassert(s390_host_has_ldisp); 1859 1860 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1861 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2); 1862 1863 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2); 1864 } 1865 1866 1867 static UChar * 1868 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1869 { 1870 vassert(s390_host_has_ldisp || dh2 == 0); 1871 1872 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1873 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2); 1874 1875 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2); 1876 } 1877 1878 1879 static UChar * 1880 s390_emit_CDS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2) 1881 { 1882 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1883 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cds", r1, r3, d2, 0, b2); 1884 1885 return emit_RS(p, 0xbb000000, r1, r3, b2, d2); 1886 } 1887 1888 1889 static UChar * 1890 s390_emit_CDSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1891 { 1892 vassert(s390_host_has_ldisp); 1893 1894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1895 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsy", r1, r3, dh2, dl2, 0, b2); 1896 1897 return emit_RSY(p, 0xeb0000000031ULL, r1, r3, b2, dl2, dh2); 1898 } 1899 1900 1901 static UChar * 1902 s390_emit_CDSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1903 { 1904 vassert(s390_host_has_ldisp || dh2 == 0); 1905 1906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1907 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "cdsg", r1, r3, dh2, dl2, 0, b2); 1908 1909 return emit_RSY(p, 0xeb000000003eULL, r1, r3, b2, dl2, dh2); 1910 } 1911 1912 1913 static UChar * 1914 s390_emit_CLR(UChar *p, UChar r1, UChar r2) 1915 { 1916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1917 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2); 1918 1919 return emit_RR(p, 0x1500, r1, r2); 1920 } 1921 1922 1923 static UChar * 1924 s390_emit_CLGR(UChar *p, UChar r1, UChar r2) 1925 { 1926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1927 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2); 1928 1929 return emit_RRE(p, 0xb9210000, r1, r2); 1930 } 1931 1932 1933 static UChar * 1934 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1935 { 1936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1937 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2); 1938 1939 return emit_RX(p, 0x55000000, r1, x2, b2, d2); 1940 } 1941 1942 1943 static UChar * 1944 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1945 { 1946 vassert(s390_host_has_ldisp); 1947 1948 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1949 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2); 1950 1951 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2); 1952 } 1953 1954 1955 static UChar * 1956 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1957 { 1958 vassert(s390_host_has_ldisp || dh2 == 0); 1959 1960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1961 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2); 1962 1963 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2); 1964 } 1965 1966 1967 static UChar * 1968 s390_emit_CLFI(UChar *p, UChar r1, UInt i2) 1969 { 1970 vassert(s390_host_has_eimm); 1971 1972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1973 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2); 1974 1975 return emit_RIL(p, 0xc20f00000000ULL, r1, i2); 1976 } 1977 1978 1979 static UChar * 1980 s390_emit_CLGFI(UChar *p, UChar r1, UInt i2) 1981 { 1982 vassert(s390_host_has_eimm); 1983 1984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1985 s390_disasm(ENC3(MNM, GPR, UINT), "clgfi", r1, i2); 1986 1987 return emit_RIL(p, 0xc20e00000000ULL, r1, i2); 1988 } 1989 1990 1991 static UChar * 1992 s390_emit_DR(UChar *p, UChar r1, UChar r2) 1993 { 1994 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1995 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2); 1996 1997 return emit_RR(p, 0x1d00, r1, r2); 1998 } 1999 2000 2001 static UChar * 2002 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2003 { 2004 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2005 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2); 2006 2007 return emit_RX(p, 0x5d000000, r1, x2, b2, d2); 2008 } 2009 2010 2011 static UChar * 2012 s390_emit_DLR(UChar *p, UChar r1, UChar r2) 2013 { 2014 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2015 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2); 2016 2017 return emit_RRE(p, 0xb9970000, r1, r2); 2018 } 2019 2020 2021 static UChar * 2022 s390_emit_DLGR(UChar *p, UChar r1, UChar r2) 2023 { 2024 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2025 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2); 2026 2027 return emit_RRE(p, 0xb9870000, r1, r2); 2028 } 2029 2030 2031 static UChar * 2032 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2033 { 2034 vassert(s390_host_has_ldisp || dh2 == 0); 2035 2036 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2037 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2); 2038 2039 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2); 2040 } 2041 2042 2043 static UChar * 2044 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2045 { 2046 vassert(s390_host_has_ldisp || dh2 == 0); 2047 2048 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2049 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2); 2050 2051 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2); 2052 } 2053 2054 2055 static UChar * 2056 s390_emit_DSGR(UChar *p, UChar r1, UChar r2) 2057 { 2058 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2059 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2); 2060 2061 return emit_RRE(p, 0xb90d0000, r1, r2); 2062 } 2063 2064 2065 static UChar * 2066 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2067 { 2068 vassert(s390_host_has_ldisp || dh2 == 0); 2069 2070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2071 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2); 2072 2073 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2); 2074 } 2075 2076 2077 static UChar * 2078 s390_emit_XR(UChar *p, UChar r1, UChar r2) 2079 { 2080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2081 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2); 2082 2083 return emit_RR(p, 0x1700, r1, r2); 2084 } 2085 2086 2087 static UChar * 2088 s390_emit_XGR(UChar *p, UChar r1, UChar r2) 2089 { 2090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2091 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2); 2092 2093 return emit_RRE(p, 0xb9820000, r1, r2); 2094 } 2095 2096 2097 static UChar * 2098 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2099 { 2100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2101 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2); 2102 2103 return emit_RX(p, 0x57000000, r1, x2, b2, d2); 2104 } 2105 2106 2107 static UChar * 2108 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2109 { 2110 vassert(s390_host_has_ldisp); 2111 2112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2113 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2); 2114 2115 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2); 2116 } 2117 2118 2119 static UChar * 2120 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2121 { 2122 vassert(s390_host_has_ldisp || dh2 == 0); 2123 2124 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2125 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2); 2126 2127 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2); 2128 } 2129 2130 2131 static UChar * 2132 s390_emit_XIHF(UChar *p, UChar r1, UInt i2) 2133 { 2134 vassert(s390_host_has_eimm); 2135 2136 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2137 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2); 2138 2139 return emit_RIL(p, 0xc00600000000ULL, r1, i2); 2140 } 2141 2142 2143 static UChar * 2144 s390_emit_XILF(UChar *p, UChar r1, UInt i2) 2145 { 2146 vassert(s390_host_has_eimm); 2147 2148 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2149 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2); 2150 2151 return emit_RIL(p, 0xc00700000000ULL, r1, i2); 2152 } 2153 2154 2155 static UChar * 2156 s390_emit_XC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2) 2157 { 2158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2159 s390_disasm(ENC3(MNM, UDLB, UDXB), "xc", d1, l, b1, d2, 0, b2); 2160 2161 return emit_SSa(p, 0xd70000000000ULL, l, b1, d1, b2, d2); 2162 } 2163 2164 2165 static UChar * 2166 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2) 2167 { 2168 vassert(s390_host_has_eimm); 2169 2170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2171 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2); 2172 2173 return emit_RRE(p, 0xb9830000, r1, r2); 2174 } 2175 2176 2177 static UChar * 2178 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2179 { 2180 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2181 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2); 2182 2183 return emit_RX(p, 0x43000000, r1, x2, b2, d2); 2184 } 2185 2186 2187 static UChar * 2188 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2189 { 2190 vassert(s390_host_has_ldisp); 2191 2192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2193 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2); 2194 2195 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2); 2196 } 2197 2198 2199 static UChar * 2200 s390_emit_IIHF(UChar *p, UChar r1, UInt i2) 2201 { 2202 vassert(s390_host_has_eimm); 2203 2204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2205 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2); 2206 2207 return emit_RIL(p, 0xc00800000000ULL, r1, i2); 2208 } 2209 2210 2211 static UChar * 2212 s390_emit_IIHH(UChar *p, UChar r1, UShort i2) 2213 { 2214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2215 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2); 2216 2217 return emit_RI(p, 0xa5000000, r1, i2); 2218 } 2219 2220 2221 static UChar * 2222 s390_emit_IIHL(UChar *p, UChar r1, UShort i2) 2223 { 2224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2225 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2); 2226 2227 return emit_RI(p, 0xa5010000, r1, i2); 2228 } 2229 2230 2231 static UChar * 2232 s390_emit_IILF(UChar *p, UChar r1, UInt i2) 2233 { 2234 vassert(s390_host_has_eimm); 2235 2236 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2237 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2); 2238 2239 return emit_RIL(p, 0xc00900000000ULL, r1, i2); 2240 } 2241 2242 2243 static UChar * 2244 s390_emit_IILH(UChar *p, UChar r1, UShort i2) 2245 { 2246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2247 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2); 2248 2249 return emit_RI(p, 0xa5020000, r1, i2); 2250 } 2251 2252 2253 static UChar * 2254 s390_emit_IILL(UChar *p, UChar r1, UShort i2) 2255 { 2256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2257 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2); 2258 2259 return emit_RI(p, 0xa5030000, r1, i2); 2260 } 2261 2262 2263 static UChar * 2264 s390_emit_IPM(UChar *p, UChar r1, UChar r2) 2265 { 2266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2267 s390_disasm(ENC2(MNM, GPR), "ipm", r1); 2268 2269 return emit_RRE(p, 0xb2220000, r1, r2); 2270 } 2271 2272 2273 static UChar * 2274 s390_emit_LR(UChar *p, UChar r1, UChar r2) 2275 { 2276 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2277 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2); 2278 2279 return emit_RR(p, 0x1800, r1, r2); 2280 } 2281 2282 2283 static UChar * 2284 s390_emit_LGR(UChar *p, UChar r1, UChar r2) 2285 { 2286 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2287 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2); 2288 2289 return emit_RRE(p, 0xb9040000, r1, r2); 2290 } 2291 2292 2293 static UChar * 2294 s390_emit_LGFR(UChar *p, UChar r1, UChar r2) 2295 { 2296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2297 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2); 2298 2299 return emit_RRE(p, 0xb9140000, r1, r2); 2300 } 2301 2302 2303 static UChar * 2304 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2305 { 2306 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2307 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2); 2308 2309 return emit_RX(p, 0x58000000, r1, x2, b2, d2); 2310 } 2311 2312 2313 static UChar * 2314 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2315 { 2316 vassert(s390_host_has_ldisp); 2317 2318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2319 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2); 2320 2321 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2); 2322 } 2323 2324 2325 static UChar * 2326 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2327 { 2328 vassert(s390_host_has_ldisp || dh2 == 0); 2329 2330 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2331 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2); 2332 2333 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2); 2334 } 2335 2336 2337 static UChar * 2338 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2339 { 2340 vassert(s390_host_has_ldisp || dh2 == 0); 2341 2342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2343 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2); 2344 2345 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2); 2346 } 2347 2348 2349 static UChar * 2350 s390_emit_LGFI(UChar *p, UChar r1, UInt i2) 2351 { 2352 vassert(s390_host_has_eimm); 2353 2354 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2355 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2); 2356 2357 return emit_RIL(p, 0xc00100000000ULL, r1, i2); 2358 } 2359 2360 2361 static UChar * 2362 s390_emit_LTR(UChar *p, UChar r1, UChar r2) 2363 { 2364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2365 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2); 2366 2367 return emit_RR(p, 0x1200, r1, r2); 2368 } 2369 2370 2371 static UChar * 2372 s390_emit_LTGR(UChar *p, UChar r1, UChar r2) 2373 { 2374 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2375 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2); 2376 2377 return emit_RRE(p, 0xb9020000, r1, r2); 2378 } 2379 2380 2381 static UChar * 2382 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2383 { 2384 vassert(s390_host_has_eimm); 2385 2386 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2387 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2); 2388 2389 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2); 2390 } 2391 2392 2393 static UChar * 2394 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2395 { 2396 vassert(s390_host_has_eimm); 2397 2398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2399 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2); 2400 2401 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2); 2402 } 2403 2404 2405 static UChar * 2406 s390_emit_LBR(UChar *p, UChar r1, UChar r2) 2407 { 2408 vassert(s390_host_has_eimm); 2409 2410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2411 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2); 2412 2413 return emit_RRE(p, 0xb9260000, r1, r2); 2414 } 2415 2416 2417 static UChar * 2418 s390_emit_LGBR(UChar *p, UChar r1, UChar r2) 2419 { 2420 vassert(s390_host_has_eimm); 2421 2422 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2423 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2); 2424 2425 return emit_RRE(p, 0xb9060000, r1, r2); 2426 } 2427 2428 2429 static UChar * 2430 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2431 { 2432 vassert(s390_host_has_ldisp); 2433 2434 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2435 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2); 2436 2437 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2); 2438 } 2439 2440 2441 static UChar * 2442 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2443 { 2444 vassert(s390_host_has_ldisp); 2445 2446 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2447 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2); 2448 2449 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2); 2450 } 2451 2452 2453 static UChar * 2454 s390_emit_LCR(UChar *p, UChar r1, UChar r2) 2455 { 2456 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2457 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2); 2458 2459 return emit_RR(p, 0x1300, r1, r2); 2460 } 2461 2462 2463 static UChar * 2464 s390_emit_LCGR(UChar *p, UChar r1, UChar r2) 2465 { 2466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2467 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2); 2468 2469 return emit_RRE(p, 0xb9030000, r1, r2); 2470 } 2471 2472 2473 static UChar * 2474 s390_emit_LHR(UChar *p, UChar r1, UChar r2) 2475 { 2476 vassert(s390_host_has_eimm); 2477 2478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2479 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2); 2480 2481 return emit_RRE(p, 0xb9270000, r1, r2); 2482 } 2483 2484 2485 static UChar * 2486 s390_emit_LGHR(UChar *p, UChar r1, UChar r2) 2487 { 2488 vassert(s390_host_has_eimm); 2489 2490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2491 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2); 2492 2493 return emit_RRE(p, 0xb9070000, r1, r2); 2494 } 2495 2496 2497 static UChar * 2498 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2499 { 2500 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2501 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2); 2502 2503 return emit_RX(p, 0x48000000, r1, x2, b2, d2); 2504 } 2505 2506 2507 static UChar * 2508 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2509 { 2510 vassert(s390_host_has_ldisp); 2511 2512 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2513 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2); 2514 2515 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2); 2516 } 2517 2518 2519 static UChar * 2520 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2521 { 2522 vassert(s390_host_has_ldisp || dh2 == 0); 2523 2524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2525 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2); 2526 2527 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2); 2528 } 2529 2530 2531 static UChar * 2532 s390_emit_LHI(UChar *p, UChar r1, UShort i2) 2533 { 2534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2535 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2); 2536 2537 return emit_RI(p, 0xa7080000, r1, i2); 2538 } 2539 2540 2541 static UChar * 2542 s390_emit_LGHI(UChar *p, UChar r1, UShort i2) 2543 { 2544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2545 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2); 2546 2547 return emit_RI(p, 0xa7090000, r1, i2); 2548 } 2549 2550 2551 static UChar * 2552 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2) 2553 { 2554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2555 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2); 2556 2557 return emit_RRE(p, 0xb9160000, r1, r2); 2558 } 2559 2560 2561 static UChar * 2562 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2563 { 2564 vassert(s390_host_has_ldisp || dh2 == 0); 2565 2566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2567 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2); 2568 2569 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2); 2570 } 2571 2572 2573 static UChar * 2574 s390_emit_LLCR(UChar *p, UChar r1, UChar r2) 2575 { 2576 vassert(s390_host_has_eimm); 2577 2578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2579 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2); 2580 2581 return emit_RRE(p, 0xb9940000, r1, r2); 2582 } 2583 2584 2585 static UChar * 2586 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2) 2587 { 2588 vassert(s390_host_has_eimm); 2589 2590 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2591 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2); 2592 2593 return emit_RRE(p, 0xb9840000, r1, r2); 2594 } 2595 2596 2597 static UChar * 2598 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2599 { 2600 vassert(s390_host_has_eimm); 2601 2602 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2603 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2); 2604 2605 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2); 2606 } 2607 2608 2609 static UChar * 2610 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2611 { 2612 vassert(s390_host_has_ldisp || dh2 == 0); 2613 2614 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2615 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2); 2616 2617 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2); 2618 } 2619 2620 2621 static UChar * 2622 s390_emit_LLHR(UChar *p, UChar r1, UChar r2) 2623 { 2624 vassert(s390_host_has_eimm); 2625 2626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2627 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2); 2628 2629 return emit_RRE(p, 0xb9950000, r1, r2); 2630 } 2631 2632 2633 static UChar * 2634 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2) 2635 { 2636 vassert(s390_host_has_eimm); 2637 2638 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2639 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2); 2640 2641 return emit_RRE(p, 0xb9850000, r1, r2); 2642 } 2643 2644 2645 static UChar * 2646 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2647 { 2648 vassert(s390_host_has_eimm); 2649 2650 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2651 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2); 2652 2653 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2); 2654 } 2655 2656 2657 static UChar * 2658 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2659 { 2660 vassert(s390_host_has_ldisp || dh2 == 0); 2661 2662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2663 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2); 2664 2665 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2); 2666 } 2667 2668 2669 static UChar * 2670 s390_emit_LLILF(UChar *p, UChar r1, UInt i2) 2671 { 2672 vassert(s390_host_has_eimm); 2673 2674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2675 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2); 2676 2677 return emit_RIL(p, 0xc00f00000000ULL, r1, i2); 2678 } 2679 2680 2681 static UChar * 2682 s390_emit_LLILH(UChar *p, UChar r1, UShort i2) 2683 { 2684 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2685 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2); 2686 2687 return emit_RI(p, 0xa50e0000, r1, i2); 2688 } 2689 2690 2691 static UChar * 2692 s390_emit_LLILL(UChar *p, UChar r1, UShort i2) 2693 { 2694 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2695 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2); 2696 2697 return emit_RI(p, 0xa50f0000, r1, i2); 2698 } 2699 2700 2701 static UChar * 2702 s390_emit_MR(UChar *p, UChar r1, UChar r2) 2703 { 2704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2705 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2); 2706 2707 return emit_RR(p, 0x1c00, r1, r2); 2708 } 2709 2710 2711 static UChar * 2712 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2713 { 2714 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2715 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2); 2716 2717 return emit_RX(p, 0x5c000000, r1, x2, b2, d2); 2718 } 2719 2720 2721 static UChar * 2722 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2723 { 2724 vassert(s390_host_has_gie); 2725 2726 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2727 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2); 2728 2729 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2); 2730 } 2731 2732 2733 static UChar * 2734 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2735 { 2736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2737 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2); 2738 2739 return emit_RX(p, 0x4c000000, r1, x2, b2, d2); 2740 } 2741 2742 2743 static UChar * 2744 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2745 { 2746 vassert(s390_host_has_gie); 2747 2748 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2749 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2); 2750 2751 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2); 2752 } 2753 2754 2755 static UChar * 2756 s390_emit_MHI(UChar *p, UChar r1, UShort i2) 2757 { 2758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2759 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2); 2760 2761 return emit_RI(p, 0xa70c0000, r1, i2); 2762 } 2763 2764 2765 static UChar * 2766 s390_emit_MLR(UChar *p, UChar r1, UChar r2) 2767 { 2768 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2769 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2); 2770 2771 return emit_RRE(p, 0xb9960000, r1, r2); 2772 } 2773 2774 2775 static UChar * 2776 s390_emit_MLGR(UChar *p, UChar r1, UChar r2) 2777 { 2778 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2779 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2); 2780 2781 return emit_RRE(p, 0xb9860000, r1, r2); 2782 } 2783 2784 2785 static UChar * 2786 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2787 { 2788 vassert(s390_host_has_ldisp || dh2 == 0); 2789 2790 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2791 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2); 2792 2793 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2); 2794 } 2795 2796 2797 static UChar * 2798 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2799 { 2800 vassert(s390_host_has_ldisp || dh2 == 0); 2801 2802 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2803 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2); 2804 2805 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2); 2806 } 2807 2808 2809 static UChar * 2810 s390_emit_MSR(UChar *p, UChar r1, UChar r2) 2811 { 2812 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2813 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2); 2814 2815 return emit_RRE(p, 0xb2520000, r1, r2); 2816 } 2817 2818 2819 static UChar * 2820 s390_emit_MSGR(UChar *p, UChar r1, UChar r2) 2821 { 2822 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2823 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2); 2824 2825 return emit_RRE(p, 0xb90c0000, r1, r2); 2826 } 2827 2828 2829 static UChar * 2830 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2831 { 2832 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2833 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2); 2834 2835 return emit_RX(p, 0x71000000, r1, x2, b2, d2); 2836 } 2837 2838 2839 static UChar * 2840 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2841 { 2842 vassert(s390_host_has_ldisp); 2843 2844 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2845 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2); 2846 2847 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2); 2848 } 2849 2850 2851 static UChar * 2852 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2853 { 2854 vassert(s390_host_has_ldisp || dh2 == 0); 2855 2856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2857 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2); 2858 2859 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2); 2860 } 2861 2862 2863 static UChar * 2864 s390_emit_MSFI(UChar *p, UChar r1, UInt i2) 2865 { 2866 vassert(s390_host_has_gie); 2867 2868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2869 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2); 2870 2871 return emit_RIL(p, 0xc20100000000ULL, r1, i2); 2872 } 2873 2874 2875 static UChar * 2876 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2) 2877 { 2878 vassert(s390_host_has_gie); 2879 2880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2881 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2); 2882 2883 return emit_RIL(p, 0xc20000000000ULL, r1, i2); 2884 } 2885 2886 2887 static UChar * 2888 s390_emit_MVC(UChar *p, UInt l, UChar b1, UShort d1, UChar b2, UShort d2) 2889 { 2890 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2891 s390_disasm(ENC3(MNM, UDLB, UDXB), "mvc", d1, l, b1, d2, 0, b2); 2892 2893 return emit_SSa(p, 0xd20000000000ULL, l, b1, d1, b2, d2); 2894 } 2895 2896 2897 static UChar * 2898 s390_emit_MVI(UChar *p, UChar i2, UChar b1, UShort d1) 2899 { 2900 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2901 s390_disasm(ENC3(MNM, UDXB, INT), "mvi", d1, 0, b1, i2); 2902 2903 return emit_SI(p, 0x92000000, i2, b1, d1); 2904 } 2905 2906 2907 static UChar * 2908 s390_emit_MVHHI(UChar *p, UChar b1, UShort d1, UShort i2) 2909 { 2910 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2911 s390_disasm(ENC3(MNM, UDXB, INT), "mvhhi", d1, 0, b1, i2); 2912 2913 return emit_SIL(p, 0xe54400000000ULL, b1, d1, i2); 2914 } 2915 2916 2917 static UChar * 2918 s390_emit_MVHI(UChar *p, UChar b1, UShort d1, UShort i2) 2919 { 2920 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2921 s390_disasm(ENC3(MNM, UDXB, INT), "mvhi", d1, 0, b1, i2); 2922 2923 return emit_SIL(p, 0xe54c00000000ULL, b1, d1, i2); 2924 } 2925 2926 2927 static UChar * 2928 s390_emit_MVGHI(UChar *p, UChar b1, UShort d1, UShort i2) 2929 { 2930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2931 s390_disasm(ENC3(MNM, UDXB, INT), "mvghi", d1, 0, b1, i2); 2932 2933 return emit_SIL(p, 0xe54800000000ULL, b1, d1, i2); 2934 } 2935 2936 2937 static UChar * 2938 s390_emit_OR(UChar *p, UChar r1, UChar r2) 2939 { 2940 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2941 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2); 2942 2943 return emit_RR(p, 0x1600, r1, r2); 2944 } 2945 2946 2947 static UChar * 2948 s390_emit_OGR(UChar *p, UChar r1, UChar r2) 2949 { 2950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2951 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2); 2952 2953 return emit_RRE(p, 0xb9810000, r1, r2); 2954 } 2955 2956 2957 static UChar * 2958 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2959 { 2960 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2961 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2); 2962 2963 return emit_RX(p, 0x56000000, r1, x2, b2, d2); 2964 } 2965 2966 2967 static UChar * 2968 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2969 { 2970 vassert(s390_host_has_ldisp); 2971 2972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2973 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2); 2974 2975 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2); 2976 } 2977 2978 2979 static UChar * 2980 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2981 { 2982 vassert(s390_host_has_ldisp || dh2 == 0); 2983 2984 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2985 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2); 2986 2987 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2); 2988 } 2989 2990 2991 static UChar * 2992 s390_emit_OIHF(UChar *p, UChar r1, UInt i2) 2993 { 2994 vassert(s390_host_has_eimm); 2995 2996 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2997 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2); 2998 2999 return emit_RIL(p, 0xc00c00000000ULL, r1, i2); 3000 } 3001 3002 3003 static UChar * 3004 s390_emit_OILF(UChar *p, UChar r1, UInt i2) 3005 { 3006 vassert(s390_host_has_eimm); 3007 3008 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3009 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2); 3010 3011 return emit_RIL(p, 0xc00d00000000ULL, r1, i2); 3012 } 3013 3014 3015 static UChar * 3016 s390_emit_OILL(UChar *p, UChar r1, UShort i2) 3017 { 3018 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3019 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2); 3020 3021 return emit_RI(p, 0xa50b0000, r1, i2); 3022 } 3023 3024 3025 static UChar * 3026 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2) 3027 { 3028 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3029 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2); 3030 3031 return emit_RS(p, 0x89000000, r1, 0, b2, d2); 3032 } 3033 3034 3035 static UChar * 3036 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 3037 { 3038 vassert(s390_host_has_ldisp || dh2 == 0); 3039 3040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3041 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2); 3042 3043 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2); 3044 } 3045 3046 3047 static UChar * 3048 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2) 3049 { 3050 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3051 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2); 3052 3053 return emit_RS(p, 0x8a000000, r1, 0, b2, d2); 3054 } 3055 3056 3057 static UChar * 3058 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 3059 { 3060 vassert(s390_host_has_ldisp || dh2 == 0); 3061 3062 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3063 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2); 3064 3065 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2); 3066 } 3067 3068 3069 static UChar * 3070 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2) 3071 { 3072 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3073 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2); 3074 3075 return emit_RS(p, 0x88000000, r1, 0, b2, d2); 3076 } 3077 3078 3079 static UChar * 3080 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 3081 { 3082 vassert(s390_host_has_ldisp || dh2 == 0); 3083 3084 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3085 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2); 3086 3087 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2); 3088 } 3089 3090 3091 static UChar * 3092 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3093 { 3094 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3095 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2); 3096 3097 return emit_RX(p, 0x50000000, r1, x2, b2, d2); 3098 } 3099 3100 3101 static UChar * 3102 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3103 { 3104 vassert(s390_host_has_ldisp); 3105 3106 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3107 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2); 3108 3109 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2); 3110 } 3111 3112 3113 static UChar * 3114 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3115 { 3116 vassert(s390_host_has_ldisp || dh2 == 0); 3117 3118 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3119 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2); 3120 3121 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2); 3122 } 3123 3124 3125 static UChar * 3126 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3127 { 3128 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3129 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2); 3130 3131 return emit_RX(p, 0x42000000, r1, x2, b2, d2); 3132 } 3133 3134 3135 static UChar * 3136 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3137 { 3138 vassert(s390_host_has_ldisp); 3139 3140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3141 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2); 3142 3143 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2); 3144 } 3145 3146 3147 static UChar * 3148 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3149 { 3150 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3151 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2); 3152 3153 return emit_RX(p, 0x40000000, r1, x2, b2, d2); 3154 } 3155 3156 3157 static UChar * 3158 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3159 { 3160 vassert(s390_host_has_ldisp); 3161 3162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3163 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2); 3164 3165 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2); 3166 } 3167 3168 3169 static UChar * 3170 s390_emit_SR(UChar *p, UChar r1, UChar r2) 3171 { 3172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3173 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2); 3174 3175 return emit_RR(p, 0x1b00, r1, r2); 3176 } 3177 3178 3179 static UChar * 3180 s390_emit_SGR(UChar *p, UChar r1, UChar r2) 3181 { 3182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3183 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2); 3184 3185 return emit_RRE(p, 0xb9090000, r1, r2); 3186 } 3187 3188 3189 static UChar * 3190 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3191 { 3192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3193 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2); 3194 3195 return emit_RX(p, 0x5b000000, r1, x2, b2, d2); 3196 } 3197 3198 3199 static UChar * 3200 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3201 { 3202 vassert(s390_host_has_ldisp); 3203 3204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3205 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2); 3206 3207 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2); 3208 } 3209 3210 3211 static UChar * 3212 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3213 { 3214 vassert(s390_host_has_ldisp || dh2 == 0); 3215 3216 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3217 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2); 3218 3219 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2); 3220 } 3221 3222 3223 static UChar * 3224 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3225 { 3226 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3227 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2); 3228 3229 return emit_RX(p, 0x4b000000, r1, x2, b2, d2); 3230 } 3231 3232 3233 static UChar * 3234 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3235 { 3236 vassert(s390_host_has_ldisp); 3237 3238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3239 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2); 3240 3241 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2); 3242 } 3243 3244 3245 static UChar * 3246 s390_emit_SLFI(UChar *p, UChar r1, UInt i2) 3247 { 3248 vassert(s390_host_has_eimm); 3249 3250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3251 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2); 3252 3253 return emit_RIL(p, 0xc20500000000ULL, r1, i2); 3254 } 3255 3256 3257 static UChar * 3258 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2) 3259 { 3260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3261 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2); 3262 3263 return emit_RIL(p, 0xc20400000000ULL, r1, i2); 3264 } 3265 3266 3267 static UChar * 3268 s390_emit_LDR(UChar *p, UChar r1, UChar r2) 3269 { 3270 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3271 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2); 3272 3273 return emit_RR(p, 0x2800, r1, r2); 3274 } 3275 3276 3277 static UChar * 3278 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3279 { 3280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3281 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2); 3282 3283 return emit_RX(p, 0x78000000, r1, x2, b2, d2); 3284 } 3285 3286 3287 static UChar * 3288 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3289 { 3290 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3291 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2); 3292 3293 return emit_RX(p, 0x68000000, r1, x2, b2, d2); 3294 } 3295 3296 3297 static UChar * 3298 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3299 { 3300 vassert(s390_host_has_ldisp); 3301 3302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3303 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2); 3304 3305 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2); 3306 } 3307 3308 3309 static UChar * 3310 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3311 { 3312 vassert(s390_host_has_ldisp); 3313 3314 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3315 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2); 3316 3317 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2); 3318 } 3319 3320 3321 static UChar * 3322 s390_emit_LFPC(UChar *p, UChar b2, UShort d2) 3323 { 3324 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3325 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2); 3326 3327 return emit_S(p, 0xb29d0000, b2, d2); 3328 } 3329 3330 3331 static UChar * 3332 s390_emit_LDGR(UChar *p, UChar r1, UChar r2) 3333 { 3334 vassert(s390_host_has_fgx); 3335 3336 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3337 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2); 3338 3339 return emit_RRE(p, 0xb3c10000, r1, r2); 3340 } 3341 3342 3343 static UChar * 3344 s390_emit_LGDR(UChar *p, UChar r1, UChar r2) 3345 { 3346 vassert(s390_host_has_fgx); 3347 3348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3349 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2); 3350 3351 return emit_RRE(p, 0xb3cd0000, r1, r2); 3352 } 3353 3354 3355 static UChar * 3356 s390_emit_LZER(UChar *p, UChar r1, UChar r2) 3357 { 3358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3359 s390_disasm(ENC2(MNM, FPR), "lzer", r1); 3360 3361 return emit_RRE(p, 0xb3740000, r1, r2); 3362 } 3363 3364 3365 static UChar * 3366 s390_emit_LZDR(UChar *p, UChar r1, UChar r2) 3367 { 3368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3369 s390_disasm(ENC2(MNM, FPR), "lzdr", r1); 3370 3371 return emit_RRE(p, 0xb3750000, r1, r2); 3372 } 3373 3374 3375 static UChar * 3376 s390_emit_SFPC(UChar *p, UChar r1) 3377 { 3378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3379 s390_disasm(ENC2(MNM, GPR), "sfpc", r1); 3380 3381 return emit_RRE(p, 0xb3840000, r1, 0); 3382 } 3383 3384 3385 static UChar * 3386 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3387 { 3388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3389 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2); 3390 3391 return emit_RX(p, 0x70000000, r1, x2, b2, d2); 3392 } 3393 3394 3395 static UChar * 3396 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 3397 { 3398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3399 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2); 3400 3401 return emit_RX(p, 0x60000000, r1, x2, b2, d2); 3402 } 3403 3404 3405 static UChar * 3406 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3407 { 3408 vassert(s390_host_has_ldisp); 3409 3410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3411 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2); 3412 3413 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2); 3414 } 3415 3416 3417 static UChar * 3418 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3419 { 3420 vassert(s390_host_has_ldisp); 3421 3422 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3423 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2); 3424 3425 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2); 3426 } 3427 3428 3429 static UChar * 3430 s390_emit_STFPC(UChar *p, UChar b2, UShort d2) 3431 { 3432 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3433 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2); 3434 3435 return emit_S(p, 0xb29c0000, b2, d2); 3436 } 3437 3438 3439 static UChar * 3440 s390_emit_AEBR(UChar *p, UChar r1, UChar r2) 3441 { 3442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3443 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2); 3444 3445 return emit_RRE(p, 0xb30a0000, r1, r2); 3446 } 3447 3448 3449 static UChar * 3450 s390_emit_ADBR(UChar *p, UChar r1, UChar r2) 3451 { 3452 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3453 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2); 3454 3455 return emit_RRE(p, 0xb31a0000, r1, r2); 3456 } 3457 3458 3459 static UChar * 3460 s390_emit_AXBR(UChar *p, UChar r1, UChar r2) 3461 { 3462 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3463 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2); 3464 3465 return emit_RRE(p, 0xb34a0000, r1, r2); 3466 } 3467 3468 3469 static UChar * 3470 s390_emit_CEBR(UChar *p, UChar r1, UChar r2) 3471 { 3472 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3473 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2); 3474 3475 return emit_RRE(p, 0xb3090000, r1, r2); 3476 } 3477 3478 3479 static UChar * 3480 s390_emit_CDBR(UChar *p, UChar r1, UChar r2) 3481 { 3482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3483 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2); 3484 3485 return emit_RRE(p, 0xb3190000, r1, r2); 3486 } 3487 3488 3489 static UChar * 3490 s390_emit_CXBR(UChar *p, UChar r1, UChar r2) 3491 { 3492 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3493 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2); 3494 3495 return emit_RRE(p, 0xb3490000, r1, r2); 3496 } 3497 3498 3499 static UChar * 3500 s390_emit_CEFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3501 { 3502 vassert(m4 == 0); 3503 vassert(m3 == 0 || s390_host_has_fpext); 3504 3505 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3506 if (m3 == 0) 3507 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2); 3508 else 3509 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3510 "cefbra", r1, m3, r2, m4); 3511 } 3512 3513 return emit_RRF2(p, 0xb3940000, m3, m4, r1, r2); 3514 } 3515 3516 3517 static UChar * 3518 s390_emit_CDFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3519 { 3520 vassert(m4 == 0); 3521 vassert(m3 == 0 || s390_host_has_fpext); 3522 3523 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3524 if (m3 == 0) 3525 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2); 3526 else 3527 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3528 "cdfbra", r1, m3, r2, m4); 3529 } 3530 3531 return emit_RRF2(p, 0xb3950000, m3, m4, r1, r2); 3532 } 3533 3534 3535 static UChar * 3536 s390_emit_CXFBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3537 { 3538 vassert(m4 == 0); 3539 vassert(m3 == 0 || s390_host_has_fpext); 3540 3541 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3542 if (m3 == 0) 3543 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2); 3544 else 3545 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3546 "cxfbra", r1, m3, r2, m4); 3547 } 3548 3549 return emit_RRF2(p, 0xb3960000, m3, m4, r1, r2); 3550 } 3551 3552 3553 static UChar * 3554 s390_emit_CEGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3555 { 3556 vassert(m4 == 0); 3557 vassert(m3 == 0 || s390_host_has_fpext); 3558 3559 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3560 if (m3 == 0) 3561 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2); 3562 else 3563 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3564 "cegbra", r1, m3, r2, m4); 3565 } 3566 3567 return emit_RRF2(p, 0xb3a40000, m3, m4, r1, r2); 3568 } 3569 3570 3571 static UChar * 3572 s390_emit_CDGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3573 { 3574 vassert(m4 == 0); 3575 vassert(m3 == 0 || s390_host_has_fpext); 3576 3577 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3578 if (m3 == 0) 3579 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2); 3580 else 3581 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3582 "cdgbra", r1, m3, r2, m4); 3583 } 3584 3585 return emit_RRF2(p, 0xb3a50000, m3, m4, r1, r2); 3586 } 3587 3588 3589 static UChar * 3590 s390_emit_CXGBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3591 { 3592 vassert(m4 == 0); 3593 vassert(m3 == 0 || s390_host_has_fpext); 3594 3595 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3596 if (m3 == 0) 3597 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2); 3598 else 3599 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), 3600 "cxgbra", r1, m3, r2, m4); 3601 } 3602 3603 return emit_RRF2(p, 0xb3a60000, m3, m4, r1, r2); 3604 } 3605 3606 3607 static UChar * 3608 s390_emit_CELFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3609 { 3610 vassert(m4 == 0); 3611 vassert(s390_host_has_fpext); 3612 3613 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3614 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celfbr", r1, m3, r2, m4); 3615 3616 return emit_RRF2(p, 0xb3900000, m3, m4, r1, r2); 3617 } 3618 3619 3620 static UChar * 3621 s390_emit_CDLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3622 { 3623 vassert(m4 == 0); 3624 vassert(s390_host_has_fpext); 3625 3626 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3627 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlfbr", r1, m3, r2, m4); 3628 3629 return emit_RRF2(p, 0xb3910000, m3, m4, r1, r2); 3630 } 3631 3632 3633 static UChar * 3634 s390_emit_CXLFBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3635 { 3636 vassert(m4 == 0); 3637 vassert(s390_host_has_fpext); 3638 3639 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3640 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlfbr", r1, m3, r2, m4); 3641 3642 return emit_RRF2(p, 0xb3920000, m3, m4, r1, r2); 3643 } 3644 3645 3646 static UChar * 3647 s390_emit_CELGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3648 { 3649 vassert(m4 == 0); 3650 vassert(s390_host_has_fpext); 3651 3652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3653 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "celgbr", r1, m3, r2, m4); 3654 3655 return emit_RRF2(p, 0xb3a00000, m3, m4, r1, r2); 3656 } 3657 3658 3659 static UChar * 3660 s390_emit_CDLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3661 { 3662 vassert(m4 == 0); 3663 vassert(s390_host_has_fpext); 3664 3665 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3666 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgbr", r1, m3, r2, m4); 3667 3668 return emit_RRF2(p, 0xb3a10000, m3, m4, r1, r2); 3669 } 3670 3671 3672 static UChar * 3673 s390_emit_CXLGBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3674 { 3675 vassert(m4 == 0); 3676 vassert(s390_host_has_fpext); 3677 3678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3679 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgbr", r1, m3, r2, m4); 3680 3681 return emit_RRF2(p, 0xb3a20000, m3, m4, r1, r2); 3682 } 3683 3684 3685 static UChar * 3686 s390_emit_CLFEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3687 { 3688 vassert(m4 == 0); 3689 vassert(s390_host_has_fpext); 3690 3691 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3692 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfebr", r1, m3, r2, m4); 3693 3694 return emit_RRF2(p, 0xb39c0000, m3, m4, r1, r2); 3695 } 3696 3697 3698 static UChar * 3699 s390_emit_CLFDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3700 { 3701 vassert(m4 == 0); 3702 vassert(s390_host_has_fpext); 3703 3704 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3705 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdbr", r1, m3, r2, m4); 3706 3707 return emit_RRF2(p, 0xb39d0000, m3, m4, r1, r2); 3708 } 3709 3710 3711 static UChar * 3712 s390_emit_CLFXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3713 { 3714 vassert(m4 == 0); 3715 vassert(s390_host_has_fpext); 3716 3717 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3718 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxbr", r1, m3, r2, m4); 3719 3720 return emit_RRF2(p, 0xb39e0000, m3, m4, r1, r2); 3721 } 3722 3723 3724 static UChar * 3725 s390_emit_CLGEBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3726 { 3727 vassert(m4 == 0); 3728 vassert(s390_host_has_fpext); 3729 3730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3731 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgebr", r1, m3, r2, m4); 3732 3733 return emit_RRF2(p, 0xb3ac0000, m3, m4, r1, r2); 3734 } 3735 3736 3737 static UChar * 3738 s390_emit_CLGDBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3739 { 3740 vassert(m4 == 0); 3741 vassert(s390_host_has_fpext); 3742 3743 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3744 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdbr", r1, m3, r2, m4); 3745 3746 return emit_RRF2(p, 0xb3ad0000, m3, m4, r1, r2); 3747 } 3748 3749 3750 static UChar * 3751 s390_emit_CLGXBR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3752 { 3753 vassert(m4 == 0); 3754 vassert(s390_host_has_fpext); 3755 3756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3757 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxbr", r1, m3, r2, m4); 3758 3759 return emit_RRF2(p, 0xb3ae0000, m3, m4, r1, r2); 3760 } 3761 3762 3763 static UChar * 3764 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2) 3765 { 3766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3767 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2); 3768 3769 return emit_RRF3(p, 0xb3980000, r3, r1, r2); 3770 } 3771 3772 3773 static UChar * 3774 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2) 3775 { 3776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3777 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2); 3778 3779 return emit_RRF3(p, 0xb3990000, r3, r1, r2); 3780 } 3781 3782 3783 static UChar * 3784 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2) 3785 { 3786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3787 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2); 3788 3789 return emit_RRF3(p, 0xb39a0000, r3, r1, r2); 3790 } 3791 3792 3793 static UChar * 3794 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2) 3795 { 3796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3797 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2); 3798 3799 return emit_RRF3(p, 0xb3a80000, r3, r1, r2); 3800 } 3801 3802 3803 static UChar * 3804 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2) 3805 { 3806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3807 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2); 3808 3809 return emit_RRF3(p, 0xb3a90000, r3, r1, r2); 3810 } 3811 3812 3813 static UChar * 3814 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2) 3815 { 3816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3817 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2); 3818 3819 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2); 3820 } 3821 3822 3823 static UChar * 3824 s390_emit_DEBR(UChar *p, UChar r1, UChar r2) 3825 { 3826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3827 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2); 3828 3829 return emit_RRE(p, 0xb30d0000, r1, r2); 3830 } 3831 3832 3833 static UChar * 3834 s390_emit_DDBR(UChar *p, UChar r1, UChar r2) 3835 { 3836 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3837 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2); 3838 3839 return emit_RRE(p, 0xb31d0000, r1, r2); 3840 } 3841 3842 3843 static UChar * 3844 s390_emit_DXBR(UChar *p, UChar r1, UChar r2) 3845 { 3846 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3847 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2); 3848 3849 return emit_RRE(p, 0xb34d0000, r1, r2); 3850 } 3851 3852 3853 static UChar * 3854 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2) 3855 { 3856 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3857 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2); 3858 3859 return emit_RRE(p, 0xb3030000, r1, r2); 3860 } 3861 3862 3863 static UChar * 3864 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2) 3865 { 3866 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3867 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2); 3868 3869 return emit_RRE(p, 0xb3130000, r1, r2); 3870 } 3871 3872 3873 static UChar * 3874 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2) 3875 { 3876 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3877 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2); 3878 3879 return emit_RRE(p, 0xb3430000, r1, r2); 3880 } 3881 3882 3883 static UChar * 3884 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2) 3885 { 3886 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3887 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2); 3888 3889 return emit_RRE(p, 0xb3040000, r1, r2); 3890 } 3891 3892 3893 static UChar * 3894 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2) 3895 { 3896 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3897 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2); 3898 3899 return emit_RRE(p, 0xb3050000, r1, r2); 3900 } 3901 3902 3903 static UChar * 3904 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2) 3905 { 3906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3907 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2); 3908 3909 return emit_RRE(p, 0xb3060000, r1, r2); 3910 } 3911 3912 3913 static UChar * 3914 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2) 3915 { 3916 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3917 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2); 3918 3919 return emit_RRE(p, 0xb3010000, r1, r2); 3920 } 3921 3922 3923 static UChar * 3924 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2) 3925 { 3926 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3927 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2); 3928 3929 return emit_RRE(p, 0xb3110000, r1, r2); 3930 } 3931 3932 3933 static UChar * 3934 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2) 3935 { 3936 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3937 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2); 3938 3939 return emit_RRE(p, 0xb3410000, r1, r2); 3940 } 3941 3942 3943 static UChar * 3944 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2) 3945 { 3946 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3947 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2); 3948 3949 return emit_RRE(p, 0xb3000000, r1, r2); 3950 } 3951 3952 3953 static UChar * 3954 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2) 3955 { 3956 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3957 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2); 3958 3959 return emit_RRE(p, 0xb3100000, r1, r2); 3960 } 3961 3962 3963 static UChar * 3964 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2) 3965 { 3966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3967 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2); 3968 3969 return emit_RRE(p, 0xb3400000, r1, r2); 3970 } 3971 3972 3973 static UChar * 3974 s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3975 { 3976 vassert(m4 == 0); 3977 vassert(m3 == 0 || s390_host_has_fpext); 3978 3979 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3980 if (m3 == 0) 3981 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2); 3982 else 3983 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), 3984 "ledbra", r1, m3, r2, m4); 3985 } 3986 3987 return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2); 3988 } 3989 3990 3991 static UChar * 3992 s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 3993 { 3994 vassert(m4 == 0); 3995 vassert(m3 == 0 || s390_host_has_fpext); 3996 3997 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 3998 if (m3 == 0) 3999 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2); 4000 else 4001 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), 4002 "ldxbra", r1, m3, r2, m4); 4003 } 4004 4005 return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2); 4006 } 4007 4008 4009 static UChar * 4010 s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4011 { 4012 vassert(m4 == 0); 4013 vassert(m3 == 0 || s390_host_has_fpext); 4014 4015 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4016 if (m3 == 0) 4017 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2); 4018 else 4019 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), 4020 "lexbra", r1, m3, r2, m4); 4021 } 4022 4023 return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2); 4024 } 4025 4026 4027 static UChar * 4028 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2) 4029 { 4030 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4031 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2); 4032 4033 return emit_RRE(p, 0xb3170000, r1, r2); 4034 } 4035 4036 4037 static UChar * 4038 s390_emit_MDBR(UChar *p, UChar r1, UChar r2) 4039 { 4040 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4041 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2); 4042 4043 return emit_RRE(p, 0xb31c0000, r1, r2); 4044 } 4045 4046 4047 static UChar * 4048 s390_emit_MXBR(UChar *p, UChar r1, UChar r2) 4049 { 4050 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4051 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2); 4052 4053 return emit_RRE(p, 0xb34c0000, r1, r2); 4054 } 4055 4056 4057 static UChar * 4058 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2) 4059 { 4060 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4061 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2); 4062 4063 return emit_RRF(p, 0xb30e0000, r1, r3, r2); 4064 } 4065 4066 4067 static UChar * 4068 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2) 4069 { 4070 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4071 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2); 4072 4073 return emit_RRF(p, 0xb31e0000, r1, r3, r2); 4074 } 4075 4076 4077 static UChar * 4078 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2) 4079 { 4080 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4081 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2); 4082 4083 return emit_RRF(p, 0xb30f0000, r1, r3, r2); 4084 } 4085 4086 4087 static UChar * 4088 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2) 4089 { 4090 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4091 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2); 4092 4093 return emit_RRF(p, 0xb31f0000, r1, r3, r2); 4094 } 4095 4096 4097 static UChar * 4098 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2) 4099 { 4100 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4101 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2); 4102 4103 return emit_RRE(p, 0xb3140000, r1, r2); 4104 } 4105 4106 4107 static UChar * 4108 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2) 4109 { 4110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4111 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2); 4112 4113 return emit_RRE(p, 0xb3150000, r1, r2); 4114 } 4115 4116 4117 static UChar * 4118 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2) 4119 { 4120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4121 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2); 4122 4123 return emit_RRE(p, 0xb3160000, r1, r2); 4124 } 4125 4126 4127 static UChar * 4128 s390_emit_SEBR(UChar *p, UChar r1, UChar r2) 4129 { 4130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4131 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2); 4132 4133 return emit_RRE(p, 0xb30b0000, r1, r2); 4134 } 4135 4136 4137 static UChar * 4138 s390_emit_SDBR(UChar *p, UChar r1, UChar r2) 4139 { 4140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4141 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2); 4142 4143 return emit_RRE(p, 0xb31b0000, r1, r2); 4144 } 4145 4146 4147 static UChar * 4148 s390_emit_SXBR(UChar *p, UChar r1, UChar r2) 4149 { 4150 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4151 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2); 4152 4153 return emit_RRE(p, 0xb34b0000, r1, r2); 4154 } 4155 4156 4157 static UChar * 4158 s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4159 { 4160 vassert(s390_host_has_dfp); 4161 vassert(m4 == 0 || s390_host_has_fpext); 4162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4163 if (m4 == 0) 4164 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "adtr", r1, r2, r3); 4165 else 4166 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "adtra", r1, r2, r3, m4); 4167 } 4168 4169 return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2); 4170 } 4171 4172 4173 static UChar * 4174 s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4175 { 4176 vassert(s390_host_has_dfp); 4177 vassert(m4 == 0 || s390_host_has_fpext); 4178 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4179 if (m4 == 0) 4180 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "axtr", r1, r2, r3); 4181 else 4182 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "axtra", r1, r2, r3, m4); 4183 } 4184 4185 return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2); 4186 } 4187 4188 4189 static UChar * 4190 s390_emit_CDTR(UChar *p, UChar r1, UChar r2) 4191 { 4192 vassert(s390_host_has_dfp); 4193 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4194 s390_disasm(ENC3(MNM, FPR, FPR), "cdtr", r1, r2); 4195 4196 return emit_RRE(p, 0xb3e40000, r1, r2); 4197 } 4198 4199 4200 static UChar * 4201 s390_emit_CXTR(UChar *p, UChar r1, UChar r2) 4202 { 4203 vassert(s390_host_has_dfp); 4204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4205 s390_disasm(ENC3(MNM, FPR, FPR), "cxtr", r1, r2); 4206 4207 return emit_RRE(p, 0xb3ec0000, r1, r2); 4208 } 4209 4210 4211 static UChar * 4212 s390_emit_CDGTRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4213 { 4214 vassert(s390_host_has_dfp); 4215 vassert(m4 == 0); 4216 vassert(m3 == 0 || s390_host_has_fpext); 4217 4218 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4219 if (m3 == 0) 4220 s390_disasm(ENC3(MNM, FPR, GPR), "cdgtr", r1, r2); 4221 else 4222 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdgtra", r1, m3, r2, m4); 4223 } 4224 4225 return emit_RRF2(p, 0xb3f10000, m3, m4, r1, r2); 4226 } 4227 4228 4229 static UChar * 4230 s390_emit_CXGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4231 { 4232 vassert(s390_host_has_dfp); 4233 vassert(m4 == 0); 4234 /* rounding mode m3 is not considered, as the corresponding 4235 IRop (Iop_I64StoD128) does not take rounding mode. */ 4236 vassert(m3 == 0); 4237 4238 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4239 s390_disasm(ENC3(MNM, FPR, GPR), "cxgtr", r1, r2); 4240 4241 return emit_RRF2(p, 0xb3f90000, m3, m4, r1, r2); 4242 } 4243 4244 4245 static UChar * 4246 s390_emit_CDFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4247 { 4248 vassert(m4 == 0); 4249 vassert(s390_host_has_dfp); 4250 vassert(s390_host_has_fpext); 4251 4252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4253 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdftr", r1, m3, r2, m4); 4254 4255 return emit_RRF2(p, 0xb9510000, m3, m4, r1, r2); 4256 } 4257 4258 4259 static UChar * 4260 s390_emit_CXFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4261 { 4262 vassert(m4 == 0); 4263 vassert(s390_host_has_dfp); 4264 vassert(s390_host_has_fpext); 4265 4266 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4267 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxftr", r1, m3, r2, m4); 4268 4269 return emit_RRF2(p, 0xb9590000, m3, m4, r1, r2); 4270 } 4271 4272 4273 static UChar * 4274 s390_emit_CDLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4275 { 4276 vassert(m4 == 0); 4277 vassert(s390_host_has_dfp); 4278 vassert(s390_host_has_fpext); 4279 4280 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4281 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlftr", r1, m3, r2, m4); 4282 4283 return emit_RRF2(p, 0xb9530000, m3, m4, r1, r2); 4284 } 4285 4286 4287 static UChar * 4288 s390_emit_CXLFTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4289 { 4290 vassert(m4 == 0); 4291 vassert(s390_host_has_dfp); 4292 vassert(s390_host_has_fpext); 4293 4294 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4295 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlftr", r1, m3, r2, m4); 4296 4297 return emit_RRF2(p, 0xb95b0000, m3, m4, r1, r2); 4298 } 4299 4300 4301 static UChar * 4302 s390_emit_CDLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4303 { 4304 vassert(m4 == 0); 4305 vassert(s390_host_has_dfp); 4306 vassert(s390_host_has_fpext); 4307 4308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4309 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cdlgtr", r1, m3, r2, m4); 4310 4311 return emit_RRF2(p, 0xb9520000, m3, m4, r1, r2); 4312 } 4313 4314 4315 static UChar * 4316 s390_emit_CXLGTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4317 { 4318 vassert(m4 == 0); 4319 vassert(s390_host_has_dfp); 4320 vassert(s390_host_has_fpext); 4321 4322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4323 s390_disasm(ENC5(MNM, FPR, UINT, GPR, UINT), "cxlgtr", r1, m3, r2, m4); 4324 4325 return emit_RRF2(p, 0xb95a0000, m3, m4, r1, r2); 4326 } 4327 4328 4329 static UChar * 4330 s390_emit_CEDTR(UChar *p, UChar r1, UChar r2) 4331 { 4332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4333 s390_disasm(ENC3(MNM, FPR, FPR), "cedtr", r1, r2); 4334 4335 return emit_RRE(p, 0xb3f40000, r1, r2); 4336 } 4337 4338 4339 static UChar * 4340 s390_emit_CEXTR(UChar *p, UChar r1, UChar r2) 4341 { 4342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4343 s390_disasm(ENC3(MNM, FPR, FPR), "cextr", r1, r2); 4344 4345 return emit_RRE(p, 0xb3fc0000, r1, r2); 4346 } 4347 4348 4349 static UChar * 4350 s390_emit_CFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4351 { 4352 vassert(m4 == 0); 4353 vassert(s390_host_has_dfp); 4354 vassert(s390_host_has_fpext); 4355 4356 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4357 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfdtr", r1, m3, r2, m4); 4358 4359 return emit_RRF2(p, 0xb9410000, m3, m4, r1, r2); 4360 } 4361 4362 4363 static UChar * 4364 s390_emit_CFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4365 { 4366 vassert(m4 == 0); 4367 vassert(s390_host_has_dfp); 4368 vassert(s390_host_has_fpext); 4369 4370 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4371 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "cfxtr", r1, m3, r2, m4); 4372 4373 return emit_RRF2(p, 0xb9490000, m3, m4, r1, r2); 4374 } 4375 4376 4377 static UChar * 4378 s390_emit_CGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4379 { 4380 vassert(s390_host_has_dfp); 4381 vassert(m4 == 0); 4382 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); 4383 4384 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4385 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdtr", r1, m3, r2); 4386 4387 return emit_RRF2(p, 0xb3e10000, m3, m4, r1, r2); 4388 } 4389 4390 4391 static UChar * 4392 s390_emit_CGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4393 { 4394 vassert(s390_host_has_dfp); 4395 vassert(m4 == 0); 4396 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); 4397 4398 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4399 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxtr", r1, m3, r2); 4400 4401 return emit_RRF2(p, 0xb3e90000, m3, m4, r1, r2); 4402 } 4403 4404 4405 static UChar * 4406 s390_emit_CLFDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4407 { 4408 vassert(m4 == 0); 4409 vassert(s390_host_has_dfp); 4410 vassert(s390_host_has_fpext); 4411 4412 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4413 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfdtr", r1, m3, r2, m4); 4414 4415 return emit_RRF2(p, 0xb9430000, m3, m4, r1, r2); 4416 } 4417 4418 4419 static UChar * 4420 s390_emit_CLFXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4421 { 4422 vassert(m4 == 0); 4423 vassert(s390_host_has_dfp); 4424 vassert(s390_host_has_fpext); 4425 4426 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4427 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clfxtr", r1, m3, r2, m4); 4428 4429 return emit_RRF2(p, 0xb94b0000, m3, m4, r1, r2); 4430 } 4431 4432 4433 static UChar * 4434 s390_emit_CLGDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4435 { 4436 vassert(m4 == 0); 4437 vassert(s390_host_has_dfp); 4438 vassert(s390_host_has_fpext); 4439 4440 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4441 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgdtr", r1, m3, r2, m4); 4442 4443 return emit_RRF2(p, 0xb9420000, m3, m4, r1, r2); 4444 } 4445 4446 4447 static UChar * 4448 s390_emit_CLGXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4449 { 4450 vassert(m4 == 0); 4451 vassert(s390_host_has_dfp); 4452 vassert(s390_host_has_fpext); 4453 4454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4455 s390_disasm(ENC5(MNM, GPR, UINT, FPR, UINT), "clgxtr", r1, m3, r2, m4); 4456 4457 return emit_RRF2(p, 0xb94a0000, m3, m4, r1, r2); 4458 } 4459 4460 4461 static UChar * 4462 s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4463 { 4464 vassert(s390_host_has_dfp); 4465 vassert(m4 == 0 || s390_host_has_fpext); 4466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4467 if (m4 == 0) 4468 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "ddtr", r1, r2, r3); 4469 else 4470 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "ddtra", r1, r2, r3, m4); 4471 } 4472 4473 return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2); 4474 } 4475 4476 4477 static UChar * 4478 s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4479 { 4480 vassert(s390_host_has_dfp); 4481 vassert(m4 == 0 || s390_host_has_fpext); 4482 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4483 if (m4 == 0) 4484 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "dxtr", r1, r2, r3); 4485 else 4486 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "dxtra", r1, r2, r3, m4); 4487 } 4488 4489 return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2); 4490 } 4491 4492 4493 static UChar * 4494 s390_emit_EEDTR(UChar *p, UChar r1, UChar r2) 4495 { 4496 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4497 s390_disasm(ENC3(MNM, GPR, FPR), "eedtr", r1, r2); 4498 4499 return emit_RRE(p, 0xb3e50000, r1, r2); 4500 } 4501 4502 4503 static UChar * 4504 s390_emit_EEXTR(UChar *p, UChar r1, UChar r2) 4505 { 4506 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4507 s390_disasm(ENC3(MNM, GPR, FPR), "eextr", r1, r2); 4508 4509 return emit_RRE(p, 0xb3ed0000, r1, r2); 4510 } 4511 4512 4513 static UChar * 4514 s390_emit_ESDTR(UChar *p, UChar r1, UChar r2) 4515 { 4516 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4517 s390_disasm(ENC3(MNM, GPR, FPR), "esdtr", r1, r2); 4518 4519 return emit_RRE(p, 0xb3e70000, r1, r2); 4520 } 4521 4522 4523 static UChar * 4524 s390_emit_ESXTR(UChar *p, UChar r1, UChar r2) 4525 { 4526 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4527 s390_disasm(ENC3(MNM, GPR, FPR), "esxtr", r1, r2); 4528 4529 return emit_RRE(p, 0xb3ef0000, r1, r2); 4530 } 4531 4532 4533 static UChar * 4534 s390_emit_IEDTR(UChar *p, UChar r3, UChar r1, UChar r2) 4535 { 4536 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4537 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iedtr", r1, r3, r2); 4538 4539 return emit_RRF(p, 0xb3f60000, r3, r1, r2); 4540 } 4541 4542 4543 static UChar * 4544 s390_emit_IEXTR(UChar *p, UChar r3, UChar r1, UChar r2) 4545 { 4546 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4547 s390_disasm(ENC4(MNM, FPR, FPR, GPR), "iextr", r1, r3, r2); 4548 4549 return emit_RRF(p, 0xb3fe0000, r3, r1, r2); 4550 } 4551 4552 4553 static UChar * 4554 s390_emit_LDETR(UChar *p, UChar m4, UChar r1, UChar r2) 4555 { 4556 vassert(s390_host_has_dfp); 4557 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4558 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "ldetr", r1, r2, m4); 4559 4560 return emit_RRF5(p, 0xb3d40000, m4, r1, r2); 4561 } 4562 4563 4564 static UChar * 4565 s390_emit_LXDTR(UChar *p, UChar m4, UChar r1, UChar r2) 4566 { 4567 vassert(s390_host_has_dfp); 4568 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4569 s390_disasm(ENC4(MNM, FPR, FPR, UINT), "lxdtr", r1, r2, m4); 4570 4571 return emit_RRF5(p, 0xb3dc0000, m4, r1, r2); 4572 } 4573 4574 4575 static UChar * 4576 s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4577 { 4578 vassert(s390_host_has_dfp); 4579 vassert(m4 == 0); 4580 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); 4581 4582 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4583 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ledtr", r1, m3, r2, m4); 4584 4585 return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2); 4586 } 4587 4588 4589 static UChar * 4590 s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) 4591 { 4592 vassert(s390_host_has_dfp); 4593 vassert(m4 == 0); 4594 vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); 4595 4596 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4597 s390_disasm(ENC5(MNM, FPR, UINT, FPR, UINT), "ldxtr", r1, m3, r2, m4); 4598 4599 return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2); 4600 } 4601 4602 4603 static UChar * 4604 s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4605 { 4606 vassert(s390_host_has_dfp); 4607 vassert(m4 == 0 || s390_host_has_fpext); 4608 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4609 if (m4 == 0) 4610 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mdtr", r1, r2, r3); 4611 else 4612 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mdtra", r1, r2, r3, m4); 4613 } 4614 4615 return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2); 4616 } 4617 4618 4619 static UChar * 4620 s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4621 { 4622 vassert(s390_host_has_dfp); 4623 vassert(m4 == 0 || s390_host_has_fpext); 4624 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4625 if (m4 == 0) 4626 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "mxtr", r1, r2, r3); 4627 else 4628 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "mxtra", r1, r2, r3, m4); 4629 } 4630 4631 return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2); 4632 } 4633 4634 4635 static UChar * 4636 emit_E(UChar *p, UInt op) 4637 { 4638 ULong the_insn = op; 4639 4640 return emit_2bytes(p, the_insn); 4641 } 4642 4643 4644 static UChar * 4645 s390_emit_PFPO(UChar *p) 4646 { 4647 vassert(s390_host_has_pfpo); 4648 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4649 s390_disasm(ENC1(MNM), "pfpo"); 4650 } 4651 4652 return emit_E(p, 0x010a); 4653 } 4654 4655 4656 static UChar * 4657 s390_emit_QADTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4658 { 4659 vassert(s390_host_has_dfp); 4660 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4661 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qadtr", r1, r3, r2, m4); 4662 4663 return emit_RRF4(p, 0xb3f50000, r3, m4, r1, r2); 4664 } 4665 4666 4667 static UChar * 4668 s390_emit_QAXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4669 { 4670 vassert(s390_host_has_dfp); 4671 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4672 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "qaxtr", r1, r3, r2, m4); 4673 4674 return emit_RRF4(p, 0xb3fd0000, r3, m4, r1, r2); 4675 } 4676 4677 4678 static UChar * 4679 s390_emit_RRDTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4680 { 4681 vassert(s390_host_has_dfp); 4682 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4683 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrdtr", r1, r3, r2, m4); 4684 4685 return emit_RRF4(p, 0xb3f70000, r3, m4, r1, r2); 4686 } 4687 4688 4689 static UChar * 4690 s390_emit_RRXTR(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4691 { 4692 vassert(s390_host_has_dfp); 4693 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4694 s390_disasm(ENC5(MNM, FPR, FPR, GPR, UINT), "rrxtr", r1, r3, r2, m4); 4695 4696 return emit_RRF4(p, 0xb3ff0000, r3, m4, r1, r2); 4697 } 4698 4699 4700 static UChar * 4701 s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4702 { 4703 vassert(s390_host_has_dfp); 4704 vassert(m4 == 0 || s390_host_has_fpext); 4705 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4706 if (m4 == 0) 4707 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sdtr", r1, r2, r3); 4708 else 4709 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sdtra", r1, r2, r3, m4); 4710 } 4711 4712 return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2); 4713 } 4714 4715 4716 static UChar * 4717 s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 4718 { 4719 vassert(s390_host_has_dfp); 4720 vassert(m4 == 0 || s390_host_has_fpext); 4721 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 4722 if (m4 == 0) 4723 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "sxtr", r1, r2, r3); 4724 else 4725 s390_disasm(ENC5(MNM, FPR, FPR, FPR, UINT), "sxtra", r1, r2, r3, m4); 4726 } 4727 4728 return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2); 4729 } 4730 4731 4732 static UChar * 4733 s390_emit_SLDT(UChar *p, UChar r3, UChar r1, UChar r2) 4734 { 4735 vassert(s390_host_has_dfp); 4736 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4737 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "sldt", r1, r3, 0, 0, r2); 4738 4739 return emit_RXF(p, 0xED0000000040ULL, r3, 0, r2, 0, r1); 4740 } 4741 4742 4743 static UChar * 4744 s390_emit_SLXT(UChar *p, UChar r3, UChar r1, UChar r2) 4745 { 4746 vassert(s390_host_has_dfp); 4747 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4748 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "slxt", r1, r3, 0, 0, r2); 4749 4750 return emit_RXF(p, 0xED0000000048ULL, r3, 0, r2, 0, r1); 4751 } 4752 4753 4754 static UChar * 4755 s390_emit_SRDT(UChar *p, UChar r3, UChar r1, UChar r2) 4756 { 4757 vassert(s390_host_has_dfp); 4758 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4759 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srdt", r1, r3, 0, 0, r2); 4760 4761 return emit_RXF(p, 0xED0000000041ULL, r3, 0, r2, 0, r1); 4762 } 4763 4764 4765 static UChar * 4766 s390_emit_SRXT(UChar *p, UChar r3, UChar r1, UChar r2) 4767 { 4768 vassert(s390_host_has_dfp); 4769 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4770 s390_disasm(ENC4(MNM, FPR, FPR, UDXB), "srxt", r1, r3, 0, 0, r2); 4771 4772 return emit_RXF(p, 0xED0000000049ULL, r3, 0, r2, 0, r1); 4773 } 4774 4775 4776 static UChar * 4777 s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2) 4778 { 4779 vassert(s390_host_has_lsc); 4780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4781 s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3); 4782 4783 return emit_RRF3(p, 0xb9e20000, m3, r1, r2); 4784 } 4785 4786 4787 static UChar * 4788 s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2) 4789 { 4790 vassert(s390_host_has_ldisp || dh2 == 0); 4791 4792 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4793 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2); 4794 4795 return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2); 4796 } 4797 4798 4799 static UChar * 4800 s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2) 4801 { 4802 vassert(s390_host_has_ldisp || dh2 == 0); 4803 4804 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 4805 s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2); 4806 4807 return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2); 4808 } 4809 4810 4811 /* Provide a symbolic name for register "R0" */ 4812 #define R0 0 4813 4814 /* Split up a 20-bit displacement into its high and low piece 4815 suitable for passing as function arguments */ 4816 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF) 4817 4818 /*---------------------------------------------------------------*/ 4819 /*--- Helper functions ---*/ 4820 /*---------------------------------------------------------------*/ 4821 4822 static __inline__ Bool 4823 uint_fits_signed_16bit(UInt val) 4824 { 4825 Int v = val & 0xFFFFu; 4826 4827 /* sign extend */ 4828 v = (v << 16) >> 16; 4829 4830 return val == (UInt)v; 4831 } 4832 4833 4834 static __inline__ Bool 4835 ulong_fits_signed_16bit(ULong val) 4836 { 4837 Long v = val & 0xFFFFu; 4838 4839 /* sign extend */ 4840 v = (v << 48) >> 48; 4841 4842 return val == (ULong)v; 4843 } 4844 4845 4846 static __inline__ Bool 4847 ulong_fits_signed_32bit(ULong val) 4848 { 4849 Long v = val & 0xFFFFFFFFu; 4850 4851 /* sign extend */ 4852 v = (v << 32) >> 32; 4853 4854 return val == (ULong)v; 4855 } 4856 4857 4858 static __inline__ Bool 4859 ulong_fits_unsigned_32bit(ULong val) 4860 { 4861 return (val & 0xFFFFFFFFu) == val; 4862 } 4863 4864 4865 /* Load a 64-bit immediate VAL into register REG. */ 4866 static UChar * 4867 s390_emit_load_64imm(UChar *p, UChar reg, ULong val) 4868 { 4869 if (ulong_fits_signed_16bit(val)) { 4870 return s390_emit_LGHI(p, reg, val); 4871 } 4872 4873 if (s390_host_has_eimm) { 4874 if (ulong_fits_unsigned_32bit(val)) { 4875 return s390_emit_LLILF(p, reg, val); 4876 } 4877 if (ulong_fits_signed_32bit(val)) { 4878 /* LGFI's sign extension will recreate the correct 64-bit value */ 4879 return s390_emit_LGFI(p, reg, val); 4880 } 4881 /* Do it in two steps: upper half [0:31] and lower half [32:63] */ 4882 p = s390_emit_IIHF(p, reg, val >> 32); 4883 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF); 4884 } 4885 4886 /* Fall back */ 4887 if (ulong_fits_unsigned_32bit(val)) { 4888 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47] 4889 val[0:31] = 0 */ 4890 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */ 4891 return p; 4892 } 4893 4894 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF); 4895 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF); 4896 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF); 4897 p = s390_emit_IILL(p, reg, val & 0xFFFF); 4898 4899 return p; 4900 } 4901 4902 /* Load a 32-bit immediate VAL into register REG. */ 4903 static UChar * 4904 s390_emit_load_32imm(UChar *p, UChar reg, UInt val) 4905 { 4906 if (uint_fits_signed_16bit(val)) { 4907 /* LHI's sign extension will recreate the correct 32-bit value */ 4908 return s390_emit_LHI(p, reg, val); 4909 } 4910 if (s390_host_has_eimm) { 4911 return s390_emit_IILF(p, reg, val); 4912 } 4913 /* val[0:15] --> (val >> 16) & 0xFFFF 4914 val[16:31] --> val & 0xFFFF */ 4915 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF); 4916 return s390_emit_IILL(p, reg, val & 0xFFFF); 4917 } 4918 4919 /*------------------------------------------------------------*/ 4920 /*--- Wrapper functions ---*/ 4921 /*------------------------------------------------------------*/ 4922 4923 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */ 4924 static UChar * 4925 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh) 4926 { 4927 if (s390_host_has_gie) { 4928 return s390_emit_MFY(p, r1, x, b, dl, dh); 4929 } 4930 4931 /* Load from memory into R0, then MULTIPLY with R1 */ 4932 p = s390_emit_LY(p, R0, x, b, dl, dh); 4933 return s390_emit_MR(p, r1, R0); 4934 } 4935 4936 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */ 4937 static UChar * 4938 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh) 4939 { 4940 if (s390_host_has_gie) { 4941 return s390_emit_MHY(p, r1, x, b, dl, dh); 4942 } 4943 4944 /* Load from memory into R0, then MULTIPLY with R1 */ 4945 p = s390_emit_LHY(p, R0, x, b, dl, dh); 4946 return s390_emit_MSR(p, r1, R0); 4947 } 4948 4949 /* r1[32:63] = r1[32:63] * i2 */ 4950 static UChar * 4951 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2) 4952 { 4953 if (s390_host_has_gie) { 4954 return s390_emit_MSFI(p, r1, i2); 4955 } 4956 4957 /* Load I2 into R0; then MULTIPLY R0 with R1 */ 4958 p = s390_emit_load_32imm(p, R0, i2); 4959 return s390_emit_MSR(p, r1, R0); 4960 } 4961 4962 4963 /* r1[32:63] = r1[32:63] & i2 */ 4964 static UChar * 4965 s390_emit_NILFw(UChar *p, UChar r1, UInt i2) 4966 { 4967 if (s390_host_has_eimm) { 4968 return s390_emit_NILF(p, r1, i2); 4969 } 4970 4971 /* Load I2 into R0; then AND R0 with R1 */ 4972 p = s390_emit_load_32imm(p, R0, i2); 4973 return s390_emit_NR(p, r1, R0); 4974 } 4975 4976 4977 /* r1[32:63] = r1[32:63] | i2 */ 4978 static UChar * 4979 s390_emit_OILFw(UChar *p, UChar r1, UInt i2) 4980 { 4981 if (s390_host_has_eimm) { 4982 return s390_emit_OILF(p, r1, i2); 4983 } 4984 4985 /* Load I2 into R0; then AND R0 with R1 */ 4986 p = s390_emit_load_32imm(p, R0, i2); 4987 return s390_emit_OR(p, r1, R0); 4988 } 4989 4990 4991 /* r1[32:63] = r1[32:63] ^ i2 */ 4992 static UChar * 4993 s390_emit_XILFw(UChar *p, UChar r1, UInt i2) 4994 { 4995 if (s390_host_has_eimm) { 4996 return s390_emit_XILF(p, r1, i2); 4997 } 4998 4999 /* Load I2 into R0; then AND R0 with R1 */ 5000 p = s390_emit_load_32imm(p, R0, i2); 5001 return s390_emit_XR(p, r1, R0); 5002 } 5003 5004 5005 /* r1[32:63] = sign_extend(mem[op2addr][0:7]) */ 5006 static UChar * 5007 s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 5008 { 5009 vassert(s390_host_has_ldisp || dh2 == 0); 5010 5011 if (s390_host_has_ldisp) { 5012 return s390_emit_LB(p, r1, x2, b2, dl2, dh2); 5013 } 5014 5015 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */ 5016 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */ 5017 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */ 5018 } 5019 5020 5021 /* r1[32:63] = sign_extend(r2[56:63]) */ 5022 static UChar * 5023 s390_emit_LBRw(UChar *p, UChar r1, UChar r2) 5024 { 5025 if (s390_host_has_eimm) { 5026 return s390_emit_LBR(p, r1, r2); 5027 } 5028 5029 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 5030 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */ 5031 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */ 5032 } 5033 5034 5035 /* r1[0:63] = sign_extend(mem[op2addr][0:7]) */ 5036 static UChar * 5037 s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 5038 { 5039 vassert(s390_host_has_ldisp || dh2 == 0); 5040 5041 if (s390_host_has_ldisp) { 5042 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2); 5043 } 5044 5045 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */ 5046 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */ 5047 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */ 5048 } 5049 5050 5051 /* r1[0:63] = sign_extend(r2[56:63]) */ 5052 static UChar * 5053 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2) 5054 { 5055 if (s390_host_has_eimm) { 5056 return s390_emit_LGBR(p, r1, r2); 5057 } 5058 5059 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 5060 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */ 5061 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */ 5062 } 5063 5064 5065 /* r1[32:63] = sign_extend(r2[48:63]) */ 5066 static UChar * 5067 s390_emit_LHRw(UChar *p, UChar r1, UChar r2) 5068 { 5069 if (s390_host_has_eimm) { 5070 return s390_emit_LHR(p, r1, r2); 5071 } 5072 5073 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 5074 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */ 5075 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */ 5076 } 5077 5078 5079 /* r1[0:63] = sign_extend(r2[48:63]) */ 5080 static UChar * 5081 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2) 5082 { 5083 if (s390_host_has_eimm) { 5084 return s390_emit_LGHR(p, r1, r2); 5085 } 5086 5087 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 5088 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */ 5089 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */ 5090 } 5091 5092 5093 /* r1[0:63] = sign_extend(i2) */ 5094 static UChar * 5095 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2) 5096 { 5097 if (s390_host_has_eimm) { 5098 return s390_emit_LGFI(p, r1, i2); 5099 } 5100 5101 p = s390_emit_load_32imm(p, R0, i2); 5102 return s390_emit_LGFR(p, r1, R0); 5103 } 5104 5105 5106 /* r1[32:63] = zero_extend($r2[56:63]) */ 5107 static UChar * 5108 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2) 5109 { 5110 if (s390_host_has_eimm) { 5111 return s390_emit_LLCR(p, r1, r2); 5112 } 5113 5114 p = s390_emit_LR(p, r1, r2); 5115 p = s390_emit_LHI(p, R0, 0xFF); 5116 return s390_emit_NR(p, r1, R0); 5117 } 5118 5119 5120 /* r1[0:63] = zero_extend($r2[56:63]) */ 5121 static UChar * 5122 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2) 5123 { 5124 if (s390_host_has_eimm) { 5125 return s390_emit_LLGCR(p, r1, r2); 5126 } 5127 5128 p = s390_emit_LR(p, r1, r2); 5129 p = s390_emit_LLILL(p, R0, 0xFF); 5130 return s390_emit_NGR(p, r1, R0); 5131 } 5132 5133 5134 /* r1[32:63] = zero_extend(r2[48:63]) */ 5135 static UChar * 5136 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2) 5137 { 5138 if (s390_host_has_eimm) { 5139 return s390_emit_LLHR(p, r1, r2); 5140 } 5141 5142 p = s390_emit_LR(p, r1, r2); 5143 p = s390_emit_LLILL(p, R0, 0xFFFF); 5144 return s390_emit_NR(p, r1, R0); 5145 } 5146 5147 5148 /* r1[0:63] = zero_extend(r2[48:63]) */ 5149 static UChar * 5150 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2) 5151 { 5152 if (s390_host_has_eimm) { 5153 return s390_emit_LLGHR(p, r1, r2); 5154 } 5155 5156 p = s390_emit_LR(p, r1, r2); 5157 p = s390_emit_LLILL(p, R0, 0xFFFF); 5158 return s390_emit_NGR(p, r1, R0); 5159 } 5160 5161 5162 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */ 5163 static UChar * 5164 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 5165 { 5166 if (s390_host_has_eimm) { 5167 return s390_emit_LLC(p, r1, x2, b2, dl, dh); 5168 } 5169 5170 if (dh == 0) { 5171 p = s390_emit_IC(p, r1, x2, b2, dl); 5172 } else { 5173 p = s390_emit_ICY(p, r1, x2, b2, dl, dh); 5174 } 5175 p = s390_emit_LLILL(p, R0, 0xFF); 5176 return s390_emit_NR(p, r1, R0); 5177 } 5178 5179 5180 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */ 5181 static UChar * 5182 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 5183 { 5184 if (s390_host_has_eimm) { 5185 return s390_emit_LLH(p, r1, x2, b2, dl, dh); 5186 } 5187 5188 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh); 5189 p = s390_emit_LLILL(p, R0, 0xFFFF); 5190 return s390_emit_NR(p, r1, R0); 5191 } 5192 5193 5194 /* r1[0:63] = zero_extend(i2) */ 5195 static UChar * 5196 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2) 5197 { 5198 if (s390_host_has_eimm) { 5199 return s390_emit_LLILF(p, r1, i2); 5200 } 5201 5202 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */ 5203 return s390_emit_OILL(p, r1, i2 & 0xFFFF); 5204 } 5205 5206 5207 /* r1[32:63] = r1[32:63] + i2 */ 5208 static UChar * 5209 s390_emit_AFIw(UChar *p, UChar r1, UInt i2) 5210 { 5211 if (s390_host_has_eimm) { 5212 return s390_emit_AFI(p, r1, i2); 5213 } 5214 /* Load 32 bit immediate to R0 then add */ 5215 p = s390_emit_load_32imm(p, R0, i2); 5216 return s390_emit_AR(p, r1, R0); 5217 } 5218 5219 5220 /* r1[32:63] = r1[32:63] - i2 */ 5221 static UChar * 5222 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2) 5223 { 5224 if (s390_host_has_eimm) { 5225 return s390_emit_SLFI(p, r1, i2); 5226 } 5227 5228 /* Load 32 bit immediate to R0 then subtract */ 5229 p = s390_emit_load_32imm(p, R0, i2); 5230 return s390_emit_SR(p, r1, R0); 5231 } 5232 5233 5234 /* r1[0:63] = r1[0:63] - zero_extend(i2) */ 5235 static UChar * 5236 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2) 5237 { 5238 if (s390_host_has_eimm) { 5239 return s390_emit_SLGFI(p, r1, i2); 5240 } 5241 5242 /* Load zero-extended 32 bit immediate to R0 then subtract */ 5243 p = s390_emit_load_64imm(p, R0, i2); 5244 return s390_emit_SGR(p, r1, R0); 5245 } 5246 5247 5248 static UChar * 5249 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 5250 { 5251 if (s390_host_has_eimm) { 5252 return s390_emit_LT(p, r1, x2, b2, dl, dh); 5253 } 5254 /* Load 32 bit from memory to R0 then compare */ 5255 if (dh == 0) { 5256 p = s390_emit_L(p, R0, x2, b2, dl); 5257 } else { 5258 p = s390_emit_LY(p, R0, x2, b2, dl, dh); 5259 } 5260 return s390_emit_LTR(p, r1, R0); 5261 } 5262 5263 5264 static UChar * 5265 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 5266 { 5267 if (s390_host_has_eimm) { 5268 return s390_emit_LTG(p, r1, x2, b2, dl, dh); 5269 } 5270 /* Load 64 bit from memory to R0 then compare */ 5271 p = s390_emit_LG(p, R0, x2, b2, dl, dh); 5272 return s390_emit_LTGR(p, r1, R0); 5273 } 5274 5275 5276 static UChar * 5277 s390_emit_CFIw(UChar *p, UChar r1, UInt i2) 5278 { 5279 if (s390_host_has_eimm) { 5280 return s390_emit_CFI(p, r1, i2); 5281 } 5282 /* Load 32 bit immediate to R0 then compare */ 5283 p = s390_emit_load_32imm(p, R0, i2); 5284 return s390_emit_CR(p, r1, R0); 5285 } 5286 5287 5288 static UChar * 5289 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2) 5290 { 5291 if (s390_host_has_eimm) { 5292 return s390_emit_CLFI(p, r1, i2); 5293 } 5294 /* Load 32 bit immediate to R0 then compare */ 5295 p = s390_emit_load_32imm(p, R0, i2); 5296 return s390_emit_CLR(p, r1, R0); 5297 } 5298 5299 5300 static UChar * 5301 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2) 5302 { 5303 if (s390_host_has_fgx) { 5304 return s390_emit_LGDR(p, r1, r2); 5305 } 5306 5307 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards 5308 smaller addresses and is 8-byte aligned. Then load the GPR from that 5309 memory location/ */ 5310 if (s390_host_has_ldisp) { 5311 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 5312 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 5313 } 5314 5315 /* No long displacement. Need to adjust SP explicitly as to avoid negative 5316 displacements. */ 5317 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8); 5318 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0); 5319 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0)); 5320 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8); 5321 } 5322 5323 5324 static UChar * 5325 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2) 5326 { 5327 if (s390_host_has_fgx) { 5328 return s390_emit_LDGR(p, r1, r2); 5329 } 5330 5331 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards 5332 smaller addresses and is 8-byte aligned. Then load the FPR from that 5333 memory location/ */ 5334 if (s390_host_has_ldisp) { 5335 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 5336 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 5337 } 5338 5339 /* No long displacement. Need to adjust SP explicitly as to avoid negative 5340 displacements. */ 5341 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8); 5342 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0)); 5343 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0); 5344 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8); 5345 } 5346 5347 5348 /*---------------------------------------------------------------*/ 5349 /*--- Constructors for the various s390_insn kinds ---*/ 5350 /*---------------------------------------------------------------*/ 5351 5352 s390_insn * 5353 s390_insn_load(UChar size, HReg dst, s390_amode *src) 5354 { 5355 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5356 5357 insn->tag = S390_INSN_LOAD; 5358 insn->size = size; 5359 insn->variant.load.src = src; 5360 insn->variant.load.dst = dst; 5361 5362 vassert(size == 1 || size == 2 || size == 4 || size == 8); 5363 5364 return insn; 5365 } 5366 5367 5368 s390_insn * 5369 s390_insn_store(UChar size, s390_amode *dst, HReg src) 5370 { 5371 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5372 5373 insn->tag = S390_INSN_STORE; 5374 insn->size = size; 5375 insn->variant.store.src = src; 5376 insn->variant.store.dst = dst; 5377 5378 vassert(size == 1 || size == 2 || size == 4 || size == 8); 5379 5380 return insn; 5381 } 5382 5383 5384 s390_insn * 5385 s390_insn_move(UChar size, HReg dst, HReg src) 5386 { 5387 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5388 5389 insn->tag = S390_INSN_MOVE; 5390 insn->size = size; 5391 insn->variant.move.src = src; 5392 insn->variant.move.dst = dst; 5393 5394 vassert(size == 1 || size == 2 || size == 4 || size == 8); 5395 5396 return insn; 5397 } 5398 5399 5400 s390_insn * 5401 s390_insn_memcpy(UChar size, s390_amode *dst, s390_amode *src) 5402 { 5403 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5404 5405 /* This insn will be mapped to MVC which requires base register 5406 plus 12-bit displacement */ 5407 vassert(src->tag == S390_AMODE_B12); 5408 vassert(dst->tag == S390_AMODE_B12); 5409 5410 insn->tag = S390_INSN_MEMCPY; 5411 insn->size = size; 5412 insn->variant.memcpy.src = src; 5413 insn->variant.memcpy.dst = dst; 5414 5415 vassert(size == 1 || size == 2 || size == 4 || size == 8); 5416 5417 return insn; 5418 } 5419 5420 5421 s390_insn * 5422 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src) 5423 { 5424 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5425 5426 insn->tag = S390_INSN_COND_MOVE; 5427 insn->size = size; 5428 insn->variant.cond_move.cond = cond; 5429 insn->variant.cond_move.src = src; 5430 insn->variant.cond_move.dst = dst; 5431 5432 vassert(size == 1 || size == 2 || size == 4 || size == 8); 5433 5434 return insn; 5435 } 5436 5437 5438 s390_insn * 5439 s390_insn_load_immediate(UChar size, HReg dst, ULong value) 5440 { 5441 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5442 5443 insn->tag = S390_INSN_LOAD_IMMEDIATE; 5444 insn->size = size; 5445 insn->variant.load_immediate.dst = dst; 5446 insn->variant.load_immediate.value = value; 5447 5448 return insn; 5449 } 5450 5451 5452 s390_insn * 5453 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2) 5454 { 5455 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5456 5457 insn->tag = S390_INSN_ALU; 5458 insn->size = size; 5459 insn->variant.alu.tag = tag; 5460 insn->variant.alu.dst = dst; 5461 insn->variant.alu.op2 = op2; 5462 5463 return insn; 5464 } 5465 5466 5467 s390_insn * 5468 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2, 5469 Bool signed_multiply) 5470 { 5471 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5472 5473 vassert(! hregIsVirtual(dst_hi)); 5474 vassert(! hregIsVirtual(dst_lo)); 5475 5476 insn->tag = signed_multiply ? S390_INSN_SMUL : S390_INSN_UMUL; 5477 insn->size = size; 5478 insn->variant.mul.dst_hi = dst_hi; 5479 insn->variant.mul.dst_lo = dst_lo; 5480 insn->variant.mul.op2 = op2; 5481 5482 return insn; 5483 } 5484 5485 5486 s390_insn * 5487 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2, 5488 Bool signed_divide) 5489 { 5490 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5491 5492 vassert(size == 4 || size == 8); 5493 vassert(! hregIsVirtual(op1_hi)); 5494 vassert(! hregIsVirtual(op1_lo)); 5495 5496 insn->tag = signed_divide ? S390_INSN_SDIV : S390_INSN_UDIV; 5497 insn->size = size; 5498 insn->variant.div.op1_hi = op1_hi; 5499 insn->variant.div.op1_lo = op1_lo; 5500 insn->variant.div.op2 = op2; 5501 5502 return insn; 5503 } 5504 5505 5506 s390_insn * 5507 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2) 5508 { 5509 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5510 5511 vassert(size == 8); 5512 vassert(! hregIsVirtual(op1)); 5513 vassert(! hregIsVirtual(rem)); 5514 5515 insn->tag = S390_INSN_DIVS; 5516 insn->size = size; 5517 insn->variant.divs.rem = rem; /* remainder */ 5518 insn->variant.divs.op1 = op1; /* also quotient */ 5519 insn->variant.divs.op2 = op2; 5520 5521 return insn; 5522 } 5523 5524 5525 s390_insn * 5526 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src) 5527 { 5528 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5529 5530 vassert(size == 8); 5531 vassert(! hregIsVirtual(num_bits)); 5532 vassert(! hregIsVirtual(clobber)); 5533 5534 insn->tag = S390_INSN_CLZ; 5535 insn->size = size; 5536 insn->variant.clz.num_bits = num_bits; 5537 insn->variant.clz.clobber = clobber; 5538 insn->variant.clz.src = src; 5539 5540 return insn; 5541 } 5542 5543 5544 s390_insn * 5545 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd) 5546 { 5547 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5548 5549 insn->tag = S390_INSN_UNOP; 5550 insn->size = size; 5551 insn->variant.unop.tag = tag; 5552 insn->variant.unop.dst = dst; 5553 insn->variant.unop.src = opnd; 5554 5555 return insn; 5556 } 5557 5558 5559 s390_insn * 5560 s390_insn_test(UChar size, s390_opnd_RMI src) 5561 { 5562 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5563 5564 vassert(size == 4 || size == 8); 5565 5566 insn->tag = S390_INSN_TEST; 5567 insn->size = size; 5568 insn->variant.test.src = src; 5569 5570 return insn; 5571 } 5572 5573 5574 s390_insn * 5575 s390_insn_cc2bool(HReg dst, s390_cc_t cond) 5576 { 5577 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5578 5579 insn->tag = S390_INSN_CC2BOOL; 5580 insn->size = 0; /* does not matter */ 5581 insn->variant.cc2bool.cond = cond; 5582 insn->variant.cc2bool.dst = dst; 5583 5584 return insn; 5585 } 5586 5587 5588 s390_insn * 5589 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem) 5590 { 5591 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5592 5593 vassert(size == 4 || size == 8); 5594 vassert(hregNumber(op2->x) == 0); 5595 5596 insn->tag = S390_INSN_CAS; 5597 insn->size = size; 5598 insn->variant.cas.op1 = op1; 5599 insn->variant.cas.op2 = op2; 5600 insn->variant.cas.op3 = op3; 5601 insn->variant.cas.old_mem = old_mem; 5602 5603 return insn; 5604 } 5605 5606 5607 s390_insn * 5608 s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2, 5609 HReg op3_high, HReg op3_low, HReg old_mem_high, HReg old_mem_low, 5610 HReg scratch) 5611 { 5612 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5613 s390_cdas *cdas = LibVEX_Alloc(sizeof(s390_cdas)); 5614 5615 vassert(size == 4 || size == 8); 5616 vassert(hregNumber(op2->x) == 0); 5617 vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */ 5618 5619 insn->tag = S390_INSN_CDAS; 5620 insn->size = size; 5621 insn->variant.cdas.details = cdas; 5622 5623 cdas->op1_high = op1_high; 5624 cdas->op1_low = op1_low; 5625 cdas->op2 = op2; 5626 cdas->op3_high = op3_high; 5627 cdas->op3_low = op3_low; 5628 cdas->old_mem_high = old_mem_high; 5629 cdas->old_mem_low = old_mem_low; 5630 cdas->scratch = scratch; 5631 5632 return insn; 5633 } 5634 5635 5636 s390_insn * 5637 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2, 5638 Bool signed_comparison) 5639 { 5640 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5641 5642 vassert(size == 4 || size == 8); 5643 5644 insn->tag = S390_INSN_COMPARE; 5645 insn->size = size; 5646 insn->variant.compare.src1 = src1; 5647 insn->variant.compare.src2 = src2; 5648 insn->variant.compare.signed_comparison = signed_comparison; 5649 5650 return insn; 5651 } 5652 5653 5654 s390_insn * 5655 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args, 5656 const HChar *name, RetLoc rloc) 5657 { 5658 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5659 s390_helper_call *helper_call = LibVEX_Alloc(sizeof(s390_helper_call)); 5660 5661 insn->tag = S390_INSN_HELPER_CALL; 5662 insn->size = 0; /* does not matter */ 5663 insn->variant.helper_call.details = helper_call; 5664 5665 helper_call->cond = cond; 5666 helper_call->target = target; 5667 helper_call->num_args = num_args; 5668 helper_call->name = name; 5669 helper_call->rloc = rloc; 5670 5671 vassert(is_sane_RetLoc(rloc)); 5672 5673 return insn; 5674 } 5675 5676 5677 s390_insn * 5678 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2, 5679 HReg op3) 5680 { 5681 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5682 5683 vassert(size == 4 || size == 8); 5684 5685 insn->tag = S390_INSN_BFP_TRIOP; 5686 insn->size = size; 5687 insn->variant.bfp_triop.tag = tag; 5688 insn->variant.bfp_triop.dst = dst; 5689 insn->variant.bfp_triop.op2 = op2; 5690 insn->variant.bfp_triop.op3 = op3; 5691 5692 return insn; 5693 } 5694 5695 5696 s390_insn * 5697 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2) 5698 { 5699 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5700 5701 vassert(size == 4 || size == 8); 5702 5703 insn->tag = S390_INSN_BFP_BINOP; 5704 insn->size = size; 5705 insn->variant.bfp_binop.tag = tag; 5706 insn->variant.bfp_binop.dst_hi = dst; 5707 insn->variant.bfp_binop.op2_hi = op2; 5708 insn->variant.bfp_binop.dst_lo = INVALID_HREG; 5709 insn->variant.bfp_binop.op2_lo = INVALID_HREG; 5710 5711 return insn; 5712 } 5713 5714 5715 s390_insn * 5716 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op) 5717 { 5718 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5719 5720 vassert(size == 4 || size == 8); 5721 5722 insn->tag = S390_INSN_BFP_UNOP; 5723 insn->size = size; 5724 insn->variant.bfp_unop.tag = tag; 5725 insn->variant.bfp_unop.dst_hi = dst; 5726 insn->variant.bfp_unop.op_hi = op; 5727 insn->variant.bfp_unop.dst_lo = INVALID_HREG; 5728 insn->variant.bfp_unop.op_lo = INVALID_HREG; 5729 5730 return insn; 5731 } 5732 5733 5734 s390_insn * 5735 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2) 5736 { 5737 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5738 5739 vassert(size == 4 || size == 8); 5740 5741 insn->tag = S390_INSN_BFP_COMPARE; 5742 insn->size = size; 5743 insn->variant.bfp_compare.dst = dst; 5744 insn->variant.bfp_compare.op1_hi = op1; 5745 insn->variant.bfp_compare.op2_hi = op2; 5746 insn->variant.bfp_compare.op1_lo = INVALID_HREG; 5747 insn->variant.bfp_compare.op2_lo = INVALID_HREG; 5748 5749 return insn; 5750 } 5751 5752 5753 s390_insn * 5754 s390_insn_bfp_convert(UChar size, s390_bfp_conv_t tag, HReg dst, HReg op, 5755 s390_bfp_round_t rounding_mode) 5756 { 5757 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5758 5759 vassert(size == 4 || size == 8); 5760 5761 insn->tag = S390_INSN_BFP_CONVERT; 5762 insn->size = size; 5763 insn->variant.bfp_convert.tag = tag; 5764 insn->variant.bfp_convert.dst_hi = dst; 5765 insn->variant.bfp_convert.op_hi = op; 5766 insn->variant.bfp_convert.dst_lo = INVALID_HREG; 5767 insn->variant.bfp_convert.op_lo = INVALID_HREG; 5768 insn->variant.bfp_convert.rounding_mode = rounding_mode; 5769 5770 return insn; 5771 } 5772 5773 5774 /* Check validity of a register pair for 128-bit FP. Valid register 5775 pairs are (0,2), (1,3), (4, 6), (5, 7), (8, 10), (9, 11), (12, 14), 5776 and (13, 15). */ 5777 static Bool 5778 is_valid_fp128_regpair(HReg hi, HReg lo) 5779 { 5780 UInt hi_regno = hregNumber(hi); 5781 UInt lo_regno = hregNumber(lo); 5782 5783 if (lo_regno != hi_regno + 2) return False; 5784 if ((hi_regno & 0x2) != 0) return False; 5785 5786 return True; 5787 } 5788 5789 s390_insn * 5790 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi, 5791 HReg dst_lo, HReg op2_hi, HReg op2_lo) 5792 { 5793 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5794 5795 vassert(size == 16); 5796 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 5797 vassert(is_valid_fp128_regpair(op2_hi, op2_lo)); 5798 5799 insn->tag = S390_INSN_BFP_BINOP; 5800 insn->size = size; 5801 insn->variant.bfp_binop.tag = tag; 5802 insn->variant.bfp_binop.dst_hi = dst_hi; 5803 insn->variant.bfp_binop.dst_lo = dst_lo; 5804 insn->variant.bfp_binop.op2_hi = op2_hi; 5805 insn->variant.bfp_binop.op2_lo = op2_lo; 5806 5807 return insn; 5808 } 5809 5810 5811 s390_insn * 5812 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi, 5813 HReg dst_lo, HReg op_hi, HReg op_lo) 5814 { 5815 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5816 5817 vassert(size == 16); 5818 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 5819 vassert(is_valid_fp128_regpair(op_hi, op_lo)); 5820 5821 insn->tag = S390_INSN_BFP_UNOP; 5822 insn->size = size; 5823 insn->variant.bfp_unop.tag = tag; 5824 insn->variant.bfp_unop.dst_hi = dst_hi; 5825 insn->variant.bfp_unop.dst_lo = dst_lo; 5826 insn->variant.bfp_unop.op_hi = op_hi; 5827 insn->variant.bfp_unop.op_lo = op_lo; 5828 5829 return insn; 5830 } 5831 5832 5833 s390_insn * 5834 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo, 5835 HReg op2_hi, HReg op2_lo) 5836 { 5837 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5838 5839 vassert(size == 16); 5840 vassert(is_valid_fp128_regpair(op1_hi, op1_lo)); 5841 vassert(is_valid_fp128_regpair(op2_hi, op2_lo)); 5842 5843 insn->tag = S390_INSN_BFP_COMPARE; 5844 insn->size = size; 5845 insn->variant.bfp_compare.dst = dst; 5846 insn->variant.bfp_compare.op1_hi = op1_hi; 5847 insn->variant.bfp_compare.op1_lo = op1_lo; 5848 insn->variant.bfp_compare.op2_hi = op2_hi; 5849 insn->variant.bfp_compare.op2_lo = op2_lo; 5850 5851 return insn; 5852 } 5853 5854 5855 static s390_insn * 5856 s390_insn_bfp128_convert(UChar size, s390_bfp_conv_t tag, HReg dst_hi, 5857 HReg dst_lo, HReg op_hi, HReg op_lo, 5858 s390_bfp_round_t rounding_mode) 5859 { 5860 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5861 5862 if (size == 16) { 5863 /* From smaller size to 16 bytes */ 5864 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 5865 vassert(hregIsInvalid(op_lo)); 5866 } else { 5867 /* From 16 bytes to smaller size */ 5868 vassert(is_valid_fp128_regpair(op_hi, op_lo)); 5869 } 5870 5871 insn->tag = S390_INSN_BFP_CONVERT; 5872 insn->size = size; 5873 insn->variant.bfp_convert.tag = tag; 5874 insn->variant.bfp_convert.dst_hi = dst_hi; 5875 insn->variant.bfp_convert.dst_lo = dst_lo; 5876 insn->variant.bfp_convert.op_hi = op_hi; 5877 insn->variant.bfp_convert.op_lo = op_lo; 5878 insn->variant.bfp_convert.rounding_mode = rounding_mode; 5879 5880 return insn; 5881 } 5882 5883 5884 s390_insn * 5885 s390_insn_bfp128_convert_to(UChar size, s390_bfp_conv_t tag, HReg dst_hi, 5886 HReg dst_lo, HReg op) 5887 { 5888 /* Conversion to bfp128 never requires a rounding mode. Provide default 5889 rounding mode. It will not be used when emitting insns. */ 5890 s390_bfp_round_t rounding_mode = S390_BFP_ROUND_NEAREST_EVEN; 5891 5892 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op, 5893 INVALID_HREG, rounding_mode); 5894 } 5895 5896 5897 s390_insn * 5898 s390_insn_bfp128_convert_from(UChar size, s390_bfp_conv_t tag, HReg dst_hi, 5899 HReg dst_lo, HReg op_hi, HReg op_lo, 5900 s390_bfp_round_t rounding_mode) 5901 { 5902 return s390_insn_bfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo, 5903 rounding_mode); 5904 } 5905 5906 5907 s390_insn * 5908 s390_insn_dfp_binop(UChar size, s390_dfp_binop_t tag, HReg dst, HReg op2, 5909 HReg op3, s390_dfp_round_t rounding_mode) 5910 { 5911 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5912 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop)); 5913 5914 vassert(size == 8); 5915 5916 insn->tag = S390_INSN_DFP_BINOP; 5917 insn->size = size; 5918 insn->variant.dfp_binop.details = dfp_binop; 5919 5920 dfp_binop->tag = tag; 5921 dfp_binop->dst_hi = dst; 5922 dfp_binop->op2_hi = op2; 5923 dfp_binop->op3_hi = op3; 5924 dfp_binop->dst_lo = INVALID_HREG; 5925 dfp_binop->op2_lo = INVALID_HREG; 5926 dfp_binop->op3_lo = INVALID_HREG; 5927 dfp_binop->rounding_mode = rounding_mode; 5928 5929 return insn; 5930 } 5931 5932 5933 s390_insn * 5934 s390_insn_dfp_unop(UChar size, s390_dfp_unop_t tag, HReg dst, HReg op) 5935 { 5936 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5937 5938 vassert(size == 8); 5939 5940 insn->tag = S390_INSN_DFP_UNOP; 5941 insn->size = size; 5942 insn->variant.dfp_unop.tag = tag; 5943 insn->variant.dfp_unop.dst_hi = dst; 5944 insn->variant.dfp_unop.op_hi = op; 5945 insn->variant.dfp_unop.dst_lo = INVALID_HREG; 5946 insn->variant.dfp_unop.op_lo = INVALID_HREG; 5947 5948 return insn; 5949 } 5950 5951 5952 s390_insn * 5953 s390_insn_dfp_intop(UChar size, s390_dfp_intop_t tag, HReg dst, HReg op2, 5954 HReg op3) 5955 { 5956 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5957 5958 vassert(size == 8); 5959 5960 insn->tag = S390_INSN_DFP_INTOP; 5961 insn->size = size; 5962 insn->variant.dfp_intop.tag = tag; 5963 insn->variant.dfp_intop.dst_hi = dst; 5964 insn->variant.dfp_intop.op2 = op2; 5965 insn->variant.dfp_intop.op3_hi = op3; 5966 insn->variant.dfp_intop.dst_lo = INVALID_HREG; 5967 insn->variant.dfp_intop.op3_lo = INVALID_HREG; 5968 5969 return insn; 5970 } 5971 5972 5973 s390_insn * 5974 s390_insn_dfp_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, 5975 HReg op1, HReg op2) 5976 { 5977 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5978 5979 vassert(size == 8); 5980 5981 insn->tag = S390_INSN_DFP_COMPARE; 5982 insn->size = size; 5983 insn->variant.dfp_compare.tag = tag; 5984 insn->variant.dfp_compare.dst = dst; 5985 insn->variant.dfp_compare.op1_hi = op1; 5986 insn->variant.dfp_compare.op2_hi = op2; 5987 insn->variant.dfp_compare.op1_lo = INVALID_HREG; 5988 insn->variant.dfp_compare.op2_lo = INVALID_HREG; 5989 5990 return insn; 5991 } 5992 5993 5994 s390_insn * 5995 s390_insn_dfp_convert(UChar size, s390_dfp_conv_t tag, HReg dst, HReg op, 5996 s390_dfp_round_t rounding_mode) 5997 { 5998 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 5999 6000 vassert(size == 4 || size == 8); 6001 6002 insn->tag = S390_INSN_DFP_CONVERT; 6003 insn->size = size; 6004 insn->variant.dfp_convert.tag = tag; 6005 insn->variant.dfp_convert.dst_hi = dst; 6006 insn->variant.dfp_convert.op_hi = op; 6007 insn->variant.dfp_convert.dst_lo = INVALID_HREG; 6008 insn->variant.dfp_convert.op_lo = INVALID_HREG; 6009 insn->variant.dfp_convert.rounding_mode = rounding_mode; 6010 6011 return insn; 6012 } 6013 6014 6015 s390_insn * 6016 s390_insn_dfp_reround(UChar size, HReg dst, HReg op2, HReg op3, 6017 s390_dfp_round_t rounding_mode) 6018 { 6019 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6020 6021 vassert(size == 8); 6022 6023 insn->tag = S390_INSN_DFP_REROUND; 6024 insn->size = size; 6025 insn->variant.dfp_reround.dst_hi = dst; 6026 insn->variant.dfp_reround.op2 = op2; 6027 insn->variant.dfp_reround.op3_hi = op3; 6028 insn->variant.dfp_reround.dst_lo = INVALID_HREG; 6029 insn->variant.dfp_reround.op3_lo = INVALID_HREG; 6030 insn->variant.dfp_reround.rounding_mode = rounding_mode; 6031 6032 return insn; 6033 } 6034 6035 6036 s390_insn * 6037 s390_insn_fp_convert(UChar size, s390_fp_conv_t tag, HReg dst, HReg op, 6038 HReg r1, s390_dfp_round_t rounding_mode) 6039 { 6040 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6041 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert)); 6042 6043 vassert(size == 4 || size == 8); 6044 6045 insn->tag = S390_INSN_FP_CONVERT; 6046 insn->size = size; 6047 insn->variant.fp_convert.details = fp_convert; 6048 6049 fp_convert->tag = tag; 6050 fp_convert->dst_hi = dst; 6051 fp_convert->op_hi = op; 6052 fp_convert->r1 = r1; 6053 fp_convert->dst_lo = INVALID_HREG; 6054 fp_convert->op_lo = INVALID_HREG; 6055 fp_convert->rounding_mode = rounding_mode; 6056 6057 return insn; 6058 } 6059 6060 6061 s390_insn * 6062 s390_insn_fp128_convert(UChar size, s390_fp_conv_t tag, HReg dst_hi, 6063 HReg dst_lo, HReg op_hi, HReg op_lo, HReg r1, 6064 s390_dfp_round_t rounding_mode) 6065 { 6066 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6067 s390_fp_convert *fp_convert = LibVEX_Alloc(sizeof(s390_fp_convert)); 6068 6069 vassert(size == 16); 6070 6071 insn->tag = S390_INSN_FP_CONVERT; 6072 insn->size = size; 6073 insn->variant.fp_convert.details = fp_convert; 6074 6075 fp_convert->tag = tag; 6076 fp_convert->dst_hi = dst_hi; 6077 fp_convert->dst_lo = dst_lo; 6078 fp_convert->op_hi = op_hi; 6079 fp_convert->r1 = r1; 6080 fp_convert->op_lo = op_lo; 6081 fp_convert->rounding_mode = rounding_mode; 6082 6083 return insn; 6084 } 6085 6086 6087 s390_insn * 6088 s390_insn_dfp128_binop(UChar size, s390_dfp_binop_t tag, HReg dst_hi, 6089 HReg dst_lo, HReg op2_hi, HReg op2_lo, HReg op3_hi, 6090 HReg op3_lo, s390_dfp_round_t rounding_mode) 6091 { 6092 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6093 s390_dfp_binop *dfp_binop = LibVEX_Alloc(sizeof(s390_dfp_binop)); 6094 6095 vassert(size == 16); 6096 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 6097 vassert(is_valid_fp128_regpair(op2_hi, op2_lo)); 6098 vassert(is_valid_fp128_regpair(op3_hi, op3_lo)); 6099 6100 insn->tag = S390_INSN_DFP_BINOP; 6101 insn->size = size; 6102 insn->variant.dfp_binop.details = dfp_binop; 6103 6104 dfp_binop->tag = tag; 6105 dfp_binop->dst_hi = dst_hi; 6106 dfp_binop->dst_lo = dst_lo; 6107 dfp_binop->op2_hi = op2_hi; 6108 dfp_binop->op2_lo = op2_lo; 6109 dfp_binop->op3_hi = op3_hi; 6110 dfp_binop->op3_lo = op3_lo; 6111 dfp_binop->rounding_mode = rounding_mode; 6112 6113 return insn; 6114 } 6115 6116 6117 s390_insn * 6118 s390_insn_dfp128_unop(UChar size, s390_dfp_unop_t tag, HReg dst, 6119 HReg op_hi, HReg op_lo) 6120 { 6121 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6122 6123 /* destination is an 8 byte integer value */ 6124 vassert(size == 8); 6125 vassert(is_valid_fp128_regpair(op_hi, op_lo)); 6126 6127 insn->tag = S390_INSN_DFP_UNOP; 6128 insn->size = size; 6129 insn->variant.dfp_unop.tag = tag; 6130 insn->variant.dfp_unop.dst_hi = dst; 6131 insn->variant.dfp_unop.dst_lo = INVALID_HREG; 6132 insn->variant.dfp_unop.op_hi = op_hi; 6133 insn->variant.dfp_unop.op_lo = op_lo; 6134 6135 return insn; 6136 } 6137 6138 6139 s390_insn * 6140 s390_insn_dfp128_intop(UChar size, s390_dfp_intop_t tag, HReg dst_hi, 6141 HReg dst_lo, HReg op2, HReg op3_hi, HReg op3_lo) 6142 { 6143 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6144 6145 vassert(size == 16); 6146 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 6147 vassert(is_valid_fp128_regpair(op3_hi, op3_lo)); 6148 6149 insn->tag = S390_INSN_DFP_INTOP; 6150 insn->size = size; 6151 insn->variant.dfp_intop.tag = tag; 6152 insn->variant.dfp_intop.dst_hi = dst_hi; 6153 insn->variant.dfp_intop.dst_lo = dst_lo; 6154 insn->variant.dfp_intop.op2 = op2; 6155 insn->variant.dfp_intop.op3_hi = op3_hi; 6156 insn->variant.dfp_intop.op3_lo = op3_lo; 6157 6158 return insn; 6159 } 6160 6161 6162 s390_insn * 6163 s390_insn_dfp128_compare(UChar size, s390_dfp_cmp_t tag, HReg dst, HReg op1_hi, 6164 HReg op1_lo, HReg op2_hi, HReg op2_lo) 6165 { 6166 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6167 6168 vassert(size == 16); 6169 vassert(is_valid_fp128_regpair(op1_hi, op1_lo)); 6170 vassert(is_valid_fp128_regpair(op2_hi, op2_lo)); 6171 6172 insn->tag = S390_INSN_DFP_COMPARE; 6173 insn->size = size; 6174 insn->variant.dfp_compare.tag = tag; 6175 insn->variant.dfp_compare.dst = dst; 6176 insn->variant.dfp_compare.op1_hi = op1_hi; 6177 insn->variant.dfp_compare.op1_lo = op1_lo; 6178 insn->variant.dfp_compare.op2_hi = op2_hi; 6179 insn->variant.dfp_compare.op2_lo = op2_lo; 6180 6181 return insn; 6182 } 6183 6184 6185 static s390_insn * 6186 s390_insn_dfp128_convert(UChar size, s390_dfp_conv_t tag, HReg dst_hi, 6187 HReg dst_lo, HReg op_hi, HReg op_lo, 6188 s390_dfp_round_t rounding_mode) 6189 { 6190 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6191 6192 if (size == 16) { 6193 /* From smaller size to 16 bytes */ 6194 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 6195 vassert(hregIsInvalid(op_lo)); 6196 } else { 6197 /* From 16 bytes to smaller size */ 6198 vassert(is_valid_fp128_regpair(op_hi, op_lo)); 6199 } 6200 6201 insn->tag = S390_INSN_DFP_CONVERT; 6202 insn->size = size; 6203 insn->variant.dfp_convert.tag = tag; 6204 insn->variant.dfp_convert.dst_hi = dst_hi; 6205 insn->variant.dfp_convert.dst_lo = dst_lo; 6206 insn->variant.dfp_convert.op_hi = op_hi; 6207 insn->variant.dfp_convert.op_lo = op_lo; 6208 insn->variant.dfp_convert.rounding_mode = rounding_mode; 6209 6210 return insn; 6211 } 6212 6213 6214 s390_insn * 6215 s390_insn_dfp128_convert_to(UChar size, s390_dfp_conv_t tag, HReg dst_hi, 6216 HReg dst_lo, HReg op) 6217 { 6218 /* Conversion to dfp128 never requires a rounding mode. Provide default 6219 rounding mode. It will not be used when emitting insns. */ 6220 s390_dfp_round_t rounding_mode = S390_DFP_ROUND_NEAREST_EVEN_4; 6221 6222 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op, 6223 INVALID_HREG, rounding_mode); 6224 } 6225 6226 6227 s390_insn * 6228 s390_insn_dfp128_convert_from(UChar size, s390_dfp_conv_t tag, HReg dst_hi, 6229 HReg dst_lo, HReg op_hi, HReg op_lo, 6230 s390_dfp_round_t rounding_mode) 6231 { 6232 return s390_insn_dfp128_convert(size, tag, dst_hi, dst_lo, op_hi, op_lo, 6233 rounding_mode); 6234 } 6235 6236 6237 s390_insn * 6238 s390_insn_dfp128_reround(UChar size, HReg dst_hi, HReg dst_lo, HReg op2, 6239 HReg op3_hi, HReg op3_lo, 6240 s390_dfp_round_t rounding_mode) 6241 { 6242 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6243 6244 vassert(size == 16); 6245 vassert(is_valid_fp128_regpair(dst_hi, dst_lo)); 6246 vassert(is_valid_fp128_regpair(op3_hi, op3_lo)); 6247 6248 insn->tag = S390_INSN_DFP_REROUND; 6249 insn->size = size; 6250 insn->variant.dfp_reround.dst_hi = dst_hi; 6251 insn->variant.dfp_reround.dst_lo = dst_lo; 6252 insn->variant.dfp_reround.op2 = op2; 6253 insn->variant.dfp_reround.op3_hi = op3_hi; 6254 insn->variant.dfp_reround.op3_lo = op3_lo; 6255 insn->variant.dfp_reround.rounding_mode = rounding_mode; 6256 6257 return insn; 6258 } 6259 6260 6261 s390_insn * 6262 s390_insn_mfence(void) 6263 { 6264 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6265 6266 insn->tag = S390_INSN_MFENCE; 6267 insn->size = 0; /* not needed */ 6268 6269 return insn; 6270 } 6271 6272 6273 s390_insn * 6274 s390_insn_mimm(UChar size, s390_amode *dst, ULong value) 6275 { 6276 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6277 6278 /* This insn will be mapped to insns that require base register 6279 plus 12-bit displacement */ 6280 vassert(dst->tag == S390_AMODE_B12); 6281 6282 insn->tag = S390_INSN_MIMM; 6283 insn->size = size; 6284 insn->variant.mimm.dst = dst; 6285 insn->variant.mimm.value = value; 6286 6287 return insn; 6288 } 6289 6290 6291 s390_insn * 6292 s390_insn_madd(UChar size, s390_amode *dst, UChar delta, ULong value) 6293 { 6294 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6295 6296 vassert(size == 4 || size == 8); 6297 6298 /* This insn will be mapped to an ASI or AGSI so we can only allow base 6299 register plus 12-bit / 20-bit displacement. */ 6300 vassert(dst->tag == S390_AMODE_B12 || dst->tag == S390_AMODE_B20); 6301 6302 insn->tag = S390_INSN_MADD; 6303 insn->size = size; 6304 insn->variant.madd.dst = dst; 6305 insn->variant.madd.delta = delta; 6306 insn->variant.madd.value = value; 6307 6308 return insn; 6309 } 6310 6311 6312 s390_insn * 6313 s390_insn_set_fpc_bfprm(UChar size, HReg mode) 6314 { 6315 vassert(size == 4); 6316 6317 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6318 6319 insn->tag = S390_INSN_SET_FPC_BFPRM; 6320 insn->size = size; 6321 insn->variant.set_fpc_bfprm.mode = mode; 6322 6323 return insn; 6324 } 6325 6326 6327 s390_insn * 6328 s390_insn_set_fpc_dfprm(UChar size, HReg mode) 6329 { 6330 vassert(size == 4); 6331 6332 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6333 6334 insn->tag = S390_INSN_SET_FPC_DFPRM; 6335 insn->size = size; 6336 insn->variant.set_fpc_dfprm.mode = mode; 6337 6338 return insn; 6339 } 6340 6341 6342 s390_insn * 6343 s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA, 6344 Bool to_fast_entry) 6345 { 6346 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6347 6348 insn->tag = S390_INSN_XDIRECT; 6349 insn->size = 0; /* does not matter */ 6350 6351 insn->variant.xdirect.cond = cond; 6352 insn->variant.xdirect.dst = dst; 6353 insn->variant.xdirect.guest_IA = guest_IA; 6354 insn->variant.xdirect.to_fast_entry = to_fast_entry; 6355 6356 return insn; 6357 } 6358 6359 6360 s390_insn * 6361 s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA) 6362 { 6363 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6364 6365 insn->tag = S390_INSN_XINDIR; 6366 insn->size = 0; /* does not matter */ 6367 6368 insn->variant.xindir.cond = cond; 6369 insn->variant.xindir.dst = dst; 6370 insn->variant.xindir.guest_IA = guest_IA; 6371 6372 return insn; 6373 } 6374 6375 6376 s390_insn * 6377 s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA, 6378 IRJumpKind kind) 6379 { 6380 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6381 6382 insn->tag = S390_INSN_XASSISTED; 6383 insn->size = 0; /* does not matter */ 6384 6385 insn->variant.xassisted.cond = cond; 6386 insn->variant.xassisted.dst = dst; 6387 insn->variant.xassisted.guest_IA = guest_IA; 6388 insn->variant.xassisted.kind = kind; 6389 6390 return insn; 6391 } 6392 6393 6394 s390_insn * 6395 s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr) 6396 { 6397 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6398 6399 vassert(counter->tag == S390_AMODE_B12); 6400 vassert(fail_addr->tag == S390_AMODE_B12); 6401 6402 insn->tag = S390_INSN_EVCHECK; 6403 insn->size = 0; /* does not matter */ 6404 6405 insn->variant.evcheck.counter = counter; 6406 insn->variant.evcheck.fail_addr = fail_addr; 6407 6408 return insn; 6409 } 6410 6411 6412 s390_insn * 6413 s390_insn_profinc(void) 6414 { 6415 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 6416 6417 insn->tag = S390_INSN_PROFINC; 6418 insn->size = 0; /* does not matter */ 6419 6420 return insn; 6421 } 6422 6423 6424 /*---------------------------------------------------------------*/ 6425 /*--- Debug print ---*/ 6426 /*---------------------------------------------------------------*/ 6427 6428 static const HChar * 6429 s390_cc_as_string(s390_cc_t cc) 6430 { 6431 switch (cc) { 6432 case S390_CC_NEVER: return "never"; 6433 case S390_CC_OVFL: return "overflow"; 6434 case S390_CC_H: return "greater than"; /* A > B ; high */ 6435 case S390_CC_NLE: return "not low or equal"; 6436 case S390_CC_L: return "less than"; /* A < B ; low */ 6437 case S390_CC_NHE: return "not high or equal"; 6438 case S390_CC_LH: return "low or high"; 6439 case S390_CC_NE: return "not equal"; /* A != B ; not zero */ 6440 case S390_CC_E: return "equal"; /* A == B ; zero */ 6441 case S390_CC_NLH: return "not low or high"; 6442 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/ 6443 case S390_CC_NL: return "not low"; /* not low */ 6444 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */ 6445 case S390_CC_NH: return "not high"; 6446 case S390_CC_NO: return "not overflow"; 6447 case S390_CC_ALWAYS: return "always"; 6448 default: 6449 vpanic("s390_cc_as_string"); 6450 } 6451 } 6452 6453 6454 static const HChar * 6455 s390_jump_kind_as_string(IRJumpKind kind) 6456 { 6457 switch (kind) { 6458 case Ijk_Boring: return "Boring"; 6459 case Ijk_Call: return "Call"; 6460 case Ijk_Ret: return "Return"; 6461 case Ijk_ClientReq: return "ClientReq"; 6462 case Ijk_Yield: return "Yield"; 6463 case Ijk_EmWarn: return "EmWarn"; 6464 case Ijk_EmFail: return "EmFail"; 6465 case Ijk_NoDecode: return "NoDecode"; 6466 case Ijk_MapFail: return "MapFail"; 6467 case Ijk_InvalICache: return "Invalidate"; 6468 case Ijk_NoRedir: return "NoRedir"; 6469 case Ijk_SigTRAP: return "SigTRAP"; 6470 case Ijk_SigSEGV: return "SigSEGV"; 6471 case Ijk_SigBUS: return "SigBUS"; 6472 case Ijk_Sys_syscall: return "Sys_syscall"; 6473 default: 6474 vpanic("s390_jump_kind_as_string"); 6475 } 6476 } 6477 6478 6479 /* Helper function for writing out a V insn */ 6480 static void 6481 s390_sprintf(HChar *buf, const HChar *fmt, ...) 6482 { 6483 HChar *p; 6484 ULong value; 6485 va_list args; 6486 va_start(args, fmt); 6487 6488 p = buf; 6489 for ( ; *fmt; ++fmt) { 6490 Int c = *fmt; 6491 6492 if (c != '%') { 6493 *p++ = c; 6494 continue; 6495 } 6496 6497 c = *++fmt; /* next char */ 6498 switch (c) { 6499 case '%': 6500 *p++ = c; /* %% */ 6501 continue; 6502 6503 case 's': /* %s */ 6504 p += vex_sprintf(p, "%s", va_arg(args, HChar *)); 6505 continue; 6506 6507 case 'M': /* %M = mnemonic */ 6508 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *)); 6509 continue; 6510 6511 case 'R': /* %R = register */ 6512 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg))); 6513 continue; 6514 6515 case 'A': /* %A = amode */ 6516 p += vex_sprintf(p, "%s", 6517 s390_amode_as_string(va_arg(args, s390_amode *))); 6518 continue; 6519 6520 case 'G': /* %G = guest state @ offset */ 6521 p += vex_sprintf(p, "guest[%d]", va_arg(args, UInt)); 6522 continue; 6523 6524 case 'C': /* %C = condition code */ 6525 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t))); 6526 continue; 6527 6528 case 'J': /* &J = jump kind */ 6529 p += vex_sprintf(p, "%s", 6530 s390_jump_kind_as_string(va_arg(args, IRJumpKind))); 6531 continue; 6532 6533 case 'L': { /* %L = argument list in helper call*/ 6534 UInt i, num_args; 6535 6536 num_args = va_arg(args, UInt); 6537 6538 for (i = 0; i < num_args; ++i) { 6539 if (i != 0) p += vex_sprintf(p, ", "); 6540 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i)); 6541 } 6542 continue; 6543 } 6544 6545 case 'O': { /* %O = RMI operand */ 6546 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *); 6547 6548 switch (op->tag) { 6549 case S390_OPND_REG: 6550 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg)); 6551 continue; 6552 6553 case S390_OPND_AMODE: 6554 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am)); 6555 continue; 6556 6557 case S390_OPND_IMMEDIATE: 6558 value = op->variant.imm; 6559 goto print_value; 6560 6561 default: 6562 goto fail; 6563 } 6564 } 6565 6566 case 'I': /* %I = immediate value */ 6567 value = va_arg(args, ULong); 6568 goto print_value; 6569 6570 print_value: 6571 if ((Long)value < 0) 6572 p += vex_sprintf(p, "%lld", (Long)value); 6573 else if (value < 100) 6574 p += vex_sprintf(p, "%llu", value); 6575 else 6576 p += vex_sprintf(p, "0x%llx", value); 6577 continue; 6578 6579 default: 6580 goto fail; 6581 } 6582 } 6583 *p = '\0'; 6584 va_end(args); 6585 6586 return; 6587 6588 fail: vpanic("s390_printf"); 6589 } 6590 6591 6592 /* Decompile the given insn into a static buffer and return it */ 6593 const HChar * 6594 s390_insn_as_string(const s390_insn *insn) 6595 { 6596 static HChar buf[300]; 6597 const HChar *op; 6598 HChar *p; 6599 6600 buf[0] = '\0'; 6601 6602 switch (insn->tag) { 6603 case S390_INSN_LOAD: 6604 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst, 6605 insn->variant.load.src); 6606 break; 6607 6608 case S390_INSN_STORE: 6609 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src, 6610 insn->variant.store.dst); 6611 break; 6612 6613 case S390_INSN_MOVE: 6614 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst, 6615 insn->variant.move.src); 6616 break; 6617 6618 case S390_INSN_MEMCPY: 6619 s390_sprintf(buf, "%M %A,%A", "v-memcpy", insn->variant.memcpy.dst, 6620 insn->variant.memcpy.src); 6621 break; 6622 6623 case S390_INSN_COND_MOVE: 6624 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move", 6625 insn->variant.cond_move.cond, insn->variant.cond_move.dst, 6626 &insn->variant.cond_move.src); 6627 break; 6628 6629 case S390_INSN_LOAD_IMMEDIATE: 6630 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst, 6631 insn->variant.load_immediate.value); 6632 break; 6633 6634 case S390_INSN_ALU: 6635 switch (insn->variant.alu.tag) { 6636 case S390_ALU_ADD: op = "v-add"; break; 6637 case S390_ALU_SUB: op = "v-sub"; break; 6638 case S390_ALU_MUL: op = "v-mul"; break; 6639 case S390_ALU_AND: op = "v-and"; break; 6640 case S390_ALU_OR: op = "v-or"; break; 6641 case S390_ALU_XOR: op = "v-xor"; break; 6642 case S390_ALU_LSH: op = "v-lsh"; break; 6643 case S390_ALU_RSH: op = "v-rsh"; break; 6644 case S390_ALU_RSHA: op = "v-rsha"; break; 6645 default: goto fail; 6646 } 6647 s390_sprintf(buf, "%M %R,%O", op, insn->variant.alu.dst, /* also op1 */ 6648 &insn->variant.alu.op2); 6649 break; 6650 6651 case S390_INSN_SMUL: 6652 case S390_INSN_UMUL: 6653 if (insn->tag == S390_INSN_SMUL) { 6654 op = "v-muls"; 6655 } else { 6656 op = "v-mulu"; 6657 } 6658 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi, 6659 &insn->variant.mul.op2); 6660 break; 6661 6662 case S390_INSN_SDIV: 6663 case S390_INSN_UDIV: 6664 if (insn->tag == S390_INSN_SDIV) { 6665 op = "v-divs"; 6666 } else { 6667 op = "v-divu"; 6668 } 6669 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi, 6670 &insn->variant.div.op2); 6671 break; 6672 6673 case S390_INSN_DIVS: 6674 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1, 6675 &insn->variant.divs.op2); 6676 break; 6677 6678 case S390_INSN_CLZ: 6679 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits, 6680 &insn->variant.clz.src); 6681 break; 6682 6683 case S390_INSN_UNOP: 6684 switch (insn->variant.unop.tag) { 6685 case S390_ZERO_EXTEND_8: 6686 case S390_ZERO_EXTEND_16: 6687 case S390_ZERO_EXTEND_32: 6688 op = "v-zerox"; 6689 break; 6690 6691 case S390_SIGN_EXTEND_8: 6692 case S390_SIGN_EXTEND_16: 6693 case S390_SIGN_EXTEND_32: 6694 op = "v-signx"; 6695 break; 6696 6697 case S390_NEGATE: 6698 op = "v-neg"; 6699 break; 6700 6701 default: 6702 goto fail; 6703 } 6704 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst, 6705 &insn->variant.unop.src); 6706 break; 6707 6708 case S390_INSN_TEST: 6709 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src); 6710 break; 6711 6712 case S390_INSN_CC2BOOL: 6713 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst, 6714 insn->variant.cc2bool.cond); 6715 break; 6716 6717 case S390_INSN_CAS: 6718 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1, 6719 insn->variant.cas.op2, insn->variant.cas.op3, 6720 insn->variant.cas.old_mem); 6721 break; 6722 6723 case S390_INSN_CDAS: { 6724 s390_cdas *cdas = insn->variant.cdas.details; 6725 6726 s390_sprintf(buf, "%M %R,%R,%A,%R,%R,%R,%R", "v-cdas", 6727 cdas->op1_high, cdas->op1_low, cdas->op2, cdas->op3_high, 6728 cdas->op3_low, cdas->old_mem_high, cdas->old_mem_low); 6729 break; 6730 } 6731 6732 case S390_INSN_COMPARE: 6733 if (insn->variant.compare.signed_comparison) { 6734 op = "v-cmps"; 6735 } else { 6736 op = "v-cmpu"; 6737 } 6738 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1, 6739 &insn->variant.compare.src2); 6740 break; 6741 6742 case S390_INSN_HELPER_CALL: { 6743 s390_helper_call *helper_call = insn->variant.helper_call.details; 6744 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call", 6745 helper_call->cond, 6746 helper_call->name, 6747 helper_call->target, 6748 helper_call->num_args); 6749 return buf; /* avoid printing "size = ..." which is meaningless */ 6750 } 6751 6752 case S390_INSN_BFP_TRIOP: 6753 switch (insn->variant.bfp_triop.tag) { 6754 case S390_BFP_MADD: op = "v-fmadd"; break; 6755 case S390_BFP_MSUB: op = "v-fmsub"; break; 6756 default: goto fail; 6757 } 6758 s390_sprintf(buf, "%M %R,%R,%R", op, 6759 insn->variant.bfp_triop.dst /* op1 same as dst */, 6760 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3); 6761 break; 6762 6763 case S390_INSN_BFP_BINOP: 6764 switch (insn->variant.bfp_binop.tag) { 6765 case S390_BFP_ADD: op = "v-fadd"; break; 6766 case S390_BFP_SUB: op = "v-fsub"; break; 6767 case S390_BFP_MUL: op = "v-fmul"; break; 6768 case S390_BFP_DIV: op = "v-fdiv"; break; 6769 default: goto fail; 6770 } 6771 s390_sprintf(buf, "%M %R,%R", op, 6772 insn->variant.bfp_binop.dst_hi /* op1 same as dst */, 6773 insn->variant.bfp_binop.op2_hi); 6774 break; 6775 6776 case S390_INSN_BFP_COMPARE: 6777 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst, 6778 insn->variant.bfp_compare.op1_hi, 6779 insn->variant.bfp_compare.op2_hi); 6780 break; 6781 6782 case S390_INSN_BFP_UNOP: 6783 switch (insn->variant.bfp_unop.tag) { 6784 case S390_BFP_ABS: op = "v-fabs"; break; 6785 case S390_BFP_NABS: op = "v-fnabs"; break; 6786 case S390_BFP_NEG: op = "v-fneg"; break; 6787 case S390_BFP_SQRT: op = "v-fsqrt"; break; 6788 default: goto fail; 6789 } 6790 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst_hi, 6791 insn->variant.bfp_unop.op_hi); 6792 break; 6793 6794 case S390_INSN_BFP_CONVERT: 6795 switch (insn->variant.bfp_convert.tag) { 6796 case S390_BFP_I32_TO_F32: 6797 case S390_BFP_I32_TO_F64: 6798 case S390_BFP_I32_TO_F128: 6799 case S390_BFP_I64_TO_F32: 6800 case S390_BFP_I64_TO_F64: 6801 case S390_BFP_I64_TO_F128: op = "v-i2f"; break; 6802 case S390_BFP_U32_TO_F32: 6803 case S390_BFP_U32_TO_F64: 6804 case S390_BFP_U32_TO_F128: 6805 case S390_BFP_U64_TO_F32: 6806 case S390_BFP_U64_TO_F64: 6807 case S390_BFP_U64_TO_F128: op = "v-u2f"; break; 6808 case S390_BFP_F32_TO_I32: 6809 case S390_BFP_F32_TO_I64: 6810 case S390_BFP_F64_TO_I32: 6811 case S390_BFP_F64_TO_I64: 6812 case S390_BFP_F128_TO_I32: 6813 case S390_BFP_F128_TO_I64: op = "v-f2i"; break; 6814 case S390_BFP_F32_TO_U32: 6815 case S390_BFP_F32_TO_U64: 6816 case S390_BFP_F64_TO_U32: 6817 case S390_BFP_F64_TO_U64: 6818 case S390_BFP_F128_TO_U32: 6819 case S390_BFP_F128_TO_U64: op = "v-f2u"; break; 6820 case S390_BFP_F32_TO_F64: 6821 case S390_BFP_F32_TO_F128: 6822 case S390_BFP_F64_TO_F32: 6823 case S390_BFP_F64_TO_F128: 6824 case S390_BFP_F128_TO_F32: 6825 case S390_BFP_F128_TO_F64: op = "v-f2f"; break; 6826 default: goto fail; 6827 } 6828 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_convert.dst_hi, 6829 insn->variant.bfp_convert.op_hi); 6830 break; 6831 6832 case S390_INSN_DFP_BINOP: { 6833 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details; 6834 6835 switch (dfp_binop->tag) { 6836 case S390_DFP_ADD: op = "v-dadd"; break; 6837 case S390_DFP_SUB: op = "v-dsub"; break; 6838 case S390_DFP_MUL: op = "v-dmul"; break; 6839 case S390_DFP_DIV: op = "v-ddiv"; break; 6840 case S390_DFP_QUANTIZE: op = "v-dqua"; break; 6841 default: goto fail; 6842 } 6843 s390_sprintf(buf, "%M %R,%R,%R", op, dfp_binop->dst_hi, 6844 dfp_binop->op2_hi, dfp_binop->op3_hi); 6845 break; 6846 } 6847 6848 case S390_INSN_DFP_UNOP: 6849 switch (insn->variant.dfp_unop.tag) { 6850 case S390_DFP_EXTRACT_EXP_D64: 6851 case S390_DFP_EXTRACT_EXP_D128: op = "v-d2exp"; break; 6852 case S390_DFP_EXTRACT_SIG_D64: 6853 case S390_DFP_EXTRACT_SIG_D128: op = "v-d2sig"; break; 6854 default: goto fail; 6855 } 6856 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_unop.dst_hi, 6857 insn->variant.dfp_unop.op_hi); 6858 break; 6859 6860 case S390_INSN_DFP_INTOP: 6861 switch (insn->variant.dfp_intop.tag) { 6862 case S390_DFP_SHIFT_LEFT: op = "v-dshl"; break; 6863 case S390_DFP_SHIFT_RIGHT: op = "v-dshr"; break; 6864 case S390_DFP_INSERT_EXP: op = "v-diexp"; break; 6865 default: goto fail; 6866 } 6867 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_intop.dst_hi, 6868 insn->variant.dfp_intop.op2, 6869 insn->variant.dfp_intop.op3_hi); 6870 break; 6871 6872 case S390_INSN_DFP_COMPARE: 6873 switch (insn->variant.dfp_compare.tag) { 6874 case S390_DFP_COMPARE: op = "v-dcmp"; break; 6875 case S390_DFP_COMPARE_EXP: op = "v-dcmpexp"; break; 6876 default: goto fail; 6877 } 6878 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.dfp_compare.dst, 6879 insn->variant.dfp_compare.op1_hi, 6880 insn->variant.dfp_compare.op2_hi); 6881 break; 6882 6883 case S390_INSN_DFP_CONVERT: 6884 switch (insn->variant.dfp_convert.tag) { 6885 case S390_DFP_D32_TO_D64: 6886 case S390_DFP_D64_TO_D32: 6887 case S390_DFP_D64_TO_D128: 6888 case S390_DFP_D128_TO_D64: op = "v-d2d"; break; 6889 case S390_DFP_I32_TO_D64: 6890 case S390_DFP_I32_TO_D128: 6891 case S390_DFP_I64_TO_D64: 6892 case S390_DFP_I64_TO_D128: op = "v-i2d"; break; 6893 case S390_DFP_U32_TO_D64: 6894 case S390_DFP_U32_TO_D128: 6895 case S390_DFP_U64_TO_D64: 6896 case S390_DFP_U64_TO_D128: op = "v-u2d"; break; 6897 case S390_DFP_D64_TO_I32: 6898 case S390_DFP_D128_TO_I32: 6899 case S390_DFP_D64_TO_I64: 6900 case S390_DFP_D128_TO_I64: op = "v-d2i"; break; 6901 case S390_DFP_D64_TO_U32: 6902 case S390_DFP_D64_TO_U64: 6903 case S390_DFP_D128_TO_U32: 6904 case S390_DFP_D128_TO_U64: op = "v-d2u"; break; 6905 default: goto fail; 6906 } 6907 s390_sprintf(buf, "%M %R,%R", op, insn->variant.dfp_convert.dst_hi, 6908 insn->variant.dfp_convert.op_hi); 6909 break; 6910 6911 case S390_INSN_DFP_REROUND: 6912 s390_sprintf(buf, "%M %R,%R,%R", "v-drrnd", 6913 insn->variant.dfp_reround.dst_hi, 6914 insn->variant.dfp_reround.op2, 6915 insn->variant.dfp_reround.op3_hi); 6916 break; 6917 6918 case S390_INSN_FP_CONVERT: { 6919 s390_fp_convert *fp_convert = insn->variant.fp_convert.details; 6920 6921 switch (fp_convert->tag) { 6922 case S390_FP_F32_TO_D32: 6923 case S390_FP_F32_TO_D64: 6924 case S390_FP_F32_TO_D128: 6925 case S390_FP_F64_TO_D32: 6926 case S390_FP_F64_TO_D64: 6927 case S390_FP_F64_TO_D128: 6928 case S390_FP_F128_TO_D32: 6929 case S390_FP_F128_TO_D64: 6930 case S390_FP_F128_TO_D128: op = "v-f2d"; break; 6931 case S390_FP_D32_TO_F32: 6932 case S390_FP_D32_TO_F64: 6933 case S390_FP_D32_TO_F128: 6934 case S390_FP_D64_TO_F32: 6935 case S390_FP_D64_TO_F64: 6936 case S390_FP_D64_TO_F128: 6937 case S390_FP_D128_TO_F32: 6938 case S390_FP_D128_TO_F64: 6939 case S390_FP_D128_TO_F128: op = "v-d2f"; break; 6940 default: goto fail; 6941 } 6942 s390_sprintf(buf, "%M %R,%R", op, fp_convert->dst_hi, 6943 fp_convert->op_hi); 6944 break; 6945 } 6946 6947 case S390_INSN_MFENCE: 6948 s390_sprintf(buf, "%M", "v-mfence"); 6949 return buf; /* avoid printing "size = ..." which is meaningless */ 6950 6951 case S390_INSN_MIMM: 6952 s390_sprintf(buf, "%M %A,%I", "v-mimm", insn->variant.mimm.dst, 6953 insn->variant.mimm.value); 6954 break; 6955 6956 case S390_INSN_MADD: 6957 s390_sprintf(buf, "%M %A += %I (= %I)", "v-madd", 6958 insn->variant.madd.dst, 6959 (Long)(Char)insn->variant.madd.delta, 6960 insn->variant.madd.value); 6961 break; 6962 6963 case S390_INSN_SET_FPC_BFPRM: 6964 s390_sprintf(buf, "%M %R", "v-set-fpc-bfprm", 6965 insn->variant.set_fpc_bfprm.mode); 6966 break; 6967 6968 case S390_INSN_SET_FPC_DFPRM: 6969 s390_sprintf(buf, "%M %R", "v-set-fpc-dfprm", 6970 insn->variant.set_fpc_dfprm.mode); 6971 break; 6972 6973 case S390_INSN_EVCHECK: 6974 s390_sprintf(buf, "%M counter = %A, fail-addr = %A", "v-evcheck", 6975 insn->variant.evcheck.counter, 6976 insn->variant.evcheck.fail_addr); 6977 return buf; /* avoid printing "size = ..." which is meaningless */ 6978 6979 case S390_INSN_PROFINC: 6980 s390_sprintf(buf, "%M", "v-profinc"); 6981 return buf; /* avoid printing "size = ..." which is meaningless */ 6982 6983 case S390_INSN_XDIRECT: 6984 s390_sprintf(buf, "%M if (%C) %A = %I %s", "v-xdirect", 6985 insn->variant.xdirect.cond, 6986 insn->variant.xdirect.guest_IA, 6987 insn->variant.xdirect.dst, 6988 insn->variant.xdirect.to_fast_entry ? "fast" : "slow"); 6989 return buf; /* avoid printing "size = ..." which is meaningless */ 6990 6991 case S390_INSN_XINDIR: 6992 s390_sprintf(buf, "%M if (%C) %A = %R", "v-xindir", 6993 insn->variant.xindir.cond, 6994 insn->variant.xindir.guest_IA, 6995 insn->variant.xindir.dst); 6996 return buf; /* avoid printing "size = ..." which is meaningless */ 6997 6998 case S390_INSN_XASSISTED: 6999 s390_sprintf(buf, "%M if (%C) %J %A = %R", "v-xassisted", 7000 insn->variant.xassisted.cond, 7001 insn->variant.xassisted.kind, 7002 insn->variant.xassisted.guest_IA, 7003 insn->variant.xassisted.dst); 7004 return buf; /* avoid printing "size = ..." which is meaningless */ 7005 7006 default: goto fail; 7007 } 7008 7009 /* Write out how many bytes are involved in the operation */ 7010 7011 { 7012 UInt len, i; 7013 7014 for (p = buf; *p; ++p) 7015 continue; 7016 7017 len = p - buf; 7018 7019 if (len < 32) { 7020 for (i = len; i < 32; ++i) 7021 p += vex_sprintf(p, " "); 7022 } else { 7023 p += vex_sprintf(p, "\t"); 7024 } 7025 } 7026 7027 /* Special cases first */ 7028 switch (insn->tag) { 7029 case S390_INSN_UNOP: 7030 switch (insn->variant.unop.tag) { 7031 case S390_SIGN_EXTEND_8: 7032 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common; 7033 case S390_SIGN_EXTEND_16: 7034 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common; 7035 case S390_SIGN_EXTEND_32: 7036 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common; 7037 default: 7038 goto common; 7039 } 7040 7041 case S390_INSN_BFP_CONVERT: 7042 switch (insn->variant.bfp_convert.tag) { 7043 case S390_BFP_I32_TO_F32: 7044 case S390_BFP_I32_TO_F64: 7045 case S390_BFP_I32_TO_F128: 7046 case S390_BFP_U32_TO_F32: 7047 case S390_BFP_U32_TO_F64: 7048 case S390_BFP_U32_TO_F128: 7049 case S390_BFP_F32_TO_I32: 7050 case S390_BFP_F32_TO_I64: 7051 case S390_BFP_F32_TO_U32: 7052 case S390_BFP_F32_TO_U64: 7053 case S390_BFP_F32_TO_F64: 7054 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common; 7055 case S390_BFP_I64_TO_F32: 7056 case S390_BFP_I64_TO_F64: 7057 case S390_BFP_I64_TO_F128: 7058 case S390_BFP_U64_TO_F32: 7059 case S390_BFP_U64_TO_F64: 7060 case S390_BFP_U64_TO_F128: 7061 case S390_BFP_F64_TO_I32: 7062 case S390_BFP_F64_TO_I64: 7063 case S390_BFP_F64_TO_U32: 7064 case S390_BFP_F64_TO_U64: 7065 case S390_BFP_F64_TO_F32: 7066 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common; 7067 case S390_BFP_F128_TO_I32: 7068 case S390_BFP_F128_TO_I64: 7069 case S390_BFP_F128_TO_U32: 7070 case S390_BFP_F128_TO_U64: 7071 case S390_BFP_F128_TO_F32: 7072 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common; 7073 default: 7074 goto common; 7075 } 7076 7077 case S390_INSN_DFP_CONVERT: 7078 switch (insn->variant.dfp_convert.tag) { 7079 case S390_DFP_D32_TO_D64: 7080 case S390_DFP_I32_TO_D64: 7081 case S390_DFP_I32_TO_D128: 7082 case S390_DFP_U32_TO_D64: 7083 case S390_DFP_U32_TO_D128: p += vex_sprintf(p, "4 -> "); goto common; 7084 case S390_DFP_D64_TO_D32: 7085 case S390_DFP_D64_TO_D128: 7086 case S390_DFP_I64_TO_D64: 7087 case S390_DFP_I64_TO_D128: 7088 case S390_DFP_U64_TO_D64: 7089 case S390_DFP_U64_TO_D128: 7090 case S390_DFP_D64_TO_I32: 7091 case S390_DFP_D64_TO_I64: 7092 case S390_DFP_D64_TO_U32: 7093 case S390_DFP_D64_TO_U64: p += vex_sprintf(p, "8 -> "); goto common; 7094 case S390_DFP_D128_TO_D64: 7095 case S390_DFP_D128_TO_I32: 7096 case S390_DFP_D128_TO_I64: 7097 case S390_DFP_D128_TO_U32: 7098 case S390_DFP_D128_TO_U64: p += vex_sprintf(p, "16 -> "); goto common; 7099 default: 7100 goto common; 7101 } 7102 7103 case S390_INSN_FP_CONVERT: { 7104 s390_fp_convert *fp_convert = insn->variant.fp_convert.details; 7105 7106 switch (fp_convert->tag) { 7107 case S390_FP_F32_TO_D32: 7108 case S390_FP_F32_TO_D64: 7109 case S390_FP_F32_TO_D128: 7110 case S390_FP_D32_TO_F32: 7111 case S390_FP_D32_TO_F64: 7112 case S390_FP_D32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common; 7113 case S390_FP_F64_TO_D32: 7114 case S390_FP_F64_TO_D64: 7115 case S390_FP_F64_TO_D128: 7116 case S390_FP_D64_TO_F32: 7117 case S390_FP_D64_TO_F64: 7118 case S390_FP_D64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common; 7119 case S390_FP_F128_TO_D32: 7120 case S390_FP_F128_TO_D64: 7121 case S390_FP_F128_TO_D128: 7122 case S390_FP_D128_TO_F32: 7123 case S390_FP_D128_TO_F64: 7124 case S390_FP_D128_TO_F128: p += vex_sprintf(p, "16 -> "); goto common; 7125 default: 7126 goto common; 7127 } 7128 } 7129 7130 default: 7131 goto common; 7132 } 7133 7134 /* Common case */ 7135 common: 7136 vex_sprintf(p, "%u bytes", (UInt)insn->size); 7137 7138 return buf; 7139 7140 fail: vpanic("s390_insn_as_string"); 7141 } 7142 7143 7144 7145 /* Load NUM bytes from memory into register REG using addressing mode AM. */ 7146 static UChar * 7147 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am) 7148 { 7149 UInt b = hregNumber(am->b); 7150 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */ 7151 UInt d = am->d; 7152 7153 switch (am->tag) { 7154 case S390_AMODE_B12: 7155 case S390_AMODE_BX12: 7156 switch (num) { 7157 case 1: return s390_emit_IC(p, reg, x, b, d); 7158 case 2: return s390_emit_LH(p, reg, x, b, d); 7159 case 4: return s390_emit_L(p, reg, x, b, d); 7160 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d)); 7161 default: goto fail; 7162 } 7163 break; 7164 7165 case S390_AMODE_B20: 7166 case S390_AMODE_BX20: 7167 switch (num) { 7168 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d)); 7169 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d)); 7170 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d)); 7171 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d)); 7172 default: goto fail; 7173 } 7174 break; 7175 7176 default: goto fail; 7177 } 7178 7179 fail: 7180 vpanic("s390_emit_load_mem"); 7181 } 7182 7183 7184 /* Load condition code into register REG */ 7185 static UChar * 7186 s390_emit_load_cc(UChar *p, UChar reg) 7187 { 7188 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */ 7189 p = s390_emit_IPM(p, reg, reg); 7190 /* Shift 28 bits to the right --> [0,1,2,3] */ 7191 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */ 7192 } 7193 7194 7195 /*---------------------------------------------------------------*/ 7196 /*--- Code generation ---*/ 7197 /*---------------------------------------------------------------*/ 7198 7199 /* Do not load more bytes than requested. */ 7200 static UChar * 7201 s390_insn_load_emit(UChar *buf, const s390_insn *insn) 7202 { 7203 UInt r, x, b, d; 7204 const s390_amode *src; 7205 7206 src = insn->variant.load.src; 7207 7208 r = hregNumber(insn->variant.load.dst); 7209 7210 if (hregClass(insn->variant.load.dst) == HRcFlt64) { 7211 b = hregNumber(src->b); 7212 x = hregNumber(src->x); /* 0 for B12 and B20 */ 7213 d = src->d; 7214 7215 switch (insn->size) { 7216 7217 case 4: 7218 switch (src->tag) { 7219 case S390_AMODE_B12: 7220 case S390_AMODE_BX12: 7221 return s390_emit_LE(buf, r, x, b, d); 7222 7223 case S390_AMODE_B20: 7224 case S390_AMODE_BX20: 7225 return s390_emit_LEY(buf, r, x, b, DISP20(d)); 7226 } 7227 break; 7228 7229 case 8: 7230 switch (src->tag) { 7231 case S390_AMODE_B12: 7232 case S390_AMODE_BX12: 7233 return s390_emit_LD(buf, r, x, b, d); 7234 7235 case S390_AMODE_B20: 7236 case S390_AMODE_BX20: 7237 return s390_emit_LDY(buf, r, x, b, DISP20(d)); 7238 } 7239 break; 7240 } 7241 vpanic("s390_insn_load_emit"); 7242 } 7243 7244 /* Integer stuff */ 7245 return s390_emit_load_mem(buf, insn->size, r, src); 7246 } 7247 7248 7249 static UChar * 7250 s390_insn_store_emit(UChar *buf, const s390_insn *insn) 7251 { 7252 UInt r, x, b, d; 7253 const s390_amode *dst; 7254 7255 dst = insn->variant.store.dst; 7256 7257 r = hregNumber(insn->variant.store.src); 7258 b = hregNumber(dst->b); 7259 x = hregNumber(dst->x); /* 0 for B12 and B20 */ 7260 d = dst->d; 7261 7262 if (hregClass(insn->variant.store.src) == HRcFlt64) { 7263 switch (insn->size) { 7264 7265 case 4: 7266 switch (dst->tag) { 7267 case S390_AMODE_B12: 7268 case S390_AMODE_BX12: 7269 return s390_emit_STE(buf, r, x, b, d); 7270 7271 case S390_AMODE_B20: 7272 case S390_AMODE_BX20: 7273 return s390_emit_STEY(buf, r, x, b, DISP20(d)); 7274 } 7275 break; 7276 7277 case 8: 7278 switch (dst->tag) { 7279 case S390_AMODE_B12: 7280 case S390_AMODE_BX12: 7281 return s390_emit_STD(buf, r, x, b, d); 7282 7283 case S390_AMODE_B20: 7284 case S390_AMODE_BX20: 7285 return s390_emit_STDY(buf, r, x, b, DISP20(d)); 7286 } 7287 break; 7288 } 7289 vpanic("s390_insn_store_emit"); 7290 } 7291 7292 /* Integer stuff */ 7293 switch (insn->size) { 7294 case 1: 7295 switch (dst->tag) { 7296 case S390_AMODE_B12: 7297 case S390_AMODE_BX12: 7298 return s390_emit_STC(buf, r, x, b, d); 7299 7300 case S390_AMODE_B20: 7301 case S390_AMODE_BX20: 7302 return s390_emit_STCY(buf, r, x, b, DISP20(d)); 7303 } 7304 break; 7305 7306 case 2: 7307 switch (dst->tag) { 7308 case S390_AMODE_B12: 7309 case S390_AMODE_BX12: 7310 return s390_emit_STH(buf, r, x, b, d); 7311 7312 case S390_AMODE_B20: 7313 case S390_AMODE_BX20: 7314 return s390_emit_STHY(buf, r, x, b, DISP20(d)); 7315 } 7316 break; 7317 7318 case 4: 7319 switch (dst->tag) { 7320 case S390_AMODE_B12: 7321 case S390_AMODE_BX12: 7322 return s390_emit_ST(buf, r, x, b, d); 7323 7324 case S390_AMODE_B20: 7325 case S390_AMODE_BX20: 7326 return s390_emit_STY(buf, r, x, b, DISP20(d)); 7327 } 7328 break; 7329 7330 case 8: 7331 return s390_emit_STG(buf, r, x, b, DISP20(d)); 7332 7333 default: 7334 break; 7335 } 7336 7337 vpanic("s390_insn_store_emit"); 7338 } 7339 7340 7341 static UChar * 7342 s390_insn_move_emit(UChar *buf, const s390_insn *insn) 7343 { 7344 UInt dst, src; 7345 HRegClass dst_class, src_class; 7346 7347 dst = hregNumber(insn->variant.move.dst); 7348 src = hregNumber(insn->variant.move.src); 7349 7350 dst_class = hregClass(insn->variant.move.dst); 7351 src_class = hregClass(insn->variant.move.src); 7352 7353 if (dst_class == src_class) { 7354 if (dst_class == HRcInt64) 7355 return s390_emit_LGR(buf, dst, src); 7356 if (dst_class == HRcFlt64) 7357 return s390_emit_LDR(buf, dst, src); 7358 } else { 7359 if (dst_class == HRcFlt64 && src_class == HRcInt64) { 7360 if (insn->size == 4) { 7361 buf = s390_emit_SLLG(buf, R0, src, 0, DISP20(32)); /* r0 = src << 32 */ 7362 return s390_emit_LDGRw(buf, dst, R0); 7363 } else { 7364 return s390_emit_LDGRw(buf, dst, src); 7365 } 7366 } 7367 if (dst_class == HRcInt64 && src_class == HRcFlt64) { 7368 if (insn->size == 4) { 7369 buf = s390_emit_LGDRw(buf, dst, src); 7370 return s390_emit_SRLG(buf, dst, dst, 0, DISP20(32)); /* dst >>= 32 */ 7371 } else { 7372 return s390_emit_LGDRw(buf, dst, src); 7373 } 7374 } 7375 /* A move between floating point registers and general purpose 7376 registers of different size should never occur and indicates 7377 an error elsewhere. */ 7378 } 7379 7380 vpanic("s390_insn_move_emit"); 7381 } 7382 7383 7384 static UChar * 7385 s390_insn_memcpy_emit(UChar *buf, const s390_insn *insn) 7386 { 7387 s390_amode *dst = insn->variant.memcpy.dst; 7388 s390_amode *src = insn->variant.memcpy.src; 7389 7390 return s390_emit_MVC(buf, insn->size - 1, hregNumber(dst->b), dst->d, 7391 hregNumber(src->b), src->d); 7392 } 7393 7394 7395 static UChar * 7396 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn) 7397 { 7398 UInt r; 7399 ULong value = insn->variant.load_immediate.value; 7400 7401 r = hregNumber(insn->variant.load_immediate.dst); 7402 7403 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) { 7404 vassert(value == 0); 7405 switch (insn->size) { 7406 case 4: return s390_emit_LZER(buf, r, value); 7407 case 8: return s390_emit_LZDR(buf, r, value); 7408 } 7409 vpanic("s390_insn_load_immediate_emit"); 7410 } 7411 7412 switch (insn->size) { 7413 case 1: 7414 case 2: 7415 /* Load the immediate values as a 4 byte value. That does not hurt as 7416 those extra bytes will not be looked at. Fall through .... */ 7417 case 4: 7418 return s390_emit_load_32imm(buf, r, value); 7419 7420 case 8: 7421 return s390_emit_load_64imm(buf, r, value); 7422 } 7423 7424 vpanic("s390_insn_load_immediate_emit"); 7425 } 7426 7427 7428 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands. 7429 So we simply perform a 4-byte operation. Doing so uses possibly undefined 7430 bits and produces an undefined result in those extra bit positions. But 7431 upstream does not look at those positions, so this is OK. */ 7432 static UChar * 7433 s390_insn_alu_emit(UChar *buf, const s390_insn *insn) 7434 { 7435 s390_opnd_RMI op2; 7436 UInt dst; 7437 7438 dst = hregNumber(insn->variant.alu.dst); 7439 op2 = insn->variant.alu.op2; 7440 7441 /* Second operand is in a register */ 7442 if (op2.tag == S390_OPND_REG) { 7443 UInt r2 = hregNumber(op2.variant.reg); 7444 7445 switch (insn->size) { 7446 case 1: 7447 case 2: 7448 case 4: 7449 switch (insn->variant.alu.tag) { 7450 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2); 7451 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2); 7452 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2); 7453 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2); 7454 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2); 7455 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2); 7456 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0); 7457 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0); 7458 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0); 7459 } 7460 goto fail; 7461 7462 case 8: 7463 switch (insn->variant.alu.tag) { 7464 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2); 7465 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2); 7466 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2); 7467 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2); 7468 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2); 7469 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2); 7470 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0)); 7471 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0)); 7472 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0)); 7473 } 7474 goto fail; 7475 } 7476 goto fail; 7477 } 7478 7479 /* 2nd operand is in memory */ 7480 if (op2.tag == S390_OPND_AMODE) { 7481 UInt b, x, d; 7482 const s390_amode *src = op2.variant.am; 7483 7484 b = hregNumber(src->b); 7485 x = hregNumber(src->x); /* 0 for B12 and B20 */ 7486 d = src->d; 7487 7488 /* Shift operands are special here as there are no opcodes that 7489 allow a memory operand. So we first load the 2nd operand into 7490 some register. R0 is used to save restore the contents of the 7491 chosen register.. */ 7492 7493 if (insn->variant.alu.tag == S390_ALU_LSH || 7494 insn->variant.alu.tag == S390_ALU_RSH || 7495 insn->variant.alu.tag == S390_ALU_RSHA) { 7496 UInt b2; 7497 7498 /* Choose a register (other than DST or R0) into which to stick the 7499 shift amount. The following works because r15 is reserved and 7500 thusly dst != 15. */ 7501 vassert(dst != 15); /* extra paranoia */ 7502 b2 = (dst + 1) % 16; 7503 7504 buf = s390_emit_LGR(buf, R0, b2); /* save */ 7505 7506 /* Loading SRC to B2 does not modify R0. */ 7507 buf = s390_emit_load_mem(buf, insn->size, b2, src); 7508 7509 if (insn->size == 8) { 7510 switch (insn->variant.alu.tag) { 7511 case S390_ALU_LSH: 7512 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0)); 7513 break; 7514 case S390_ALU_RSH: 7515 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0)); 7516 break; 7517 case S390_ALU_RSHA: 7518 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0)); 7519 break; 7520 default: /* unreachable */ 7521 goto fail; 7522 } 7523 } else { 7524 switch (insn->variant.alu.tag) { 7525 case S390_ALU_LSH: 7526 buf = s390_emit_SLL(buf, dst, b2, 0); 7527 break; 7528 case S390_ALU_RSH: 7529 buf = s390_emit_SRL(buf, dst, b2, 0); 7530 break; 7531 case S390_ALU_RSHA: 7532 buf = s390_emit_SRA(buf, dst, b2, 0); 7533 break; 7534 default: /* unreachable */ 7535 goto fail; 7536 } 7537 } 7538 return s390_emit_LGR(buf, b2, R0); /* restore */ 7539 } 7540 7541 switch (insn->size) { 7542 case 1: 7543 /* Move the byte from memory into scratch register r0 */ 7544 buf = s390_emit_load_mem(buf, 1, R0, src); 7545 7546 switch (insn->variant.alu.tag) { 7547 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0); 7548 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0); 7549 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0); 7550 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0); 7551 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0); 7552 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0); 7553 case S390_ALU_LSH: 7554 case S390_ALU_RSH: 7555 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7556 } 7557 goto fail; 7558 7559 case 2: 7560 switch (src->tag) { 7561 case S390_AMODE_B12: 7562 case S390_AMODE_BX12: 7563 switch (insn->variant.alu.tag) { 7564 case S390_ALU_ADD: 7565 return s390_emit_AH(buf, dst, x, b, d); 7566 7567 case S390_ALU_SUB: 7568 return s390_emit_SH(buf, dst, x, b, d); 7569 7570 case S390_ALU_MUL: 7571 return s390_emit_MH(buf, dst, x, b, d); 7572 7573 /* For bitwise operations: Move two bytes from memory into scratch 7574 register r0; then perform operation */ 7575 case S390_ALU_AND: 7576 buf = s390_emit_LH(buf, R0, x, b, d); 7577 return s390_emit_NR(buf, dst, R0); 7578 7579 case S390_ALU_OR: 7580 buf = s390_emit_LH(buf, R0, x, b, d); 7581 return s390_emit_OR(buf, dst, R0); 7582 7583 case S390_ALU_XOR: 7584 buf = s390_emit_LH(buf, R0, x, b, d); 7585 return s390_emit_XR(buf, dst, R0); 7586 7587 case S390_ALU_LSH: 7588 case S390_ALU_RSH: 7589 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7590 } 7591 goto fail; 7592 7593 case S390_AMODE_B20: 7594 case S390_AMODE_BX20: 7595 switch (insn->variant.alu.tag) { 7596 case S390_ALU_ADD: 7597 return s390_emit_AHY(buf, dst, x, b, DISP20(d)); 7598 7599 case S390_ALU_SUB: 7600 return s390_emit_SHY(buf, dst, x, b, DISP20(d)); 7601 7602 case S390_ALU_MUL: 7603 return s390_emit_MHYw(buf, dst, x, b, DISP20(d)); 7604 7605 /* For bitwise operations: Move two bytes from memory into scratch 7606 register r0; then perform operation */ 7607 case S390_ALU_AND: 7608 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 7609 return s390_emit_NR(buf, dst, R0); 7610 7611 case S390_ALU_OR: 7612 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 7613 return s390_emit_OR(buf, dst, R0); 7614 7615 case S390_ALU_XOR: 7616 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 7617 return s390_emit_XR(buf, dst, R0); 7618 7619 case S390_ALU_LSH: 7620 case S390_ALU_RSH: 7621 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7622 } 7623 goto fail; 7624 } 7625 goto fail; 7626 7627 case 4: 7628 switch (src->tag) { 7629 case S390_AMODE_B12: 7630 case S390_AMODE_BX12: 7631 switch (insn->variant.alu.tag) { 7632 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d); 7633 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d); 7634 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d); 7635 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d); 7636 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d); 7637 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d); 7638 case S390_ALU_LSH: 7639 case S390_ALU_RSH: 7640 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7641 } 7642 goto fail; 7643 7644 case S390_AMODE_B20: 7645 case S390_AMODE_BX20: 7646 switch (insn->variant.alu.tag) { 7647 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d)); 7648 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d)); 7649 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d)); 7650 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d)); 7651 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d)); 7652 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d)); 7653 case S390_ALU_LSH: 7654 case S390_ALU_RSH: 7655 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7656 } 7657 goto fail; 7658 } 7659 goto fail; 7660 7661 case 8: 7662 switch (insn->variant.alu.tag) { 7663 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d)); 7664 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d)); 7665 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d)); 7666 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d)); 7667 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d)); 7668 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d)); 7669 case S390_ALU_LSH: 7670 case S390_ALU_RSH: 7671 case S390_ALU_RSHA: ; /* avoid GCC warning */ 7672 } 7673 goto fail; 7674 } 7675 goto fail; 7676 } 7677 7678 /* 2nd operand is an immediate value */ 7679 if (op2.tag == S390_OPND_IMMEDIATE) { 7680 ULong value; 7681 7682 /* No masking of the value is required as it is not sign extended */ 7683 value = op2.variant.imm; 7684 7685 switch (insn->size) { 7686 case 1: 7687 case 2: 7688 /* There is no 1-byte opcode. Do the computation in 7689 2 bytes. The extra byte will be ignored. */ 7690 switch (insn->variant.alu.tag) { 7691 case S390_ALU_ADD: 7692 return s390_emit_AHI(buf, dst, value); 7693 7694 case S390_ALU_SUB: 7695 return s390_emit_SLFIw(buf, dst, value); 7696 7697 case S390_ALU_MUL: 7698 return s390_emit_MHI(buf, dst, value); 7699 7700 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value); 7701 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value); 7702 case S390_ALU_XOR: 7703 /* There is no XILL instruction. Load the immediate value into 7704 R0 and combine with the destination register. */ 7705 buf = s390_emit_LHI(buf, R0, value); 7706 return s390_emit_XR(buf, dst, R0); 7707 7708 case S390_ALU_LSH: 7709 return s390_emit_SLL(buf, dst, 0, value); 7710 7711 case S390_ALU_RSH: 7712 return s390_emit_SRL(buf, dst, 0, value); 7713 7714 case S390_ALU_RSHA: 7715 return s390_emit_SRA(buf, dst, 0, value); 7716 } 7717 goto fail; 7718 7719 case 4: 7720 switch (insn->variant.alu.tag) { 7721 case S390_ALU_ADD: 7722 if (uint_fits_signed_16bit(value)) { 7723 return s390_emit_AHI(buf, dst, value); 7724 } 7725 return s390_emit_AFIw(buf, dst, value); 7726 7727 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value); 7728 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value); 7729 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value); 7730 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value); 7731 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value); 7732 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value); 7733 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value); 7734 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value); 7735 } 7736 goto fail; 7737 7738 case 8: 7739 switch (insn->variant.alu.tag) { 7740 case S390_ALU_ADD: 7741 if (ulong_fits_signed_16bit(value)) { 7742 return s390_emit_AGHI(buf, dst, value); 7743 } 7744 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) { 7745 return s390_emit_AGFI(buf, dst, value); 7746 } 7747 /* Load constant into R0 then add */ 7748 buf = s390_emit_load_64imm(buf, R0, value); 7749 return s390_emit_AGR(buf, dst, R0); 7750 7751 case S390_ALU_SUB: 7752 if (ulong_fits_unsigned_32bit(value)) { 7753 return s390_emit_SLGFIw(buf, dst, value); 7754 } 7755 /* Load value into R0; then subtract from destination reg */ 7756 buf = s390_emit_load_64imm(buf, R0, value); 7757 return s390_emit_SGR(buf, dst, R0); 7758 7759 case S390_ALU_MUL: 7760 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) { 7761 return s390_emit_MSGFI(buf, dst, value); 7762 } 7763 /* Load constant into R0 then add */ 7764 buf = s390_emit_load_64imm(buf, R0, value); 7765 return s390_emit_MSGR(buf, dst, R0); 7766 7767 /* Do it in two steps: upper half [0:31] and lower half [32:63] */ 7768 case S390_ALU_AND: 7769 if (s390_host_has_eimm) { 7770 buf = s390_emit_NIHF(buf, dst, value >> 32); 7771 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF); 7772 } 7773 /* Load value into R0; then combine with destination reg */ 7774 buf = s390_emit_load_64imm(buf, R0, value); 7775 return s390_emit_NGR(buf, dst, R0); 7776 7777 case S390_ALU_OR: 7778 if (s390_host_has_eimm) { 7779 buf = s390_emit_OIHF(buf, dst, value >> 32); 7780 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF); 7781 } 7782 /* Load value into R0; then combine with destination reg */ 7783 buf = s390_emit_load_64imm(buf, R0, value); 7784 return s390_emit_OGR(buf, dst, R0); 7785 7786 case S390_ALU_XOR: 7787 if (s390_host_has_eimm) { 7788 buf = s390_emit_XIHF(buf, dst, value >> 32); 7789 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF); 7790 } 7791 /* Load value into R0; then combine with destination reg */ 7792 buf = s390_emit_load_64imm(buf, R0, value); 7793 return s390_emit_XGR(buf, dst, R0); 7794 7795 /* No special considerations for long displacement here. Only the six 7796 least significant bits of VALUE will be taken; all other bits are 7797 ignored. So the DH2 bits are irrelevant and do not influence the 7798 shift operation, independent of whether long-displacement is available 7799 or not. */ 7800 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value)); 7801 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value)); 7802 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value)); 7803 } 7804 goto fail; 7805 } 7806 goto fail; 7807 } 7808 7809 fail: 7810 vpanic("s390_insn_alu_emit"); 7811 } 7812 7813 7814 static UChar * 7815 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size, 7816 Bool sign_extend) 7817 { 7818 s390_opnd_RMI opnd = insn->variant.unop.src; 7819 7820 switch (opnd.tag) { 7821 case S390_OPND_REG: { 7822 UChar r1 = hregNumber(insn->variant.unop.dst); 7823 UChar r2 = hregNumber(opnd.variant.reg); 7824 7825 switch (from_size) { 7826 case 1: 7827 /* Widening to a half-word is implemented like widening to a word 7828 because the upper half-word will not be looked at. */ 7829 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */ 7830 if (sign_extend) 7831 return s390_emit_LBRw(buf, r1, r2); 7832 else 7833 return s390_emit_LLCRw(buf, r1, r2); 7834 } 7835 if (insn->size == 8) { /* 8 --> 64 */ 7836 if (sign_extend) 7837 return s390_emit_LGBRw(buf, r1, r2); 7838 else 7839 return s390_emit_LLGCRw(buf, r1, r2); 7840 } 7841 goto fail; 7842 7843 case 2: 7844 if (insn->size == 4) { /* 16 --> 32 */ 7845 if (sign_extend) 7846 return s390_emit_LHRw(buf, r1, r2); 7847 else 7848 return s390_emit_LLHRw(buf, r1, r2); 7849 } 7850 if (insn->size == 8) { /* 16 --> 64 */ 7851 if (sign_extend) 7852 return s390_emit_LGHRw(buf, r1, r2); 7853 else 7854 return s390_emit_LLGHRw(buf, r1, r2); 7855 } 7856 goto fail; 7857 7858 case 4: 7859 if (insn->size == 8) { /* 32 --> 64 */ 7860 if (sign_extend) 7861 return s390_emit_LGFR(buf, r1, r2); 7862 else 7863 return s390_emit_LLGFR(buf, r1, r2); 7864 } 7865 goto fail; 7866 7867 default: /* unexpected "from" size */ 7868 goto fail; 7869 } 7870 } 7871 7872 case S390_OPND_AMODE: { 7873 UChar r1 = hregNumber(insn->variant.unop.dst); 7874 const s390_amode *src = opnd.variant.am; 7875 UChar b = hregNumber(src->b); 7876 UChar x = hregNumber(src->x); 7877 Int d = src->d; 7878 7879 switch (from_size) { 7880 case 1: 7881 if (insn->size == 4 || insn->size == 2) { 7882 if (sign_extend) 7883 return s390_emit_LBw(buf, r1, x, b, DISP20(d)); 7884 else 7885 return s390_emit_LLCw(buf, r1, x, b, DISP20(d)); 7886 } 7887 if (insn->size == 8) { 7888 if (sign_extend) 7889 return s390_emit_LGBw(buf, r1, x, b, DISP20(d)); 7890 else 7891 return s390_emit_LLGC(buf, r1, x, b, DISP20(d)); 7892 } 7893 goto fail; 7894 7895 case 2: 7896 if (insn->size == 4) { /* 16 --> 32 */ 7897 if (sign_extend == 0) 7898 return s390_emit_LLHw(buf, r1, x, b, DISP20(d)); 7899 7900 switch (src->tag) { 7901 case S390_AMODE_B12: 7902 case S390_AMODE_BX12: 7903 return s390_emit_LH(buf, r1, x, b, d); 7904 7905 case S390_AMODE_B20: 7906 case S390_AMODE_BX20: 7907 return s390_emit_LHY(buf, r1, x, b, DISP20(d)); 7908 } 7909 goto fail; 7910 } 7911 if (insn->size == 8) { /* 16 --> 64 */ 7912 if (sign_extend) 7913 return s390_emit_LGH(buf, r1, x, b, DISP20(d)); 7914 else 7915 return s390_emit_LLGH(buf, r1, x, b, DISP20(d)); 7916 } 7917 goto fail; 7918 7919 case 4: 7920 if (insn->size == 8) { /* 32 --> 64 */ 7921 if (sign_extend) 7922 return s390_emit_LGF(buf, r1, x, b, DISP20(d)); 7923 else 7924 return s390_emit_LLGF(buf, r1, x, b, DISP20(d)); 7925 } 7926 goto fail; 7927 7928 default: /* unexpected "from" size */ 7929 goto fail; 7930 } 7931 } 7932 7933 case S390_OPND_IMMEDIATE: { 7934 UChar r1 = hregNumber(insn->variant.unop.dst); 7935 ULong value = opnd.variant.imm; 7936 7937 switch (from_size) { 7938 case 1: 7939 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */ 7940 if (sign_extend) { 7941 /* host can do the sign extension to 16-bit; LHI does the rest */ 7942 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value); 7943 } else { 7944 return s390_emit_LHI(buf, r1, value); 7945 } 7946 } 7947 if (insn->size == 8) { /* 8 --> 64 */ 7948 if (sign_extend) { 7949 /* host can do the sign extension to 16-bit; LGHI does the rest */ 7950 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value); 7951 } else { 7952 return s390_emit_LGHI(buf, r1, value); 7953 } 7954 } 7955 goto fail; 7956 7957 case 2: 7958 if (insn->size == 4) { /* 16 --> 32 */ 7959 return s390_emit_LHI(buf, r1, value); 7960 } 7961 if (insn->size == 8) { /* 16 --> 64 */ 7962 if (sign_extend) 7963 return s390_emit_LGHI(buf, r1, value); 7964 else 7965 return s390_emit_LLILL(buf, r1, value); 7966 } 7967 goto fail; 7968 7969 case 4: 7970 if (insn->size == 8) { /* 32 --> 64 */ 7971 if (sign_extend) 7972 return s390_emit_LGFIw(buf, r1, value); 7973 else 7974 return s390_emit_LLILFw(buf, r1, value); 7975 } 7976 goto fail; 7977 7978 default: /* unexpected "from" size */ 7979 goto fail; 7980 } 7981 } 7982 } 7983 7984 fail: 7985 vpanic("s390_widen_emit"); 7986 } 7987 7988 7989 static UChar * 7990 s390_negate_emit(UChar *buf, const s390_insn *insn) 7991 { 7992 s390_opnd_RMI opnd; 7993 7994 opnd = insn->variant.unop.src; 7995 7996 switch (opnd.tag) { 7997 case S390_OPND_REG: { 7998 UChar r1 = hregNumber(insn->variant.unop.dst); 7999 UChar r2 = hregNumber(opnd.variant.reg); 8000 8001 switch (insn->size) { 8002 case 1: 8003 case 2: 8004 case 4: 8005 return s390_emit_LCR(buf, r1, r2); 8006 8007 case 8: 8008 return s390_emit_LCGR(buf, r1, r2); 8009 8010 default: 8011 goto fail; 8012 } 8013 } 8014 8015 case S390_OPND_AMODE: { 8016 UChar r1 = hregNumber(insn->variant.unop.dst); 8017 8018 /* Load bytes into scratch register R0, then negate */ 8019 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am); 8020 8021 switch (insn->size) { 8022 case 1: 8023 case 2: 8024 case 4: 8025 return s390_emit_LCR(buf, r1, R0); 8026 8027 case 8: 8028 return s390_emit_LCGR(buf, r1, R0); 8029 8030 default: 8031 goto fail; 8032 } 8033 } 8034 8035 case S390_OPND_IMMEDIATE: { 8036 UChar r1 = hregNumber(insn->variant.unop.dst); 8037 ULong value = opnd.variant.imm; 8038 8039 value = ~value + 1; /* two's complement */ 8040 8041 switch (insn->size) { 8042 case 1: 8043 case 2: 8044 /* Load the immediate values as a 4 byte value. That does not hurt as 8045 those extra bytes will not be looked at. Fall through .... */ 8046 case 4: 8047 return s390_emit_load_32imm(buf, r1, value); 8048 8049 case 8: 8050 return s390_emit_load_64imm(buf, r1, value); 8051 8052 default: 8053 goto fail; 8054 } 8055 } 8056 } 8057 8058 fail: 8059 vpanic("s390_negate_emit"); 8060 } 8061 8062 8063 static UChar * 8064 s390_insn_unop_emit(UChar *buf, const s390_insn *insn) 8065 { 8066 switch (insn->variant.unop.tag) { 8067 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0); 8068 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0); 8069 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0); 8070 8071 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1); 8072 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1); 8073 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1); 8074 8075 case S390_NEGATE: return s390_negate_emit(buf, insn); 8076 } 8077 8078 vpanic("s390_insn_unop_emit"); 8079 } 8080 8081 8082 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte 8083 comparisons will have been converted to 4-byte comparisons in 8084 s390_isel_cc and should not occur here. */ 8085 static UChar * 8086 s390_insn_test_emit(UChar *buf, const s390_insn *insn) 8087 { 8088 s390_opnd_RMI opnd; 8089 8090 opnd = insn->variant.test.src; 8091 8092 switch (opnd.tag) { 8093 case S390_OPND_REG: { 8094 UInt reg = hregNumber(opnd.variant.reg); 8095 8096 switch (insn->size) { 8097 case 4: 8098 return s390_emit_LTR(buf, reg, reg); 8099 8100 case 8: 8101 return s390_emit_LTGR(buf, reg, reg); 8102 8103 default: 8104 goto fail; 8105 } 8106 } 8107 8108 case S390_OPND_AMODE: { 8109 const s390_amode *am = opnd.variant.am; 8110 UChar b = hregNumber(am->b); 8111 UChar x = hregNumber(am->x); 8112 Int d = am->d; 8113 8114 switch (insn->size) { 8115 case 4: 8116 return s390_emit_LTw(buf, R0, x, b, DISP20(d)); 8117 8118 case 8: 8119 return s390_emit_LTGw(buf, R0, x, b, DISP20(d)); 8120 8121 default: 8122 goto fail; 8123 } 8124 } 8125 8126 case S390_OPND_IMMEDIATE: { 8127 ULong value = opnd.variant.imm; 8128 8129 switch (insn->size) { 8130 case 4: 8131 buf = s390_emit_load_32imm(buf, R0, value); 8132 return s390_emit_LTR(buf, R0, R0); 8133 8134 case 8: 8135 buf = s390_emit_load_64imm(buf, R0, value); 8136 return s390_emit_LTGR(buf, R0, R0); 8137 8138 default: 8139 goto fail; 8140 } 8141 } 8142 8143 default: 8144 goto fail; 8145 } 8146 8147 fail: 8148 vpanic("s390_insn_test_emit"); 8149 } 8150 8151 8152 static UChar * 8153 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn) 8154 { 8155 UChar r1 = hregNumber(insn->variant.cc2bool.dst); 8156 s390_cc_t cond = insn->variant.cc2bool.cond; 8157 8158 /* Make the destination register be 1 or 0, depending on whether 8159 the relevant condition holds. A 64-bit value is computed. */ 8160 if (cond == S390_CC_ALWAYS) 8161 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */ 8162 8163 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */ 8164 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */ 8165 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */ 8166 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */ 8167 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */ 8168 8169 return buf; 8170 } 8171 8172 8173 /* Only 4-byte and 8-byte operands are handled. */ 8174 static UChar * 8175 s390_insn_cas_emit(UChar *buf, const s390_insn *insn) 8176 { 8177 UChar r1, r3, b, old; 8178 Int d; 8179 s390_amode *am; 8180 8181 r1 = hregNumber(insn->variant.cas.op1); /* expected value */ 8182 r3 = hregNumber(insn->variant.cas.op3); 8183 old= hregNumber(insn->variant.cas.old_mem); 8184 am = insn->variant.cas.op2; 8185 b = hregNumber(am->b); 8186 d = am->d; 8187 8188 switch (insn->size) { 8189 case 4: 8190 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */ 8191 buf = s390_emit_LR(buf, R0, r1); 8192 if (am->tag == S390_AMODE_B12) 8193 buf = s390_emit_CS(buf, R0, r3, b, d); 8194 else 8195 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d)); 8196 /* Now copy R0 which has the old memory value to OLD */ 8197 return s390_emit_LR(buf, old, R0); 8198 8199 case 8: 8200 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */ 8201 buf = s390_emit_LGR(buf, R0, r1); 8202 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d)); 8203 /* Now copy R0 which has the old memory value to OLD */ 8204 return s390_emit_LGR(buf, old, R0); 8205 8206 default: 8207 goto fail; 8208 } 8209 8210 fail: 8211 vpanic("s390_insn_cas_emit"); 8212 } 8213 8214 8215 /* Only 4-byte and 8-byte operands are handled. */ 8216 static UChar * 8217 s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) 8218 { 8219 UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch; 8220 Int d; 8221 s390_amode *am; 8222 s390_cdas *cdas = insn->variant.cdas.details; 8223 8224 r1 = hregNumber(cdas->op1_high); /* expected value */ 8225 r1p1 = hregNumber(cdas->op1_low); /* expected value */ 8226 r3 = hregNumber(cdas->op3_high); 8227 /* r3p1 = hregNumber(cdas->op3_low); */ /* unused */ 8228 old_high = hregNumber(cdas->old_mem_high); 8229 old_low = hregNumber(cdas->old_mem_low); 8230 scratch = hregNumber(cdas->scratch); 8231 am = cdas->op2; 8232 b = hregNumber(am->b); 8233 d = am->d; 8234 8235 vassert(scratch == 1); 8236 8237 switch (insn->size) { 8238 case 4: 8239 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch 8240 and let CDS/CDSY clobber it */ 8241 buf = s390_emit_LR(buf, R0, r1); 8242 buf = s390_emit_LR(buf, scratch, r1p1); 8243 8244 if (am->tag == S390_AMODE_B12) 8245 buf = s390_emit_CDS(buf, R0, r3, b, d); 8246 else 8247 buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d)); 8248 8249 /* Now copy R0,scratch which has the old memory value to OLD */ 8250 buf = s390_emit_LR(buf, old_high, R0); 8251 buf = s390_emit_LR(buf, old_low, scratch); 8252 return buf; 8253 8254 case 8: 8255 /* r1, r1+1 must not be overwritten. So copy them to R0,scratch 8256 and let CDSG clobber it */ 8257 buf = s390_emit_LGR(buf, R0, r1); 8258 buf = s390_emit_LGR(buf, scratch, r1p1); 8259 8260 buf = s390_emit_CDSG(buf, R0, r3, b, DISP20(d)); 8261 8262 /* Now copy R0,scratch which has the old memory value to OLD */ 8263 buf = s390_emit_LGR(buf, old_high, R0); 8264 buf = s390_emit_LGR(buf, old_low, scratch); 8265 return buf; 8266 8267 default: 8268 goto fail; 8269 } 8270 8271 fail: 8272 vpanic("s390_insn_cdas_emit"); 8273 } 8274 8275 8276 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte 8277 comparisons will have been converted to 4-byte comparisons in 8278 s390_isel_cc and should not occur here. */ 8279 static UChar * 8280 s390_insn_compare_emit(UChar *buf, const s390_insn *insn) 8281 { 8282 s390_opnd_RMI op2; 8283 HReg op1; 8284 Bool signed_comparison; 8285 8286 op1 = insn->variant.compare.src1; 8287 op2 = insn->variant.compare.src2; 8288 signed_comparison = insn->variant.compare.signed_comparison; 8289 8290 switch (op2.tag) { 8291 case S390_OPND_REG: { 8292 UInt r1 = hregNumber(op1); 8293 UInt r2 = hregNumber(op2.variant.reg); 8294 8295 switch (insn->size) { 8296 case 4: 8297 if (signed_comparison) 8298 return s390_emit_CR(buf, r1, r2); 8299 else 8300 return s390_emit_CLR(buf, r1, r2); 8301 8302 case 8: 8303 if (signed_comparison) 8304 return s390_emit_CGR(buf, r1, r2); 8305 else 8306 return s390_emit_CLGR(buf, r1, r2); 8307 8308 default: 8309 goto fail; 8310 } 8311 } 8312 8313 case S390_OPND_AMODE: { 8314 UChar r1 = hregNumber(op1); 8315 const s390_amode *am = op2.variant.am; 8316 UChar b = hregNumber(am->b); 8317 UChar x = hregNumber(am->x); 8318 Int d = am->d; 8319 8320 switch (insn->size) { 8321 case 4: 8322 switch (am->tag) { 8323 case S390_AMODE_B12: 8324 case S390_AMODE_BX12: 8325 if (signed_comparison) 8326 return s390_emit_C(buf, r1, x, b, d); 8327 else 8328 return s390_emit_CL(buf, r1, x, b, d); 8329 8330 case S390_AMODE_B20: 8331 case S390_AMODE_BX20: 8332 if (signed_comparison) 8333 return s390_emit_CY(buf, r1, x, b, DISP20(d)); 8334 else 8335 return s390_emit_CLY(buf, r1, x, b, DISP20(d)); 8336 } 8337 goto fail; 8338 8339 case 8: 8340 if (signed_comparison) 8341 return s390_emit_CG(buf, r1, x, b, DISP20(d)); 8342 else 8343 return s390_emit_CLG(buf, r1, x, b, DISP20(d)); 8344 8345 default: 8346 goto fail; 8347 } 8348 } 8349 8350 case S390_OPND_IMMEDIATE: { 8351 UChar r1 = hregNumber(op1); 8352 ULong value = op2.variant.imm; 8353 8354 switch (insn->size) { 8355 case 4: 8356 if (signed_comparison) 8357 return s390_emit_CFIw(buf, r1, value); 8358 else 8359 return s390_emit_CLFIw(buf, r1, value); 8360 8361 case 8: 8362 if (s390_host_has_eimm) { 8363 if (signed_comparison) { 8364 if (ulong_fits_signed_32bit(value)) 8365 return s390_emit_CGFI(buf, r1, value); 8366 } else { 8367 if (ulong_fits_unsigned_32bit(value)) 8368 return s390_emit_CLGFI(buf, r1, value); 8369 } 8370 } 8371 buf = s390_emit_load_64imm(buf, R0, value); 8372 if (signed_comparison) 8373 return s390_emit_CGR(buf, r1, R0); 8374 else 8375 return s390_emit_CLGR(buf, r1, R0); 8376 8377 default: 8378 goto fail; 8379 } 8380 } 8381 8382 default: 8383 goto fail; 8384 } 8385 8386 fail: 8387 vpanic("s390_insn_compare_emit"); 8388 } 8389 8390 8391 static UChar * 8392 s390_insn_mul_emit(UChar *buf, const s390_insn *insn) 8393 { 8394 s390_opnd_RMI op2; 8395 UChar r1; 8396 Bool signed_multiply; 8397 8398 /* The register number identifying the register pair */ 8399 r1 = hregNumber(insn->variant.mul.dst_hi); 8400 8401 op2 = insn->variant.mul.op2; 8402 signed_multiply = insn->tag == S390_INSN_SMUL; 8403 8404 switch (op2.tag) { 8405 case S390_OPND_REG: { 8406 UInt r2 = hregNumber(op2.variant.reg); 8407 8408 switch (insn->size) { 8409 case 1: 8410 case 2: 8411 case 4: 8412 if (signed_multiply) 8413 return s390_emit_MR(buf, r1, r2); 8414 else 8415 return s390_emit_MLR(buf, r1, r2); 8416 8417 case 8: 8418 if (signed_multiply) 8419 vpanic("s390_insn_mul_emit"); 8420 else 8421 return s390_emit_MLGR(buf, r1, r2); 8422 8423 default: 8424 goto fail; 8425 } 8426 } 8427 8428 case S390_OPND_AMODE: { 8429 const s390_amode *am = op2.variant.am; 8430 UChar b = hregNumber(am->b); 8431 UChar x = hregNumber(am->x); 8432 Int d = am->d; 8433 8434 switch (insn->size) { 8435 case 1: 8436 case 2: 8437 /* Load bytes into scratch register R0, then multiply */ 8438 buf = s390_emit_load_mem(buf, insn->size, R0, am); 8439 if (signed_multiply) 8440 return s390_emit_MR(buf, r1, R0); 8441 else 8442 return s390_emit_MLR(buf, r1, R0); 8443 8444 case 4: 8445 switch (am->tag) { 8446 case S390_AMODE_B12: 8447 case S390_AMODE_BX12: 8448 if (signed_multiply) 8449 return s390_emit_M(buf, r1, x, b, d); 8450 else 8451 return s390_emit_ML(buf, r1, x, b, DISP20(d)); 8452 8453 case S390_AMODE_B20: 8454 case S390_AMODE_BX20: 8455 if (signed_multiply) 8456 return s390_emit_MFYw(buf, r1, x, b, DISP20(d)); 8457 else 8458 return s390_emit_ML(buf, r1, x, b, DISP20(d)); 8459 } 8460 goto fail; 8461 8462 case 8: 8463 if (signed_multiply) 8464 vpanic("s390_insn_mul_emit"); 8465 else 8466 return s390_emit_MLG(buf, r1, x, b, DISP20(d)); 8467 8468 default: 8469 goto fail; 8470 } 8471 } 8472 8473 case S390_OPND_IMMEDIATE: { 8474 ULong value = op2.variant.imm; 8475 8476 switch (insn->size) { 8477 case 1: 8478 case 2: 8479 case 4: 8480 buf = s390_emit_load_32imm(buf, R0, value); 8481 if (signed_multiply) 8482 return s390_emit_MR(buf, r1, R0); 8483 else 8484 return s390_emit_MLR(buf, r1, R0); 8485 8486 case 8: 8487 buf = s390_emit_load_64imm(buf, R0, value); 8488 if (signed_multiply) 8489 vpanic("s390_insn_mul_emit"); 8490 else 8491 return s390_emit_MLGR(buf, r1, R0); 8492 8493 default: 8494 goto fail; 8495 } 8496 } 8497 8498 default: 8499 goto fail; 8500 } 8501 8502 fail: 8503 vpanic("s390_insn_mul_emit"); 8504 } 8505 8506 8507 static UChar * 8508 s390_insn_div_emit(UChar *buf, const s390_insn *insn) 8509 { 8510 s390_opnd_RMI op2; 8511 UChar r1; 8512 Bool signed_divide; 8513 8514 r1 = hregNumber(insn->variant.div.op1_hi); 8515 op2 = insn->variant.div.op2; 8516 signed_divide = insn->tag == S390_INSN_SDIV; 8517 8518 switch (op2.tag) { 8519 case S390_OPND_REG: { 8520 UInt r2 = hregNumber(op2.variant.reg); 8521 8522 switch (insn->size) { 8523 case 4: 8524 if (signed_divide) 8525 return s390_emit_DR(buf, r1, r2); 8526 else 8527 return s390_emit_DLR(buf, r1, r2); 8528 8529 case 8: 8530 if (signed_divide) 8531 vpanic("s390_insn_div_emit"); 8532 else 8533 return s390_emit_DLGR(buf, r1, r2); 8534 8535 default: 8536 goto fail; 8537 } 8538 } 8539 8540 case S390_OPND_AMODE: { 8541 const s390_amode *am = op2.variant.am; 8542 UChar b = hregNumber(am->b); 8543 UChar x = hregNumber(am->x); 8544 Int d = am->d; 8545 8546 switch (insn->size) { 8547 case 4: 8548 switch (am->tag) { 8549 case S390_AMODE_B12: 8550 case S390_AMODE_BX12: 8551 if (signed_divide) 8552 return s390_emit_D(buf, r1, x, b, d); 8553 else 8554 return s390_emit_DL(buf, r1, x, b, DISP20(d)); 8555 8556 case S390_AMODE_B20: 8557 case S390_AMODE_BX20: 8558 if (signed_divide) { 8559 buf = s390_emit_LY(buf, R0, x, b, DISP20(d)); 8560 return s390_emit_DR(buf, r1, R0); 8561 } else 8562 return s390_emit_DL(buf, r1, x, b, DISP20(d)); 8563 } 8564 goto fail; 8565 8566 case 8: 8567 if (signed_divide) 8568 vpanic("s390_insn_div_emit"); 8569 else 8570 return s390_emit_DLG(buf, r1, x, b, DISP20(d)); 8571 8572 default: 8573 goto fail; 8574 } 8575 } 8576 8577 case S390_OPND_IMMEDIATE: { 8578 ULong value = op2.variant.imm; 8579 8580 switch (insn->size) { 8581 case 4: 8582 buf = s390_emit_load_32imm(buf, R0, value); 8583 if (signed_divide) 8584 return s390_emit_DR(buf, r1, R0); 8585 else 8586 return s390_emit_DLR(buf, r1, R0); 8587 8588 case 8: 8589 buf = s390_emit_load_64imm(buf, R0, value); 8590 if (signed_divide) 8591 vpanic("s390_insn_div_emit"); 8592 else 8593 return s390_emit_DLGR(buf, r1, R0); 8594 8595 default: 8596 goto fail; 8597 } 8598 } 8599 8600 default: 8601 goto fail; 8602 } 8603 8604 fail: 8605 vpanic("s390_insn_div_emit"); 8606 } 8607 8608 8609 static UChar * 8610 s390_insn_divs_emit(UChar *buf, const s390_insn *insn) 8611 { 8612 s390_opnd_RMI op2; 8613 UChar r1; 8614 8615 r1 = hregNumber(insn->variant.divs.rem); 8616 op2 = insn->variant.divs.op2; 8617 8618 switch (op2.tag) { 8619 case S390_OPND_REG: { 8620 UInt r2 = hregNumber(op2.variant.reg); 8621 8622 return s390_emit_DSGR(buf, r1, r2); 8623 } 8624 8625 case S390_OPND_AMODE: { 8626 const s390_amode *am = op2.variant.am; 8627 UChar b = hregNumber(am->b); 8628 UChar x = hregNumber(am->x); 8629 Int d = am->d; 8630 8631 return s390_emit_DSG(buf, r1, x, b, DISP20(d)); 8632 } 8633 8634 case S390_OPND_IMMEDIATE: { 8635 ULong value = op2.variant.imm; 8636 8637 buf = s390_emit_load_64imm(buf, R0, value); 8638 return s390_emit_DSGR(buf, r1, R0); 8639 } 8640 8641 default: 8642 goto fail; 8643 } 8644 8645 fail: 8646 vpanic("s390_insn_divs_emit"); 8647 } 8648 8649 8650 static UChar * 8651 s390_insn_clz_emit(UChar *buf, const s390_insn *insn) 8652 { 8653 s390_opnd_RMI src; 8654 UChar r1, r1p1, r2, *p; 8655 8656 r1 = hregNumber(insn->variant.clz.num_bits); 8657 r1p1 = hregNumber(insn->variant.clz.clobber); 8658 8659 vassert((r1 & 0x1) == 0); 8660 vassert(r1p1 == r1 + 1); 8661 8662 p = buf; 8663 src = insn->variant.clz.src; 8664 8665 /* Get operand and move it to r2 */ 8666 switch (src.tag) { 8667 case S390_OPND_REG: 8668 r2 = hregNumber(src.variant.reg); 8669 break; 8670 8671 case S390_OPND_AMODE: { 8672 const s390_amode *am = src.variant.am; 8673 UChar b = hregNumber(am->b); 8674 UChar x = hregNumber(am->x); 8675 Int d = am->d; 8676 8677 p = s390_emit_LG(p, R0, x, b, DISP20(d)); 8678 r2 = R0; 8679 break; 8680 } 8681 8682 case S390_OPND_IMMEDIATE: { 8683 ULong value = src.variant.imm; 8684 8685 p = s390_emit_load_64imm(p, R0, value); 8686 r2 = R0; 8687 break; 8688 } 8689 8690 default: 8691 goto fail; 8692 } 8693 8694 /* Use FLOGR if you can */ 8695 if (s390_host_has_eimm) { 8696 return s390_emit_FLOGR(p, r1, r2); 8697 } 8698 8699 /* 8700 r0 = r2; 8701 r1 = 64; 8702 while (r0 != 0) { 8703 r1 -= 1; 8704 r0 >>= 1; 8705 } 8706 */ 8707 p = s390_emit_LTGR(p, R0, r2); 8708 p = s390_emit_LLILL(p, r1, 64); 8709 8710 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */ 8711 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */ 8712 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */ 8713 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */ 8714 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */ 8715 (UShort)(-(4 + 6 + 4) / 2)); 8716 return p; 8717 8718 fail: 8719 vpanic("s390_insn_clz_emit"); 8720 } 8721 8722 8723 /* Returns a value == BUF to denote failure, != BUF to denote success. */ 8724 static UChar * 8725 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn) 8726 { 8727 s390_cc_t cond; 8728 ULong target; 8729 UChar *ptmp = buf; 8730 UChar *bufIN = buf; 8731 s390_helper_call *helper_call = insn->variant.helper_call.details; 8732 8733 cond = helper_call->cond; 8734 target = helper_call->target; 8735 8736 if (cond != S390_CC_ALWAYS 8737 && helper_call->rloc.pri != RLPri_None) { 8738 /* The call might not happen (it isn't unconditional) and it 8739 returns a result. In this case we will need to generate a 8740 control flow diamond to put 0x555..555 in the return 8741 register(s) in the case where the call doesn't happen. If 8742 this ever becomes necessary, maybe copy code from the ARM 8743 equivalent. Until that day, just give up. */ 8744 return bufIN; /* To denote failure. */ 8745 } 8746 8747 if (cond != S390_CC_ALWAYS) { 8748 /* So we have something like this 8749 if (cond) call X; 8750 Y: ... 8751 We convert this into 8752 if (! cond) goto Y; // BRC opcode; 4 bytes 8753 call X; 8754 Y: 8755 */ 8756 /* 4 bytes (a BRC insn) to be filled in here */ 8757 buf += 4; 8758 } 8759 8760 /* Load the target address into a register, that 8761 (a) is not used for passing parameters to the helper and 8762 (b) can be clobbered by the callee 8763 (c) is not special to the BASR insn 8764 r1 is the only choice. 8765 Also, need to arrange for the return address be put into the 8766 link-register */ 8767 buf = s390_emit_load_64imm(buf, 1, target); 8768 8769 /* Stash away the client's FPC register because the helper might change it. */ 8770 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C); 8771 8772 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper 8773 8774 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC 8775 S390_OFFSET_SAVED_FPC_C); 8776 8777 if (cond != S390_CC_ALWAYS) { 8778 Int delta = buf - ptmp; 8779 8780 delta >>= 1; /* immediate constant is #half-words */ 8781 vassert(delta > 0 && delta < (1 << 16)); 8782 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 8783 } 8784 8785 return buf; 8786 } 8787 8788 8789 static UChar * 8790 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn) 8791 { 8792 HReg dst; 8793 s390_opnd_RMI src; 8794 s390_cc_t cond; 8795 UChar *p, *ptmp = 0; /* avoid compiler warnings */ 8796 8797 cond = insn->variant.cond_move.cond; 8798 dst = insn->variant.cond_move.dst; 8799 src = insn->variant.cond_move.src; 8800 8801 if (cond == S390_CC_NEVER) return buf; 8802 8803 p = buf; 8804 8805 if (s390_host_has_lsc) { 8806 /* LOCx is not the preferred way to implement an unconditional load. */ 8807 if (cond != S390_CC_ALWAYS) goto use_branch_insn; 8808 8809 switch (src.tag) { 8810 case S390_OPND_REG: 8811 return s390_emit_LOCGR(p, cond, hregNumber(dst), 8812 hregNumber(src.variant.reg)); 8813 8814 case S390_OPND_AMODE: { 8815 const s390_amode *am = src.variant.am; 8816 8817 /* We cannot use LOCx for loads less than 4 bytes. In that case 8818 load into R0 and then use LOCGR. Do the same if the amode uses 8819 an index register. */ 8820 if (insn->size < 4 || 8821 am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) { 8822 p = s390_emit_load_mem(p, insn->size, R0, am); 8823 p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0); 8824 return p; 8825 } 8826 8827 vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20); 8828 vassert(insn->size == 4 || insn->size == 8); 8829 8830 UInt b = hregNumber(am->b); 8831 UInt d = am->d; 8832 8833 if (insn->size == 4) { 8834 return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d)); 8835 } 8836 return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d)); 8837 } 8838 8839 case S390_OPND_IMMEDIATE: { 8840 ULong value = src.variant.imm; 8841 8842 /* Load value into R0, then use LOCGR */ 8843 if (insn->size <= 4) { 8844 p = s390_emit_load_32imm(p, R0, value); 8845 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0); 8846 } 8847 8848 vassert(insn->size == 8); 8849 p = s390_emit_load_64imm(p, R0, value); 8850 return s390_emit_LOCGR(p, cond, hregNumber(dst), R0); 8851 } 8852 } 8853 } 8854 8855 use_branch_insn: 8856 /* Branch (if cond fails) over move instrs */ 8857 if (cond != S390_CC_ALWAYS) { 8858 /* Don't know how many bytes to jump over yet. 8859 Make space for a BRC instruction (4 bytes) and fill in later. */ 8860 ptmp = p; /* to be filled in here */ 8861 p += 4; 8862 } 8863 8864 // cond true: move src => dst 8865 8866 switch (src.tag) { 8867 case S390_OPND_REG: 8868 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg)); 8869 break; 8870 8871 case S390_OPND_AMODE: 8872 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am); 8873 break; 8874 8875 case S390_OPND_IMMEDIATE: { 8876 ULong value = src.variant.imm; 8877 UInt r = hregNumber(dst); 8878 8879 switch (insn->size) { 8880 case 1: 8881 case 2: 8882 /* Load the immediate values as a 4 byte value. That does not hurt as 8883 those extra bytes will not be looked at. Fall through .... */ 8884 case 4: 8885 p = s390_emit_load_32imm(p, r, value); 8886 break; 8887 8888 case 8: 8889 p = s390_emit_load_64imm(p, r, value); 8890 break; 8891 } 8892 break; 8893 } 8894 8895 default: 8896 goto fail; 8897 } 8898 8899 if (cond != S390_CC_ALWAYS) { 8900 Int delta = p - ptmp; 8901 8902 delta >>= 1; /* immediate constant is #half-words */ 8903 vassert(delta > 0 && delta < (1 << 16)); 8904 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 8905 } 8906 8907 return p; 8908 8909 fail: 8910 vpanic("s390_insn_cond_move_emit"); 8911 } 8912 8913 8914 static UChar * 8915 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn) 8916 { 8917 UInt r1 = hregNumber(insn->variant.bfp_triop.dst); 8918 UInt r2 = hregNumber(insn->variant.bfp_triop.op2); 8919 UInt r3 = hregNumber(insn->variant.bfp_triop.op3); 8920 8921 switch (insn->size) { 8922 case 4: 8923 switch (insn->variant.bfp_triop.tag) { 8924 case S390_BFP_MADD: return s390_emit_MAEBR(buf, r1, r3, r2); 8925 case S390_BFP_MSUB: return s390_emit_MSEBR(buf, r1, r3, r2); 8926 default: goto fail; 8927 } 8928 break; 8929 8930 case 8: 8931 switch (insn->variant.bfp_triop.tag) { 8932 case S390_BFP_MADD: return s390_emit_MADBR(buf, r1, r3, r2); 8933 case S390_BFP_MSUB: return s390_emit_MSDBR(buf, r1, r3, r2); 8934 default: goto fail; 8935 } 8936 break; 8937 8938 default: goto fail; 8939 } 8940 8941 fail: 8942 vpanic("s390_insn_bfp_triop_emit"); 8943 } 8944 8945 8946 static UChar * 8947 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn) 8948 { 8949 UInt r1 = hregNumber(insn->variant.bfp_binop.dst_hi); 8950 UInt r2 = hregNumber(insn->variant.bfp_binop.op2_hi); 8951 8952 switch (insn->size) { 8953 case 4: 8954 switch (insn->variant.bfp_binop.tag) { 8955 case S390_BFP_ADD: return s390_emit_AEBR(buf, r1, r2); 8956 case S390_BFP_SUB: return s390_emit_SEBR(buf, r1, r2); 8957 case S390_BFP_MUL: return s390_emit_MEEBR(buf, r1, r2); 8958 case S390_BFP_DIV: return s390_emit_DEBR(buf, r1, r2); 8959 default: goto fail; 8960 } 8961 break; 8962 8963 case 8: 8964 switch (insn->variant.bfp_binop.tag) { 8965 case S390_BFP_ADD: return s390_emit_ADBR(buf, r1, r2); 8966 case S390_BFP_SUB: return s390_emit_SDBR(buf, r1, r2); 8967 case S390_BFP_MUL: return s390_emit_MDBR(buf, r1, r2); 8968 case S390_BFP_DIV: return s390_emit_DDBR(buf, r1, r2); 8969 default: goto fail; 8970 } 8971 break; 8972 8973 case 16: 8974 switch (insn->variant.bfp_binop.tag) { 8975 case S390_BFP_ADD: return s390_emit_AXBR(buf, r1, r2); 8976 case S390_BFP_SUB: return s390_emit_SXBR(buf, r1, r2); 8977 case S390_BFP_MUL: return s390_emit_MXBR(buf, r1, r2); 8978 case S390_BFP_DIV: return s390_emit_DXBR(buf, r1, r2); 8979 default: goto fail; 8980 } 8981 break; 8982 8983 default: goto fail; 8984 } 8985 8986 fail: 8987 vpanic("s390_insn_bfp_binop_emit"); 8988 } 8989 8990 8991 static UChar * 8992 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn) 8993 { 8994 UInt r1 = hregNumber(insn->variant.bfp_unop.dst_hi); 8995 UInt r2 = hregNumber(insn->variant.bfp_unop.op_hi); 8996 8997 switch (insn->variant.bfp_unop.tag) { 8998 case S390_BFP_ABS: 8999 switch (insn->size) { 9000 case 4: return s390_emit_LPEBR(buf, r1, r2); 9001 case 8: return s390_emit_LPDBR(buf, r1, r2); 9002 case 16: return s390_emit_LPXBR(buf, r1, r2); 9003 default: goto fail; 9004 } 9005 break; 9006 9007 case S390_BFP_NABS: 9008 switch (insn->size) { 9009 case 4: return s390_emit_LNEBR(buf, r1, r2); 9010 case 8: return s390_emit_LNDBR(buf, r1, r2); 9011 case 16: return s390_emit_LNXBR(buf, r1, r2); 9012 default: goto fail; 9013 } 9014 break; 9015 9016 case S390_BFP_NEG: 9017 switch (insn->size) { 9018 case 4: return s390_emit_LCEBR(buf, r1, r2); 9019 case 8: return s390_emit_LCDBR(buf, r1, r2); 9020 case 16: return s390_emit_LCXBR(buf, r1, r2); 9021 default: goto fail; 9022 } 9023 break; 9024 9025 case S390_BFP_SQRT: 9026 switch (insn->size) { 9027 case 4: return s390_emit_SQEBR(buf, r1, r2); 9028 case 8: return s390_emit_SQDBR(buf, r1, r2); 9029 case 16: return s390_emit_SQXBR(buf, r1, r2); 9030 default: goto fail; 9031 } 9032 break; 9033 9034 default: goto fail; 9035 } 9036 9037 fail: 9038 vpanic("s390_insn_bfp_unop_emit"); 9039 } 9040 9041 9042 static UChar * 9043 s390_insn_bfp_convert_emit(UChar *buf, const s390_insn *insn) 9044 { 9045 UInt r1 = hregNumber(insn->variant.bfp_convert.dst_hi); 9046 UInt r2 = hregNumber(insn->variant.bfp_convert.op_hi); 9047 s390_bfp_round_t m3 = insn->variant.bfp_convert.rounding_mode; 9048 /* The IEEE-inexact-exception control is not modelled. So the 9049 m4 field is 0 (which is what GCC does, too) */ 9050 const UInt m4 = 0; 9051 9052 switch (insn->variant.bfp_convert.tag) { 9053 /* Convert to fixed */ 9054 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2); 9055 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2); 9056 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, m3, r1, r2); 9057 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2); 9058 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2); 9059 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, m3, r1, r2); 9060 9061 /* Convert to logical */ 9062 case S390_BFP_F32_TO_U32: return s390_emit_CLFEBR(buf, m3, m4, r1, r2); 9063 case S390_BFP_F64_TO_U32: return s390_emit_CLFDBR(buf, m3, m4, r1, r2); 9064 case S390_BFP_F128_TO_U32: return s390_emit_CLFXBR(buf, m3, m4, r1, r2); 9065 case S390_BFP_F32_TO_U64: return s390_emit_CLGEBR(buf, m3, m4, r1, r2); 9066 case S390_BFP_F64_TO_U64: return s390_emit_CLGDBR(buf, m3, m4, r1, r2); 9067 case S390_BFP_F128_TO_U64: return s390_emit_CLGXBR(buf, m3, m4, r1, r2); 9068 9069 /* Convert from fixed */ 9070 case S390_BFP_I32_TO_F32: return s390_emit_CEFBRA(buf, m3, m4, r1, r2); 9071 case S390_BFP_I32_TO_F64: return s390_emit_CDFBRA(buf, 0, m4, r1, r2); 9072 case S390_BFP_I32_TO_F128: return s390_emit_CXFBRA(buf, 0, m4, r1, r2); 9073 case S390_BFP_I64_TO_F32: return s390_emit_CEGBRA(buf, m3, m4, r1, r2); 9074 case S390_BFP_I64_TO_F64: return s390_emit_CDGBRA(buf, m3, m4, r1, r2); 9075 case S390_BFP_I64_TO_F128: return s390_emit_CXGBRA(buf, 0, m4, r1, r2); 9076 9077 /* Convert from logical */ 9078 case S390_BFP_U32_TO_F32: return s390_emit_CELFBR(buf, m3, m4, r1, r2); 9079 case S390_BFP_U32_TO_F64: return s390_emit_CDLFBR(buf, m3, m4, r1, r2); 9080 case S390_BFP_U32_TO_F128: return s390_emit_CXLFBR(buf, m3, m4, r1, r2); 9081 case S390_BFP_U64_TO_F32: return s390_emit_CELGBR(buf, m3, m4, r1, r2); 9082 case S390_BFP_U64_TO_F64: return s390_emit_CDLGBR(buf, m3, m4, r1, r2); 9083 case S390_BFP_U64_TO_F128: return s390_emit_CXLGBR(buf, m3, m4, r1, r2); 9084 9085 /* Load lengthened */ 9086 case S390_BFP_F32_TO_F64: return s390_emit_LDEBR(buf, r1, r2); 9087 case S390_BFP_F32_TO_F128: return s390_emit_LXEBR(buf, r1, r2); 9088 case S390_BFP_F64_TO_F128: return s390_emit_LXDBR(buf, r1, r2); 9089 9090 /* Load rounded */ 9091 case S390_BFP_F64_TO_F32: return s390_emit_LEDBRA(buf, m3, m4, r1, r2); 9092 case S390_BFP_F128_TO_F32: return s390_emit_LEXBRA(buf, m3, m4, r1, r2); 9093 case S390_BFP_F128_TO_F64: return s390_emit_LDXBRA(buf, m3, m4, r1, r2); 9094 9095 default: goto fail; 9096 } 9097 9098 fail: 9099 vpanic("s390_insn_bfp_convert_emit"); 9100 } 9101 9102 9103 static UChar * 9104 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn) 9105 { 9106 UInt dst = hregNumber(insn->variant.bfp_compare.dst); 9107 UInt r1 = hregNumber(insn->variant.bfp_compare.op1_hi); 9108 UInt r2 = hregNumber(insn->variant.bfp_compare.op2_hi); 9109 9110 switch (insn->size) { 9111 case 4: buf = s390_emit_CEBR(buf, r1, r2); break; 9112 case 8: buf = s390_emit_CDBR(buf, r1, r2); break; 9113 case 16: buf = s390_emit_CXBR(buf, r1, r2); break; 9114 default: goto fail; 9115 } 9116 9117 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */ 9118 9119 fail: 9120 vpanic("s390_insn_bfp_compare_emit"); 9121 } 9122 9123 9124 static UChar * 9125 s390_insn_dfp_binop_emit(UChar *buf, const s390_insn *insn) 9126 { 9127 s390_dfp_binop *dfp_binop = insn->variant.dfp_binop.details; 9128 9129 UInt r1 = hregNumber(dfp_binop->dst_hi); 9130 UInt r2 = hregNumber(dfp_binop->op2_hi); 9131 UInt r3 = hregNumber(dfp_binop->op3_hi); 9132 s390_dfp_round_t m4 = dfp_binop->rounding_mode; 9133 9134 switch (insn->size) { 9135 case 8: 9136 switch (dfp_binop->tag) { 9137 case S390_DFP_ADD: return s390_emit_ADTRA(buf, r3, m4, r1, r2); 9138 case S390_DFP_SUB: return s390_emit_SDTRA(buf, r3, m4, r1, r2); 9139 case S390_DFP_MUL: return s390_emit_MDTRA(buf, r3, m4, r1, r2); 9140 case S390_DFP_DIV: return s390_emit_DDTRA(buf, r3, m4, r1, r2); 9141 case S390_DFP_QUANTIZE: return s390_emit_QADTR(buf, r3, m4, r1, r2); 9142 default: goto fail; 9143 } 9144 break; 9145 9146 case 16: 9147 switch (dfp_binop->tag) { 9148 case S390_DFP_ADD: return s390_emit_AXTRA(buf, r3, m4, r1, r2); 9149 case S390_DFP_SUB: return s390_emit_SXTRA(buf, r3, m4, r1, r2); 9150 case S390_DFP_MUL: return s390_emit_MXTRA(buf, r3, m4, r1, r2); 9151 case S390_DFP_DIV: return s390_emit_DXTRA(buf, r3, m4, r1, r2); 9152 case S390_DFP_QUANTIZE: return s390_emit_QAXTR(buf, r3, m4, r1, r2); 9153 default: goto fail; 9154 } 9155 break; 9156 9157 default: goto fail; 9158 } 9159 9160 fail: 9161 vpanic("s390_insn_dfp_binop_emit"); 9162 } 9163 9164 9165 static UChar * 9166 s390_insn_dfp_reround_emit(UChar *buf, const s390_insn *insn) 9167 { 9168 UInt r1 = hregNumber(insn->variant.dfp_reround.dst_hi); 9169 UInt r2 = hregNumber(insn->variant.dfp_reround.op2); 9170 UInt r3 = hregNumber(insn->variant.dfp_reround.op3_hi); 9171 s390_dfp_round_t m4 = insn->variant.dfp_reround.rounding_mode; 9172 9173 switch (insn->size) { 9174 case 8: 9175 return s390_emit_RRDTR(buf, r3, m4, r1, r2); 9176 9177 case 16: 9178 return s390_emit_RRXTR(buf, r3, m4, r1, r2); 9179 9180 default: goto fail; 9181 } 9182 fail: 9183 vpanic("s390_insn_dfp_reround_emit"); 9184 } 9185 9186 9187 static UChar * 9188 s390_insn_dfp_unop_emit(UChar *buf, const s390_insn *insn) 9189 { 9190 UInt r1 = hregNumber(insn->variant.dfp_unop.dst_hi); 9191 UInt r2 = hregNumber(insn->variant.dfp_unop.op_hi); 9192 9193 switch (insn->variant.dfp_unop.tag) { 9194 case S390_DFP_EXTRACT_EXP_D64: return s390_emit_EEDTR(buf, r1, r2); break; 9195 case S390_DFP_EXTRACT_EXP_D128: return s390_emit_EEXTR(buf, r1, r2); break; 9196 case S390_DFP_EXTRACT_SIG_D64: return s390_emit_ESDTR(buf, r1, r2); break; 9197 case S390_DFP_EXTRACT_SIG_D128: return s390_emit_ESXTR(buf, r1, r2); break; 9198 default: goto fail; 9199 } 9200 fail: 9201 vpanic("s390_insn_dfp_unop_emit"); 9202 } 9203 9204 9205 static UChar * 9206 s390_insn_dfp_intop_emit(UChar *buf, const s390_insn *insn) 9207 { 9208 UInt r1 = hregNumber(insn->variant.dfp_intop.dst_hi); 9209 UInt r2 = hregNumber(insn->variant.dfp_intop.op2); 9210 UInt r3 = hregNumber(insn->variant.dfp_intop.op3_hi); 9211 9212 switch (insn->size) { 9213 case 8: 9214 switch (insn->variant.dfp_intop.tag) { 9215 case S390_DFP_SHIFT_LEFT: return s390_emit_SLDT(buf, r3, r1, r2); 9216 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRDT(buf, r3, r1, r2); 9217 case S390_DFP_INSERT_EXP: return s390_emit_IEDTR(buf, r3, r1, r2); 9218 default: goto fail; 9219 } 9220 break; 9221 9222 case 16: 9223 switch (insn->variant.dfp_intop.tag) { 9224 case S390_DFP_SHIFT_LEFT: return s390_emit_SLXT(buf, r3, r1, r2); 9225 case S390_DFP_SHIFT_RIGHT: return s390_emit_SRXT(buf, r3, r1, r2); 9226 case S390_DFP_INSERT_EXP: return s390_emit_IEXTR(buf, r3, r1, r2); 9227 default: goto fail; 9228 } 9229 break; 9230 9231 default: goto fail; 9232 } 9233 9234 fail: 9235 vpanic("s390_insn_dfp_intop_emit"); 9236 } 9237 9238 9239 static UChar * 9240 s390_insn_dfp_compare_emit(UChar *buf, const s390_insn *insn) 9241 { 9242 UInt dst = hregNumber(insn->variant.dfp_compare.dst); 9243 UInt r1 = hregNumber(insn->variant.dfp_compare.op1_hi); 9244 UInt r2 = hregNumber(insn->variant.dfp_compare.op2_hi); 9245 9246 switch (insn->size) { 9247 case 8: 9248 switch(insn->variant.dfp_compare.tag) { 9249 case S390_DFP_COMPARE: buf = s390_emit_CDTR(buf, r1, r2); break; 9250 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEDTR(buf, r1, r2); break; 9251 default: goto fail; 9252 } 9253 break; 9254 9255 case 16: 9256 switch(insn->variant.dfp_compare.tag) { 9257 case S390_DFP_COMPARE: buf = s390_emit_CXTR(buf, r1, r2); break; 9258 case S390_DFP_COMPARE_EXP: buf = s390_emit_CEXTR(buf, r1, r2); break; 9259 default: goto fail; 9260 } 9261 break; 9262 9263 default: goto fail; 9264 } 9265 9266 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */ 9267 9268 fail: 9269 vpanic("s390_insn_dfp_compare_emit"); 9270 } 9271 9272 9273 static UChar * 9274 s390_insn_dfp_convert_emit(UChar *buf, const s390_insn *insn) 9275 { 9276 UInt r1 = hregNumber(insn->variant.dfp_convert.dst_hi); 9277 UInt r2 = hregNumber(insn->variant.dfp_convert.op_hi); 9278 s390_dfp_round_t m3 = insn->variant.dfp_convert.rounding_mode; 9279 /* The IEEE-inexact-exception control is not modelled. So the 9280 m4 field is 0 (which is what GCC does, too) */ 9281 const UInt m4 = 0; 9282 9283 switch (insn->variant.dfp_convert.tag) { 9284 9285 /* Convert to fixed */ 9286 case S390_DFP_D64_TO_I32: return s390_emit_CFDTR(buf, m3, m4, r1, r2); 9287 case S390_DFP_D128_TO_I32: return s390_emit_CFXTR(buf, m3, m4, r1, r2); 9288 case S390_DFP_D64_TO_I64: return s390_emit_CGDTR(buf, m3, m4, r1, r2); 9289 case S390_DFP_D128_TO_I64: return s390_emit_CGXTR(buf, m3, m4, r1, r2); 9290 9291 /* Convert to logical */ 9292 case S390_DFP_D64_TO_U32: return s390_emit_CLFDTR(buf, m3, m4, r1, r2); 9293 case S390_DFP_D128_TO_U32: return s390_emit_CLFXTR(buf, m3, m4, r1, r2); 9294 case S390_DFP_D64_TO_U64: return s390_emit_CLGDTR(buf, m3, m4, r1, r2); 9295 case S390_DFP_D128_TO_U64: return s390_emit_CLGXTR(buf, m3, m4, r1, r2); 9296 9297 /* Convert from fixed */ 9298 case S390_DFP_I32_TO_D64: return s390_emit_CDFTR(buf, 0, m4, r1, r2); 9299 case S390_DFP_I32_TO_D128: return s390_emit_CXFTR(buf, 0, m4, r1, r2); 9300 case S390_DFP_I64_TO_D64: return s390_emit_CDGTRA(buf, m3, m4, r1, r2); 9301 case S390_DFP_I64_TO_D128: return s390_emit_CXGTR(buf, 0, m4, r1, r2); 9302 9303 /* Convert from logical */ 9304 case S390_DFP_U32_TO_D64: return s390_emit_CDLFTR(buf, m3, m4, r1, r2); 9305 case S390_DFP_U64_TO_D64: return s390_emit_CDLGTR(buf, m3, m4, r1, r2); 9306 case S390_DFP_U32_TO_D128: return s390_emit_CXLFTR(buf, m3, m4, r1, r2); 9307 case S390_DFP_U64_TO_D128: return s390_emit_CXLGTR(buf, m3, m4, r1, r2); 9308 9309 /* Load lengthened */ 9310 case S390_DFP_D32_TO_D64: return s390_emit_LDETR(buf, m4, r1, r2); 9311 case S390_DFP_D64_TO_D128: return s390_emit_LXDTR(buf, m4, r1, r2); 9312 9313 /* Load rounded */ 9314 case S390_DFP_D64_TO_D32: return s390_emit_LEDTR(buf, m3, m4, r1, r2); 9315 case S390_DFP_D128_TO_D64: return s390_emit_LDXTR(buf, m3, m4, r1, r2); 9316 9317 default: goto fail; 9318 } 9319 9320 fail: 9321 vpanic("s390_insn_dfp_convert_emit"); 9322 } 9323 9324 9325 static UChar * 9326 s390_insn_fp_convert_emit(UChar *buf, const s390_insn *insn) 9327 { 9328 UInt pfpo; 9329 s390_fp_convert *fp_convert = insn->variant.fp_convert.details; 9330 s390_dfp_round_t rm = fp_convert->rounding_mode; 9331 9332 vassert(rm < 2 || rm > 7); 9333 9334 switch (fp_convert->tag) { 9335 case S390_FP_F32_TO_D32: pfpo = S390_PFPO_F32_TO_D32 << 8; break; 9336 case S390_FP_F32_TO_D64: pfpo = S390_PFPO_F32_TO_D64 << 8; break; 9337 case S390_FP_F32_TO_D128: pfpo = S390_PFPO_F32_TO_D128 << 8; break; 9338 case S390_FP_F64_TO_D32: pfpo = S390_PFPO_F64_TO_D32 << 8; break; 9339 case S390_FP_F64_TO_D64: pfpo = S390_PFPO_F64_TO_D64 << 8; break; 9340 case S390_FP_F64_TO_D128: pfpo = S390_PFPO_F64_TO_D128 << 8; break; 9341 case S390_FP_F128_TO_D32: pfpo = S390_PFPO_F128_TO_D32 << 8; break; 9342 case S390_FP_F128_TO_D64: pfpo = S390_PFPO_F128_TO_D64 << 8; break; 9343 case S390_FP_F128_TO_D128: pfpo = S390_PFPO_F128_TO_D128 << 8; break; 9344 case S390_FP_D32_TO_F32: pfpo = S390_PFPO_D32_TO_F32 << 8; break; 9345 case S390_FP_D32_TO_F64: pfpo = S390_PFPO_D32_TO_F64 << 8; break; 9346 case S390_FP_D32_TO_F128: pfpo = S390_PFPO_D32_TO_F128 << 8; break; 9347 case S390_FP_D64_TO_F32: pfpo = S390_PFPO_D64_TO_F32 << 8; break; 9348 case S390_FP_D64_TO_F64: pfpo = S390_PFPO_D64_TO_F64 << 8; break; 9349 case S390_FP_D64_TO_F128: pfpo = S390_PFPO_D64_TO_F128 << 8; break; 9350 case S390_FP_D128_TO_F32: pfpo = S390_PFPO_D128_TO_F32 << 8; break; 9351 case S390_FP_D128_TO_F64: pfpo = S390_PFPO_D128_TO_F64 << 8; break; 9352 case S390_FP_D128_TO_F128: pfpo = S390_PFPO_D128_TO_F128 << 8; break; 9353 default: goto fail; 9354 } 9355 9356 pfpo = pfpo | rm; 9357 buf = s390_emit_load_32imm(buf, R0, pfpo); 9358 buf = s390_emit_PFPO(buf); 9359 return buf; 9360 9361 fail: 9362 vpanic("s390_insn_fp_convert_emit"); 9363 } 9364 9365 9366 static UChar * 9367 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn) 9368 { 9369 return s390_emit_BCR(buf, 0xF, 0x0); 9370 } 9371 9372 9373 static UChar * 9374 s390_insn_mimm_emit(UChar *buf, const s390_insn *insn) 9375 { 9376 s390_amode *am = insn->variant.mimm.dst; 9377 UChar b = hregNumber(am->b); 9378 Int d = am->d; 9379 ULong value = insn->variant.mimm.value; 9380 9381 if (value == 0) { 9382 return s390_emit_XC(buf, insn->size - 1, b, d, b, d); 9383 } 9384 9385 if (insn->size == 1) { 9386 return s390_emit_MVI(buf, value & 0xFF, b, d); 9387 } 9388 9389 if (s390_host_has_gie && ulong_fits_signed_16bit(value)) { 9390 value &= 0xFFFF; 9391 switch (insn->size) { 9392 case 2: return s390_emit_MVHHI(buf, b, d, value); 9393 case 4: return s390_emit_MVHI(buf, b, d, value); 9394 case 8: return s390_emit_MVGHI(buf, b, d, value); 9395 } 9396 } else { 9397 // Load value to R0, then store. 9398 switch (insn->size) { 9399 case 2: 9400 buf = s390_emit_LHI(buf, R0, value & 0xFFFF); 9401 return s390_emit_STH(buf, R0, 0, b, d); 9402 case 4: 9403 buf = s390_emit_load_32imm(buf, R0, value); 9404 return s390_emit_ST(buf, R0, 0, b, d); 9405 case 8: 9406 buf = s390_emit_load_64imm(buf, R0, value); 9407 return s390_emit_STG(buf, R0, 0, b, DISP20(d)); 9408 } 9409 } 9410 9411 vpanic("s390_insn_mimm_emit"); 9412 } 9413 9414 9415 static UChar * 9416 s390_insn_madd_emit(UChar *buf, const s390_insn *insn) 9417 { 9418 s390_amode *am = insn->variant.madd.dst; 9419 UChar b = hregNumber(am->b); 9420 Int d = am->d; 9421 9422 if (insn->size == 4) { 9423 return s390_emit_ASI(buf, insn->variant.madd.delta, b, DISP20(d)); 9424 } 9425 9426 return s390_emit_AGSI(buf, insn->variant.madd.delta, b, DISP20(d)); 9427 } 9428 9429 9430 static UChar * 9431 s390_insn_set_fpc_bfprm_emit(UChar *buf, const s390_insn *insn) 9432 { 9433 UInt mode = hregNumber(insn->variant.set_fpc_bfprm.mode); 9434 9435 /* Copy FPC from guest state to R0 and OR in the new rounding mode */ 9436 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER, 9437 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc 9438 9439 buf = s390_emit_NILL(buf, R0, 0xFFF8); /* Clear out right-most 3 bits */ 9440 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */ 9441 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */ 9442 9443 return buf; 9444 } 9445 9446 9447 static UChar * 9448 s390_insn_set_fpc_dfprm_emit(UChar *buf, const s390_insn *insn) 9449 { 9450 UInt mode = hregNumber(insn->variant.set_fpc_dfprm.mode); 9451 9452 /* Copy FPC from guest state to R0 and OR in the new rounding mode */ 9453 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER, 9454 S390X_GUEST_OFFSET(guest_fpc)); // r0 = guest_fpc 9455 9456 /* DFP rounding mode is set at bit position 25:27 in FPC register */ 9457 buf = s390_emit_NILL(buf, R0, 0xFF8F); /* Clear out 25:27 bits */ 9458 buf = s390_emit_SLL(buf, mode, 0, 4); /* bring mode to 25:27 bits */ 9459 buf = s390_emit_OR(buf, R0, mode); /* OR in the new rounding mode */ 9460 buf = s390_emit_SFPC(buf, R0); /* Load FPC register from R0 */ 9461 9462 return buf; 9463 } 9464 9465 9466 /* Define convenience functions needed for translation chaining. 9467 Any changes need to be applied to the functions in concert. */ 9468 9469 static __inline__ Bool 9470 s390_insn_is_BRCL(const UChar *p, UChar condition) 9471 { 9472 return p[0] == 0xc0 && p[1] == ((condition << 4) | 0x04); 9473 } 9474 9475 static __inline__ Bool 9476 s390_insn_is_BR(const UChar *p, UChar reg) 9477 { 9478 return p[0] == 0x07 && p[1] == (0xF0 | reg); /* BCR 15,reg */ 9479 } 9480 9481 9482 /* The length of the BASR insn */ 9483 #define S390_BASR_LEN 2 9484 9485 9486 /* Load the 64-bit VALUE into REG. Note that this function must NOT 9487 optimise the generated code by looking at the value. I.e. using 9488 LGHI if value == 0 would be very wrong. */ 9489 static UChar * 9490 s390_tchain_load64(UChar *buf, UChar regno, ULong value) 9491 { 9492 UChar *begin = buf; 9493 9494 if (s390_host_has_eimm) { 9495 /* Do it in two steps: upper half [0:31] and lower half [32:63] */ 9496 buf = s390_emit_IIHF(buf, regno, value >> 32); 9497 buf = s390_emit_IILF(buf, regno, value & 0xFFFFFFFF); 9498 } else { 9499 buf = s390_emit_IILL(buf, regno, value & 0xFFFF); 9500 value >>= 16; 9501 buf = s390_emit_IILH(buf, regno, value & 0xFFFF); 9502 value >>= 16; 9503 buf = s390_emit_IIHL(buf, regno, value & 0xFFFF); 9504 value >>= 16; 9505 buf = s390_emit_IIHH(buf, regno, value & 0xFFFF); 9506 } 9507 9508 vassert(buf - begin == s390_tchain_load64_len()); 9509 9510 return buf; 9511 } 9512 9513 /* Return number of bytes generated by s390_tchain_load64 */ 9514 static UInt 9515 s390_tchain_load64_len(void) 9516 { 9517 if (s390_host_has_eimm) { 9518 return 6 + 6; /* IIHF + IILF */ 9519 } 9520 return 4 + 4 + 4 + 4; /* IIHH + IIHL + IILH + IILL */ 9521 } 9522 9523 /* Verify that CODE is the code sequence generated by s390_tchain_load64 9524 to load VALUE into REGNO. Return pointer to the byte following the 9525 insn sequence. */ 9526 static const UChar * 9527 s390_tchain_verify_load64(const UChar *code, UChar regno, ULong value) 9528 { 9529 UInt regmask = regno << 4; 9530 UInt hw; 9531 9532 if (s390_host_has_eimm) { 9533 /* Check for IIHF */ 9534 vassert(code[0] == 0xC0); 9535 vassert(code[1] == (0x08 | regmask)); 9536 vassert(*(const UInt *)&code[2] == (value >> 32)); 9537 /* Check for IILF */ 9538 vassert(code[6] == 0xC0); 9539 vassert(code[7] == (0x09 | regmask)); 9540 vassert(*(const UInt *)&code[8] == (value & 0xFFFFFFFF)); 9541 } else { 9542 /* Check for IILL */ 9543 hw = value & 0xFFFF; 9544 vassert(code[0] == 0xA5); 9545 vassert(code[1] == (0x03 | regmask)); 9546 vassert(code[2] == (hw >> 8)); 9547 vassert(code[3] == (hw & 0xFF)); 9548 9549 /* Check for IILH */ 9550 hw = (value >> 16) & 0xFFFF; 9551 vassert(code[4] == 0xA5); 9552 vassert(code[5] == (0x02 | regmask)); 9553 vassert(code[6] == (hw >> 8)); 9554 vassert(code[7] == (hw & 0xFF)); 9555 9556 /* Check for IIHL */ 9557 hw = (value >> 32) & 0xFFFF; 9558 vassert(code[8] == 0xA5); 9559 vassert(code[9] == (0x01 | regmask)); 9560 vassert(code[10] == (hw >> 8)); 9561 vassert(code[11] == (hw & 0xFF)); 9562 9563 /* Check for IIHH */ 9564 hw = (value >> 48) & 0xFFFF; 9565 vassert(code[12] == 0xA5); 9566 vassert(code[13] == (0x00 | regmask)); 9567 vassert(code[14] == (hw >> 8)); 9568 vassert(code[15] == (hw & 0xFF)); 9569 } 9570 9571 return code + s390_tchain_load64_len(); 9572 } 9573 9574 /* CODE points to the code sequence as generated by s390_tchain_load64. 9575 Change the loaded value to IMM64. Return pointer to the byte following 9576 the patched code sequence. */ 9577 static UChar * 9578 s390_tchain_patch_load64(UChar *code, ULong imm64) 9579 { 9580 if (s390_host_has_eimm) { 9581 /* Patch IIHF */ 9582 *(UInt *)&code[2] = imm64 >> 32; 9583 /* Patch IILF */ 9584 *(UInt *)&code[8] = imm64 & 0xFFFFFFFF; 9585 } else { 9586 code[3] = imm64 & 0xFF; imm64 >>= 8; 9587 code[2] = imm64 & 0xFF; imm64 >>= 8; 9588 code[7] = imm64 & 0xFF; imm64 >>= 8; 9589 code[6] = imm64 & 0xFF; imm64 >>= 8; 9590 code[11] = imm64 & 0xFF; imm64 >>= 8; 9591 code[10] = imm64 & 0xFF; imm64 >>= 8; 9592 code[15] = imm64 & 0xFF; imm64 >>= 8; 9593 code[14] = imm64 & 0xFF; imm64 >>= 8; 9594 } 9595 9596 return code + s390_tchain_load64_len(); 9597 } 9598 9599 9600 /* NB: what goes on here has to be very closely coordinated with the 9601 chainXDirect_S390 and unchainXDirect_S390 below. */ 9602 static UChar * 9603 s390_insn_xdirect_emit(UChar *buf, const s390_insn *insn, 9604 void *disp_cp_chain_me_to_slowEP, 9605 void *disp_cp_chain_me_to_fastEP) 9606 { 9607 /* We're generating chain-me requests here, so we need to be 9608 sure this is actually allowed -- no-redir translations can't 9609 use chain-me's. Hence: */ 9610 vassert(disp_cp_chain_me_to_slowEP != NULL); 9611 vassert(disp_cp_chain_me_to_fastEP != NULL); 9612 9613 /* Use ptmp for backpatching conditional jumps. */ 9614 UChar *ptmp = buf; 9615 9616 /* First off, if this is conditional, create a conditional 9617 jump over the rest of it. */ 9618 s390_cc_t cond = insn->variant.xdirect.cond; 9619 9620 if (cond != S390_CC_ALWAYS) { 9621 /* So we have something like this 9622 if (cond) do_xdirect; 9623 Y: ... 9624 We convert this into 9625 if (! cond) goto Y; // BRC opcode; 4 bytes 9626 do_xdirect; 9627 Y: 9628 */ 9629 /* 4 bytes (a BRC insn) to be filled in here */ 9630 buf += 4; 9631 } 9632 9633 /* Update the guest IA. */ 9634 buf = s390_emit_load_64imm(buf, R0, insn->variant.xdirect.dst); 9635 9636 const s390_amode *amode = insn->variant.xdirect.guest_IA; 9637 vassert(amode->tag == S390_AMODE_B12); 9638 UInt b = hregNumber(amode->b); 9639 UInt d = amode->d; 9640 9641 buf = s390_emit_STG(buf, R0, 0, b, DISP20(d)); 9642 9643 /* Load the chosen entry point into the scratch reg */ 9644 void *disp_cp_chain_me; 9645 9646 disp_cp_chain_me = 9647 insn->variant.xdirect.to_fast_entry ? disp_cp_chain_me_to_fastEP 9648 : disp_cp_chain_me_to_slowEP; 9649 /* Get the address of the beginning of the load64 code sequence into %r1. 9650 Do not change the register! This is part of the protocol with the 9651 dispatcher. */ 9652 buf = s390_emit_BASR(buf, 1, R0); 9653 9654 /* --- FIRST PATCHABLE BYTE follows (must not modify %r1) --- */ 9655 ULong addr = Ptr_to_ULong(disp_cp_chain_me); 9656 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, addr); 9657 9658 /* goto *tchain_scratch */ 9659 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); 9660 9661 /* --- END of PATCHABLE BYTES --- */ 9662 9663 /* Fix up the conditional jump, if there was one. */ 9664 if (cond != S390_CC_ALWAYS) { 9665 Int delta = buf - ptmp; 9666 9667 delta >>= 1; /* immediate constant is #half-words */ 9668 vassert(delta > 0 && delta < (1 << 16)); 9669 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 9670 } 9671 9672 return buf; 9673 } 9674 9675 /* Return the number of patchable bytes from an xdirect insn. */ 9676 static UInt 9677 s390_xdirect_patchable_len(void) 9678 { 9679 return s390_tchain_load64_len() + S390_BASR_LEN; 9680 } 9681 9682 9683 static UChar * 9684 s390_insn_xindir_emit(UChar *buf, const s390_insn *insn, void *disp_cp_xindir) 9685 { 9686 /* We're generating transfers that could lead indirectly to a 9687 chain-me, so we need to be sure this is actually allowed -- 9688 no-redir translations are not allowed to reach normal 9689 translations without going through the scheduler. That means 9690 no XDirects or XIndirs out from no-redir translations. 9691 Hence: */ 9692 vassert(disp_cp_xindir != NULL); 9693 9694 /* Use ptmp for backpatching conditional jumps. */ 9695 UChar *ptmp = buf; 9696 9697 /* First off, if this is conditional, create a conditional 9698 jump over the rest of it. */ 9699 s390_cc_t cond = insn->variant.xdirect.cond; 9700 9701 if (cond != S390_CC_ALWAYS) { 9702 /* So we have something like this 9703 if (cond) do_xdirect; 9704 Y: ... 9705 We convert this into 9706 if (! cond) goto Y; // BRC opcode; 4 bytes 9707 do_xdirect; 9708 Y: 9709 */ 9710 /* 4 bytes (a BRC insn) to be filled in here */ 9711 buf += 4; 9712 } 9713 9714 /* Update the guest IA with the address in xdirect.dst. */ 9715 const s390_amode *amode = insn->variant.xindir.guest_IA; 9716 9717 vassert(amode->tag == S390_AMODE_B12); 9718 UInt b = hregNumber(amode->b); 9719 UInt d = amode->d; 9720 UInt regno = hregNumber(insn->variant.xindir.dst); 9721 9722 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d)); 9723 9724 /* load tchain_scratch, #disp_indir */ 9725 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 9726 Ptr_to_ULong(disp_cp_xindir)); 9727 /* goto *tchain_direct */ 9728 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); 9729 9730 /* Fix up the conditional jump, if there was one. */ 9731 if (cond != S390_CC_ALWAYS) { 9732 Int delta = buf - ptmp; 9733 9734 delta >>= 1; /* immediate constant is #half-words */ 9735 vassert(delta > 0 && delta < (1 << 16)); 9736 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 9737 } 9738 9739 return buf; 9740 } 9741 9742 static UChar * 9743 s390_insn_xassisted_emit(UChar *buf, const s390_insn *insn, 9744 void *disp_cp_xassisted) 9745 { 9746 /* Use ptmp for backpatching conditional jumps. */ 9747 UChar *ptmp = buf; 9748 9749 /* First off, if this is conditional, create a conditional 9750 jump over the rest of it. */ 9751 s390_cc_t cond = insn->variant.xdirect.cond; 9752 9753 if (cond != S390_CC_ALWAYS) { 9754 /* So we have something like this 9755 if (cond) do_xdirect; 9756 Y: ... 9757 We convert this into 9758 if (! cond) goto Y; // BRC opcode; 4 bytes 9759 do_xdirect; 9760 Y: 9761 */ 9762 /* 4 bytes (a BRC insn) to be filled in here */ 9763 buf += 4; 9764 } 9765 9766 /* Update the guest IA with the address in xassisted.dst. */ 9767 const s390_amode *amode = insn->variant.xassisted.guest_IA; 9768 9769 vassert(amode->tag == S390_AMODE_B12); 9770 UInt b = hregNumber(amode->b); 9771 UInt d = amode->d; 9772 UInt regno = hregNumber(insn->variant.xassisted.dst); 9773 9774 buf = s390_emit_STG(buf, regno, 0, b, DISP20(d)); 9775 9776 UInt trcval = 0; 9777 9778 switch (insn->variant.xassisted.kind) { 9779 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break; 9780 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break; 9781 case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break; 9782 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break; 9783 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break; 9784 case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break; 9785 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break; 9786 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break; 9787 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break; 9788 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break; 9789 case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break; 9790 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break; 9791 /* We don't expect to see the following being assisted. */ 9792 case Ijk_Ret: 9793 case Ijk_Call: 9794 /* fallthrough */ 9795 default: 9796 ppIRJumpKind(insn->variant.xassisted.kind); 9797 vpanic("s390_insn_xassisted_emit: unexpected jump kind"); 9798 } 9799 9800 vassert(trcval != 0); 9801 9802 /* guest_state_pointer = trcval */ 9803 buf = s390_emit_LGHI(buf, S390_REGNO_GUEST_STATE_POINTER, trcval); 9804 9805 /* load tchain_scratch, #disp_assisted */ 9806 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 9807 Ptr_to_ULong(disp_cp_xassisted)); 9808 9809 /* goto *tchain_direct */ 9810 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); 9811 9812 /* Fix up the conditional jump, if there was one. */ 9813 if (cond != S390_CC_ALWAYS) { 9814 Int delta = buf - ptmp; 9815 9816 delta >>= 1; /* immediate constant is #half-words */ 9817 vassert(delta > 0 && delta < (1 << 16)); 9818 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 9819 } 9820 9821 return buf; 9822 } 9823 9824 9825 /* Pseudo code: 9826 9827 guest_state[host_EvC_COUNTER] -= 1; 9828 if (guest_state[host_EvC_COUNTER] >= 0) goto nofail; 9829 goto guest_state[host_EvC_FAILADDR]; 9830 nofail: ; 9831 9832 The dispatch counter is a 32-bit value. */ 9833 static UChar * 9834 s390_insn_evcheck_emit(UChar *buf, const s390_insn *insn) 9835 { 9836 s390_amode *amode; 9837 UInt b, d; 9838 UChar *code_begin, *code_end; 9839 9840 code_begin = buf; 9841 9842 amode = insn->variant.evcheck.counter; 9843 vassert(amode->tag == S390_AMODE_B12); 9844 b = hregNumber(amode->b); 9845 d = amode->d; 9846 9847 /* Decrement the dispatch counter in the guest state */ 9848 if (s390_host_has_gie) { 9849 buf = s390_emit_ASI(buf, -1, b, DISP20(d)); /* 6 bytes */ 9850 } else { 9851 buf = s390_emit_LHI(buf, R0, -1); /* 4 bytes */ 9852 buf = s390_emit_A(buf, R0, 0, b, d); /* 4 bytes */ 9853 buf = s390_emit_ST(buf, R0, 0, b, d); /* 4 bytes */ 9854 } 9855 9856 /* Jump over the next insn if >= 0 */ 9857 buf = s390_emit_BRC(buf, S390_CC_HE, (4 + 6 + 2) / 2); /* 4 bytes */ 9858 9859 /* Computed goto to fail_address */ 9860 amode = insn->variant.evcheck.fail_addr; 9861 b = hregNumber(amode->b); 9862 d = amode->d; 9863 buf = s390_emit_LG(buf, S390_REGNO_TCHAIN_SCRATCH, 0, b, DISP20(d)); /* 6 bytes */ 9864 buf = s390_emit_BCR(buf, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); /* 2 bytes */ 9865 9866 code_end = buf; 9867 9868 /* Make sure the size of the generated code is identical to the size 9869 returned by evCheckSzB_S390 */ 9870 vassert(evCheckSzB_S390() == code_end - code_begin); 9871 9872 return buf; 9873 } 9874 9875 9876 static UChar * 9877 s390_insn_profinc_emit(UChar *buf, 9878 const s390_insn *insn __attribute__((unused))) 9879 { 9880 /* Generate a code template to increment a memory location whose 9881 address will be known later as an immediate value. This code 9882 template will be patched once the memory location is known. 9883 For now we do this with address == 0. */ 9884 buf = s390_tchain_load64(buf, S390_REGNO_TCHAIN_SCRATCH, 0); 9885 if (s390_host_has_gie) { 9886 buf = s390_emit_AGSI(buf, 1, S390_REGNO_TCHAIN_SCRATCH, DISP20(0)); 9887 } else { 9888 buf = s390_emit_LGHI(buf, R0, 1); 9889 buf = s390_emit_AG( buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0)); 9890 buf = s390_emit_STG(buf, R0, 0, S390_REGNO_TCHAIN_SCRATCH, DISP20(0)); 9891 } 9892 9893 return buf; 9894 } 9895 9896 9897 Int 9898 emit_S390Instr(Bool *is_profinc, UChar *buf, Int nbuf, s390_insn *insn, 9899 Bool mode64, void *disp_cp_chain_me_to_slowEP, 9900 void *disp_cp_chain_me_to_fastEP, void *disp_cp_xindir, 9901 void *disp_cp_xassisted) 9902 { 9903 UChar *end; 9904 9905 /* Used to be 48 bytes. Make sure it stays low */ 9906 vassert(sizeof(s390_insn) == 32); 9907 9908 switch (insn->tag) { 9909 case S390_INSN_LOAD: 9910 end = s390_insn_load_emit(buf, insn); 9911 break; 9912 9913 case S390_INSN_STORE: 9914 end = s390_insn_store_emit(buf, insn); 9915 break; 9916 9917 case S390_INSN_MOVE: 9918 end = s390_insn_move_emit(buf, insn); 9919 break; 9920 9921 case S390_INSN_MEMCPY: 9922 end = s390_insn_memcpy_emit(buf, insn); 9923 break; 9924 9925 case S390_INSN_COND_MOVE: 9926 end = s390_insn_cond_move_emit(buf, insn); 9927 break; 9928 9929 case S390_INSN_LOAD_IMMEDIATE: 9930 end = s390_insn_load_immediate_emit(buf, insn); 9931 break; 9932 9933 case S390_INSN_ALU: 9934 end = s390_insn_alu_emit(buf, insn); 9935 break; 9936 9937 case S390_INSN_SMUL: 9938 case S390_INSN_UMUL: 9939 end = s390_insn_mul_emit(buf, insn); 9940 break; 9941 9942 case S390_INSN_SDIV: 9943 case S390_INSN_UDIV: 9944 end = s390_insn_div_emit(buf, insn); 9945 break; 9946 9947 case S390_INSN_DIVS: 9948 end = s390_insn_divs_emit(buf, insn); 9949 break; 9950 9951 case S390_INSN_CLZ: 9952 end = s390_insn_clz_emit(buf, insn); 9953 break; 9954 9955 case S390_INSN_UNOP: 9956 end = s390_insn_unop_emit(buf, insn); 9957 break; 9958 9959 case S390_INSN_TEST: 9960 end = s390_insn_test_emit(buf, insn); 9961 break; 9962 9963 case S390_INSN_CC2BOOL: 9964 end = s390_insn_cc2bool_emit(buf, insn); 9965 break; 9966 9967 case S390_INSN_CAS: 9968 end = s390_insn_cas_emit(buf, insn); 9969 break; 9970 9971 case S390_INSN_CDAS: 9972 end = s390_insn_cdas_emit(buf, insn); 9973 break; 9974 9975 case S390_INSN_COMPARE: 9976 end = s390_insn_compare_emit(buf, insn); 9977 break; 9978 9979 case S390_INSN_HELPER_CALL: 9980 end = s390_insn_helper_call_emit(buf, insn); 9981 if (end == buf) goto fail; 9982 break; 9983 9984 case S390_INSN_BFP_TRIOP: 9985 end = s390_insn_bfp_triop_emit(buf, insn); 9986 break; 9987 9988 case S390_INSN_BFP_BINOP: 9989 end = s390_insn_bfp_binop_emit(buf, insn); 9990 break; 9991 9992 case S390_INSN_BFP_UNOP: 9993 end = s390_insn_bfp_unop_emit(buf, insn); 9994 break; 9995 9996 case S390_INSN_BFP_COMPARE: 9997 end = s390_insn_bfp_compare_emit(buf, insn); 9998 break; 9999 10000 case S390_INSN_BFP_CONVERT: 10001 end = s390_insn_bfp_convert_emit(buf, insn); 10002 break; 10003 10004 case S390_INSN_DFP_BINOP: 10005 end = s390_insn_dfp_binop_emit(buf, insn); 10006 break; 10007 10008 case S390_INSN_DFP_UNOP: 10009 end = s390_insn_dfp_unop_emit(buf, insn); 10010 break; 10011 10012 case S390_INSN_DFP_INTOP: 10013 end = s390_insn_dfp_intop_emit(buf, insn); 10014 break; 10015 10016 case S390_INSN_DFP_COMPARE: 10017 end = s390_insn_dfp_compare_emit(buf, insn); 10018 break; 10019 10020 case S390_INSN_DFP_CONVERT: 10021 end = s390_insn_dfp_convert_emit(buf, insn); 10022 break; 10023 10024 case S390_INSN_DFP_REROUND: 10025 end = s390_insn_dfp_reround_emit(buf, insn); 10026 break; 10027 10028 case S390_INSN_FP_CONVERT: 10029 end = s390_insn_fp_convert_emit(buf, insn); 10030 break; 10031 10032 case S390_INSN_MFENCE: 10033 end = s390_insn_mfence_emit(buf, insn); 10034 break; 10035 10036 case S390_INSN_MIMM: 10037 end = s390_insn_mimm_emit(buf, insn); 10038 break; 10039 10040 case S390_INSN_MADD: 10041 end = s390_insn_madd_emit(buf, insn); 10042 break; 10043 10044 case S390_INSN_SET_FPC_BFPRM: 10045 end = s390_insn_set_fpc_bfprm_emit(buf, insn); 10046 break; 10047 10048 case S390_INSN_SET_FPC_DFPRM: 10049 end = s390_insn_set_fpc_dfprm_emit(buf, insn); 10050 break; 10051 10052 case S390_INSN_PROFINC: 10053 end = s390_insn_profinc_emit(buf, insn); 10054 /* Tell the caller .. */ 10055 vassert(*is_profinc == False); 10056 *is_profinc = True; 10057 break; 10058 10059 case S390_INSN_EVCHECK: 10060 end = s390_insn_evcheck_emit(buf, insn); 10061 break; 10062 10063 case S390_INSN_XDIRECT: 10064 end = s390_insn_xdirect_emit(buf, insn, disp_cp_chain_me_to_slowEP, 10065 disp_cp_chain_me_to_fastEP); 10066 break; 10067 10068 case S390_INSN_XINDIR: 10069 end = s390_insn_xindir_emit(buf, insn, disp_cp_xindir); 10070 break; 10071 10072 case S390_INSN_XASSISTED: 10073 end = s390_insn_xassisted_emit(buf, insn, disp_cp_xassisted); 10074 break; 10075 10076 fail: 10077 default: 10078 vpanic("emit_S390Instr"); 10079 } 10080 10081 vassert(end - buf <= nbuf); 10082 10083 return end - buf; 10084 } 10085 10086 10087 /* Return the number of bytes emitted for an S390_INSN_EVCHECK. 10088 See s390_insn_evcheck_emit */ 10089 Int 10090 evCheckSzB_S390(void) 10091 { 10092 return s390_host_has_gie ? 18 : 24; 10093 } 10094 10095 10096 /* Patch the counter address into CODE_TO_PATCH as previously 10097 generated by s390_insn_profinc_emit. */ 10098 VexInvalRange 10099 patchProfInc_S390(void *code_to_patch, ULong *location_of_counter) 10100 { 10101 vassert(sizeof(ULong *) == 8); 10102 10103 s390_tchain_verify_load64(code_to_patch, S390_REGNO_TCHAIN_SCRATCH, 0); 10104 10105 UChar *p = s390_tchain_patch_load64(code_to_patch, 10106 Ptr_to_ULong(location_of_counter)); 10107 10108 UInt len = p - (UChar *)code_to_patch; 10109 VexInvalRange vir = { (HWord)code_to_patch, len }; 10110 return vir; 10111 } 10112 10113 10114 /* NB: what goes on here has to be very closely coordinated with the 10115 s390_insn_xdirect_emit code above. */ 10116 VexInvalRange 10117 chainXDirect_S390(void *place_to_chain, 10118 void *disp_cp_chain_me_EXPECTED, 10119 void *place_to_jump_to) 10120 { 10121 /* What we're expecting to see @ PLACE_TO_CHAIN is: 10122 10123 load tchain_scratch, #disp_cp_chain_me_EXPECTED 10124 goto *tchain_scratch 10125 */ 10126 const UChar *next; 10127 next = s390_tchain_verify_load64(place_to_chain, S390_REGNO_TCHAIN_SCRATCH, 10128 Ptr_to_ULong(disp_cp_chain_me_EXPECTED)); 10129 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH)); 10130 10131 /* And what we want to change it to is either: 10132 (general case): 10133 10134 load tchain_scratch, #place_to_jump_to 10135 goto *tchain_scratch 10136 10137 ---OR--- 10138 10139 in the case where the displacement is small enough 10140 10141 BRCL delta where delta is in half-words 10142 invalid opcodes 10143 10144 In both cases the replacement has the same length as the original. 10145 To remain sane & verifiable, 10146 (1) limit the displacement for the short form to 10147 (say) +/- one billion, so as to avoid wraparound 10148 off-by-ones 10149 (2) even if the short form is applicable, once every (say) 10150 1024 times use the long form anyway, so as to maintain 10151 verifiability 10152 */ 10153 10154 /* This is the delta we need to put into a BRCL insn. Note, that the 10155 offset in BRCL is in half-words. Hence division by 2. */ 10156 Long delta = (Long)((UChar *)place_to_jump_to - (UChar *)place_to_chain) / 2; 10157 Bool shortOK = delta >= -1000*1000*1000 && delta < 1000*1000*1000; 10158 10159 static UInt shortCTR = 0; /* DO NOT MAKE NON-STATIC */ 10160 if (shortOK) { 10161 shortCTR++; // thread safety bleh 10162 if (0 == (shortCTR & 0x3FF)) { 10163 shortOK = False; 10164 if (0) 10165 vex_printf("QQQ chainXDirect_S390: shortCTR = %u, " 10166 "using long jmp\n", shortCTR); 10167 } 10168 } 10169 10170 /* And make the modifications. */ 10171 UChar *p = (UChar *)place_to_chain; 10172 if (shortOK) { 10173 p = s390_emit_BRCL(p, S390_CC_ALWAYS, delta); /* 6 bytes */ 10174 10175 /* Make sure that BRCL fits into the patchable part of an xdirect 10176 code sequence */ 10177 vassert(6 <= s390_xdirect_patchable_len()); 10178 10179 /* Fill remaining bytes with 0x00 (invalid opcode) */ 10180 Int i; 10181 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i) 10182 p[i] = 0x00; 10183 } else { 10184 /* 10185 load tchain_scratch, #place_to_jump_to 10186 goto *tchain_scratch 10187 */ 10188 ULong addr = Ptr_to_ULong(place_to_jump_to); 10189 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr); 10190 /* There is not need to emit a BCR here, as it is already there. */ 10191 } 10192 10193 UInt len = p - (UChar *)place_to_chain; 10194 VexInvalRange vir = { (HWord)place_to_chain, len }; 10195 return vir; 10196 } 10197 10198 10199 /* NB: what goes on here has to be very closely coordinated with the 10200 s390_insn_xdirect_emit code above. */ 10201 VexInvalRange 10202 unchainXDirect_S390(void *place_to_unchain, 10203 void *place_to_jump_to_EXPECTED, 10204 void *disp_cp_chain_me) 10205 { 10206 /* What we're expecting to see @ PLACE_TO_UNCHAIN: 10207 10208 load tchain_scratch, #place_to_jump_to_EXPECTED 10209 goto *tchain_scratch 10210 10211 ---OR--- 10212 in the case where the displacement falls within 32 bits 10213 10214 BRCL delta 10215 invalid opcodes 10216 */ 10217 UChar *p = place_to_unchain; 10218 10219 Bool uses_short_form = False; 10220 10221 if (s390_insn_is_BRCL(p, S390_CC_ALWAYS)) { 10222 /* Looks like the short form */ 10223 Int num_hw = *(Int *)&p[2]; 10224 Int delta = 2 *num_hw; 10225 10226 vassert(p + delta == place_to_jump_to_EXPECTED); 10227 10228 Int i; 10229 for (i = 0; i < s390_xdirect_patchable_len() - 6; ++i) 10230 vassert(p[6+i] == 0x00); 10231 uses_short_form = True; 10232 } else { 10233 /* Should be the long form */ 10234 const UChar *next; 10235 10236 next = s390_tchain_verify_load64(p, S390_REGNO_TCHAIN_SCRATCH, 10237 Ptr_to_ULong(place_to_jump_to_EXPECTED)); 10238 /* Check for BR *tchain_scratch */ 10239 vassert(s390_insn_is_BR(next, S390_REGNO_TCHAIN_SCRATCH)); 10240 } 10241 10242 /* And what we want to change it to is: 10243 10244 load tchain_scratch, #disp_cp_chain_me 10245 goto *tchain_scratch 10246 */ 10247 10248 /* Get the address of the beginning of the load64 code sequence into %r1. 10249 Do not change the register! This is part of the protocol with the 10250 dispatcher. 10251 Note: the incoming argument PLACE_TO_CHAIN points to the beginning of the 10252 load64 insn sequence. That sequence is prefixed with a BASR to get its 10253 address (see s390_insn_xdirect_emit). */ 10254 p = s390_emit_BASR(p - S390_BASR_LEN, 1, R0); 10255 10256 ULong addr = Ptr_to_ULong(disp_cp_chain_me); 10257 p = s390_tchain_load64(p, S390_REGNO_TCHAIN_SCRATCH, addr); 10258 10259 /* Emit the BCR in case the short form was used. In case of the long 10260 form, the BCR is already there. */ 10261 if (uses_short_form) 10262 s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_TCHAIN_SCRATCH); 10263 10264 UInt len = p - (UChar *)place_to_unchain; 10265 VexInvalRange vir = { (HWord)place_to_unchain, len }; 10266 return vir; 10267 } 10268 10269 /*---------------------------------------------------------------*/ 10270 /*--- end host_s390_defs.c ---*/ 10271 /*---------------------------------------------------------------*/ 10272