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-2011 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 /* Contributed by Florian Krohm */ 32 33 #include "libvex_basictypes.h" 34 #include "libvex.h" 35 #include "libvex_trc_values.h" 36 #include "libvex_guest_offsets.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 "host_s390_disasm.h" 44 #include <stdarg.h> 45 46 /* KLUDGE: We need to know the hwcaps of the host when generating 47 code. But that info is not passed to emit_S390Instr. Only mode64 is 48 being passed. So, ideally, we want this passed as an argument, too. 49 Until then, we use a global variable. This variable is set as a side 50 effect of iselSB_S390. This is safe because instructions are selected 51 before they are emitted. */ 52 const VexArchInfo *s390_archinfo_host; 53 54 55 /*------------------------------------------------------------*/ 56 /*--- Forward declarations ---*/ 57 /*------------------------------------------------------------*/ 58 59 static Bool s390_insn_is_reg_reg_move(const s390_insn *, HReg *src, HReg *dst); 60 static void s390_insn_map_regs(HRegRemap *, s390_insn *); 61 static void s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *); 62 63 64 /*------------------------------------------------------------*/ 65 /*--- Registers ---*/ 66 /*------------------------------------------------------------*/ 67 68 /* Decompile the given register into a static buffer and return it */ 69 const HChar * 70 s390_hreg_as_string(HReg reg) 71 { 72 static HChar buf[10]; 73 74 static const HChar ireg_names[16][5] = { 75 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", 76 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 77 }; 78 79 static const HChar freg_names[16][5] = { 80 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", 81 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15" 82 }; 83 84 UInt r; /* hregNumber() returns an UInt */ 85 86 r = hregNumber(reg); 87 88 /* Be generic for all virtual regs. */ 89 if (hregIsVirtual(reg)) { 90 buf[0] = '\0'; 91 switch (hregClass(reg)) { 92 case HRcInt64: vex_sprintf(buf, "%%vR%d", r); break; 93 case HRcFlt64: vex_sprintf(buf, "%%vF%d", r); break; 94 default: goto fail; 95 } 96 return buf; 97 } 98 99 /* But specific for real regs. */ 100 vassert(r < 16); 101 102 switch (hregClass(reg)) { 103 case HRcInt64: return ireg_names[r]; 104 case HRcFlt64: return freg_names[r]; 105 default: goto fail; 106 } 107 108 fail: vpanic("s390_hreg_as_string"); 109 } 110 111 112 /* Tell the register allocator which registers can be allocated. */ 113 static void 114 s390_hreg_get_allocable(Int *nregs, HReg **arr) 115 { 116 UInt i; 117 118 /* Total number of allocable registers (all classes) */ 119 *nregs = 16 /* GPRs */ 120 - 1 /* r0 */ 121 - 1 /* r12 register holding VG_(dispatch_ctr) */ 122 - 1 /* r13 guest state pointer */ 123 - 1 /* r14 link register */ 124 - 1 /* r15 stack pointer */ 125 + 16 /* FPRs */ 126 ; 127 128 *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); 129 130 i = 0; 131 132 /* GPR0 is not available because it is interpreted as 0, when used 133 as a base or index register. */ 134 (*arr)[i++] = mkHReg(1, HRcInt64, False); 135 (*arr)[i++] = mkHReg(2, HRcInt64, False); 136 (*arr)[i++] = mkHReg(3, HRcInt64, False); 137 (*arr)[i++] = mkHReg(4, HRcInt64, False); 138 (*arr)[i++] = mkHReg(5, HRcInt64, False); 139 (*arr)[i++] = mkHReg(6, HRcInt64, False); 140 (*arr)[i++] = mkHReg(7, HRcInt64, False); 141 (*arr)[i++] = mkHReg(8, HRcInt64, False); 142 (*arr)[i++] = mkHReg(9, HRcInt64, False); 143 /* GPR10 and GPR11 are used for instructions that use register pairs. 144 Otherwise, they are available to the allocator */ 145 (*arr)[i++] = mkHReg(10, HRcInt64, False); 146 (*arr)[i++] = mkHReg(11, HRcInt64, False); 147 /* GPR12 is not available because it caches VG_(dispatch_ctr) */ 148 /* GPR13 is not available because it is used as guest state pointer */ 149 /* GPR14 is not available because it is used as link register */ 150 /* GPR15 is not available because it is used as stack pointer */ 151 152 /* Add the available real (non-virtual) FPRs */ 153 (*arr)[i++] = mkHReg(0, HRcFlt64, False); 154 (*arr)[i++] = mkHReg(1, HRcFlt64, False); 155 (*arr)[i++] = mkHReg(2, HRcFlt64, False); 156 (*arr)[i++] = mkHReg(3, HRcFlt64, False); 157 (*arr)[i++] = mkHReg(4, HRcFlt64, False); 158 (*arr)[i++] = mkHReg(5, HRcFlt64, False); 159 (*arr)[i++] = mkHReg(6, HRcFlt64, False); 160 (*arr)[i++] = mkHReg(7, HRcFlt64, False); 161 (*arr)[i++] = mkHReg(8, HRcFlt64, False); 162 (*arr)[i++] = mkHReg(9, HRcFlt64, False); 163 (*arr)[i++] = mkHReg(10, HRcFlt64, False); 164 (*arr)[i++] = mkHReg(11, HRcFlt64, False); 165 (*arr)[i++] = mkHReg(12, HRcFlt64, False); 166 (*arr)[i++] = mkHReg(13, HRcFlt64, False); 167 (*arr)[i++] = mkHReg(14, HRcFlt64, False); 168 (*arr)[i++] = mkHReg(15, HRcFlt64, False); 169 /* FPR12 - FPR15 are also used as register pairs for 128-bit 170 floating point operations */ 171 } 172 173 174 /* Return the real register that holds the guest state pointer */ 175 HReg 176 s390_hreg_guest_state_pointer(void) 177 { 178 return mkHReg(S390_REGNO_GUEST_STATE_POINTER, HRcInt64, False); 179 } 180 181 /* Is VALUE within the domain of a 20-bit signed integer. */ 182 static __inline__ Bool 183 fits_signed_20bit(Int value) 184 { 185 return ((value << 12) >> 12) == value; 186 } 187 188 189 /* Is VALUE within the domain of a 12-bit unsigned integer. */ 190 static __inline__ Bool 191 fits_unsigned_12bit(Int value) 192 { 193 return (value & 0xFFF) == value; 194 } 195 196 /*------------------------------------------------------------*/ 197 /*--- Addressing modes (amodes) ---*/ 198 /*------------------------------------------------------------*/ 199 200 /* Construct a b12 amode. */ 201 s390_amode * 202 s390_amode_b12(Int d, HReg b) 203 { 204 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 205 206 vassert(fits_unsigned_12bit(d)); 207 208 am->tag = S390_AMODE_B12; 209 am->d = d; 210 am->b = b; 211 am->x = 0; /* hregNumber(0) == 0 */ 212 213 return am; 214 } 215 216 217 /* Construct a b20 amode. */ 218 s390_amode * 219 s390_amode_b20(Int d, HReg b) 220 { 221 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 222 223 vassert(fits_signed_20bit(d)); 224 225 am->tag = S390_AMODE_B20; 226 am->d = d; 227 am->b = b; 228 am->x = 0; /* hregNumber(0) == 0 */ 229 230 return am; 231 } 232 233 234 /* Construct a bx12 amode. */ 235 s390_amode * 236 s390_amode_bx12(Int d, HReg b, HReg x) 237 { 238 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 239 240 vassert(fits_unsigned_12bit(d)); 241 vassert(b != 0); 242 vassert(x != 0); 243 244 am->tag = S390_AMODE_BX12; 245 am->d = d; 246 am->b = b; 247 am->x = x; 248 249 return am; 250 } 251 252 253 /* Construct a bx20 amode. */ 254 s390_amode * 255 s390_amode_bx20(Int d, HReg b, HReg x) 256 { 257 s390_amode *am = LibVEX_Alloc(sizeof(s390_amode)); 258 259 vassert(fits_signed_20bit(d)); 260 vassert(b != 0); 261 vassert(x != 0); 262 263 am->tag = S390_AMODE_BX20; 264 am->d = d; 265 am->b = b; 266 am->x = x; 267 268 return am; 269 } 270 271 272 /* Construct an AMODE for accessing the guest state at OFFSET */ 273 s390_amode * 274 s390_amode_for_guest_state(Int offset) 275 { 276 if (fits_unsigned_12bit(offset)) 277 return s390_amode_b12(offset, s390_hreg_guest_state_pointer()); 278 279 vpanic("invalid guest state offset"); 280 } 281 282 283 /* Decompile the given amode into a static buffer and return it. */ 284 const HChar * 285 s390_amode_as_string(const s390_amode *am) 286 { 287 static HChar buf[30]; 288 HChar *p; 289 290 buf[0] = '\0'; 291 p = buf; 292 293 switch (am->tag) { 294 case S390_AMODE_B12: 295 case S390_AMODE_B20: 296 vex_sprintf(p, "%d(%s)", am->d, s390_hreg_as_string(am->b)); 297 break; 298 299 case S390_AMODE_BX12: 300 case S390_AMODE_BX20: 301 /* s390_hreg_as_string returns pointer to local buffer. Need to 302 split this into two printfs */ 303 p += vex_sprintf(p, "%d(%s,", am->d, s390_hreg_as_string(am->x)); 304 vex_sprintf(p, "%s)", s390_hreg_as_string(am->b)); 305 break; 306 307 default: 308 vpanic("s390_amode_as_string"); 309 } 310 311 return buf; 312 } 313 314 315 /* Helper function for s390_amode_is_sane */ 316 static __inline__ Bool 317 is_virtual_gpr(HReg reg) 318 { 319 return hregIsVirtual(reg) && hregClass(reg) == HRcInt64; 320 } 321 322 323 /* Sanity check for an amode */ 324 Bool 325 s390_amode_is_sane(const s390_amode *am) 326 { 327 switch (am->tag) { 328 case S390_AMODE_B12: 329 return is_virtual_gpr(am->b) && fits_unsigned_12bit(am->d); 330 331 case S390_AMODE_B20: 332 return is_virtual_gpr(am->b) && fits_signed_20bit(am->d); 333 334 case S390_AMODE_BX12: 335 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) && 336 fits_unsigned_12bit(am->d); 337 338 case S390_AMODE_BX20: 339 return is_virtual_gpr(am->b) && is_virtual_gpr(am->x) && 340 fits_signed_20bit(am->d); 341 342 default: 343 vpanic("s390_amode_is_sane"); 344 } 345 } 346 347 348 /* Record the register use of an amode */ 349 static void 350 s390_amode_get_reg_usage(HRegUsage *u, const s390_amode *am) 351 { 352 switch (am->tag) { 353 case S390_AMODE_B12: 354 case S390_AMODE_B20: 355 addHRegUse(u, HRmRead, am->b); 356 return; 357 358 case S390_AMODE_BX12: 359 case S390_AMODE_BX20: 360 addHRegUse(u, HRmRead, am->b); 361 addHRegUse(u, HRmRead, am->x); 362 return; 363 364 default: 365 vpanic("s390_amode_get_reg_usage"); 366 } 367 } 368 369 370 static void 371 s390_amode_map_regs(HRegRemap *m, s390_amode *am) 372 { 373 switch (am->tag) { 374 case S390_AMODE_B12: 375 case S390_AMODE_B20: 376 am->b = lookupHRegRemap(m, am->b); 377 return; 378 379 case S390_AMODE_BX12: 380 case S390_AMODE_BX20: 381 am->b = lookupHRegRemap(m, am->b); 382 am->x = lookupHRegRemap(m, am->x); 383 return; 384 385 default: 386 vpanic("s390_amode_map_regs"); 387 } 388 } 389 390 391 void 392 ppS390AMode(s390_amode *am) 393 { 394 vex_printf("%s", s390_amode_as_string(am)); 395 } 396 397 void 398 ppS390Instr(s390_insn *insn, Bool mode64) 399 { 400 vex_printf("%s", s390_insn_as_string(insn)); 401 } 402 403 void 404 ppHRegS390(HReg reg) 405 { 406 vex_printf("%s", s390_hreg_as_string(reg)); 407 } 408 409 /*------------------------------------------------------------*/ 410 /*--- Helpers for register allocation ---*/ 411 /*------------------------------------------------------------*/ 412 413 /* Called once per translation. */ 414 void 415 getAllocableRegs_S390(Int *nregs, HReg **arr, Bool mode64) 416 { 417 s390_hreg_get_allocable(nregs, arr); 418 } 419 420 421 /* Tell the register allocator how the given instruction uses the registers 422 it refers to. */ 423 void 424 getRegUsage_S390Instr(HRegUsage *u, s390_insn *insn, Bool mode64) 425 { 426 s390_insn_get_reg_usage(u, insn); 427 } 428 429 430 /* Map the registers of the given instruction */ 431 void 432 mapRegs_S390Instr(HRegRemap *m, s390_insn *insn, Bool mode64) 433 { 434 s390_insn_map_regs(m, insn); 435 } 436 437 438 /* Figure out if the given insn represents a reg-reg move, and if so 439 assign the source and destination to *src and *dst. If in doubt say No. 440 Used by the register allocator to do move coalescing. */ 441 Bool 442 isMove_S390Instr(s390_insn *insn, HReg *src, HReg *dst) 443 { 444 return s390_insn_is_reg_reg_move(insn, src, dst); 445 } 446 447 448 /* Generate s390 spill/reload instructions under the direction of the 449 register allocator. Note it's critical these don't write the 450 condition codes. This is like an Ist_Put */ 451 void 452 genSpill_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64) 453 { 454 s390_amode *am; 455 456 vassert(offsetB >= 0); 457 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */ 458 vassert(!hregIsVirtual(rreg)); 459 460 *i1 = *i2 = NULL; 461 462 am = s390_amode_for_guest_state(offsetB); 463 464 switch (hregClass(rreg)) { 465 case HRcInt64: 466 case HRcFlt64: 467 *i1 = s390_insn_store(8, am, rreg); 468 return; 469 470 default: 471 ppHRegClass(hregClass(rreg)); 472 vpanic("genSpill_S390: unimplemented regclass"); 473 } 474 } 475 476 477 /* This is like an Iex_Get */ 478 void 479 genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64) 480 { 481 s390_amode *am; 482 483 vassert(offsetB >= 0); 484 vassert(offsetB <= (1 << 12)); /* because we use b12 amode */ 485 vassert(!hregIsVirtual(rreg)); 486 487 *i1 = *i2 = NULL; 488 489 am = s390_amode_for_guest_state(offsetB); 490 491 switch (hregClass(rreg)) { 492 case HRcInt64: 493 case HRcFlt64: 494 *i1 = s390_insn_load(8, rreg, am); 495 return; 496 497 default: 498 ppHRegClass(hregClass(rreg)); 499 vpanic("genReload_S390: unimplemented regclass"); 500 } 501 } 502 503 /* Helper function for s390_insn_get_reg_usage */ 504 static void 505 s390_opnd_RMI_get_reg_usage(HRegUsage *u, s390_opnd_RMI op) 506 { 507 switch (op.tag) { 508 case S390_OPND_REG: 509 addHRegUse(u, HRmRead, op.variant.reg); 510 break; 511 512 case S390_OPND_AMODE: 513 s390_amode_get_reg_usage(u, op.variant.am); 514 break; 515 516 case S390_OPND_IMMEDIATE: 517 break; 518 519 default: 520 vpanic("s390_opnd_RMI_get_reg_usage"); 521 } 522 } 523 524 525 /* Tell the register allocator how the given insn uses the registers */ 526 static void 527 s390_insn_get_reg_usage(HRegUsage *u, const s390_insn *insn) 528 { 529 initHRegUsage(u); 530 531 switch (insn->tag) { 532 case S390_INSN_LOAD: 533 addHRegUse(u, HRmWrite, insn->variant.load.dst); 534 s390_amode_get_reg_usage(u, insn->variant.load.src); 535 break; 536 537 case S390_INSN_LOAD_IMMEDIATE: 538 addHRegUse(u, HRmWrite, insn->variant.load_immediate.dst); 539 break; 540 541 case S390_INSN_STORE: 542 addHRegUse(u, HRmRead, insn->variant.store.src); 543 s390_amode_get_reg_usage(u, insn->variant.store.dst); 544 break; 545 546 case S390_INSN_MOVE: 547 addHRegUse(u, HRmRead, insn->variant.move.src); 548 addHRegUse(u, HRmWrite, insn->variant.move.dst); 549 break; 550 551 case S390_INSN_COND_MOVE: 552 s390_opnd_RMI_get_reg_usage(u, insn->variant.cond_move.src); 553 addHRegUse(u, HRmWrite, insn->variant.cond_move.dst); 554 break; 555 556 case S390_INSN_ALU: 557 addHRegUse(u, HRmWrite, insn->variant.alu.dst); 558 addHRegUse(u, HRmRead, insn->variant.alu.dst); /* op1 */ 559 s390_opnd_RMI_get_reg_usage(u, insn->variant.alu.op2); 560 break; 561 562 case S390_INSN_MUL: 563 addHRegUse(u, HRmRead, insn->variant.mul.dst_lo); /* op1 */ 564 addHRegUse(u, HRmWrite, insn->variant.mul.dst_lo); 565 addHRegUse(u, HRmWrite, insn->variant.mul.dst_hi); 566 s390_opnd_RMI_get_reg_usage(u, insn->variant.mul.op2); 567 break; 568 569 case S390_INSN_DIV: 570 addHRegUse(u, HRmRead, insn->variant.div.op1_lo); 571 addHRegUse(u, HRmRead, insn->variant.div.op1_hi); 572 addHRegUse(u, HRmWrite, insn->variant.div.op1_lo); 573 addHRegUse(u, HRmWrite, insn->variant.div.op1_hi); 574 s390_opnd_RMI_get_reg_usage(u, insn->variant.div.op2); 575 break; 576 577 case S390_INSN_DIVS: 578 addHRegUse(u, HRmRead, insn->variant.divs.op1); 579 addHRegUse(u, HRmWrite, insn->variant.divs.op1); /* quotient */ 580 addHRegUse(u, HRmWrite, insn->variant.divs.rem); /* remainder */ 581 s390_opnd_RMI_get_reg_usage(u, insn->variant.divs.op2); 582 break; 583 584 case S390_INSN_CLZ: 585 addHRegUse(u, HRmWrite, insn->variant.clz.num_bits); 586 addHRegUse(u, HRmWrite, insn->variant.clz.clobber); 587 s390_opnd_RMI_get_reg_usage(u, insn->variant.clz.src); 588 break; 589 590 case S390_INSN_UNOP: 591 addHRegUse(u, HRmWrite, insn->variant.unop.dst); 592 s390_opnd_RMI_get_reg_usage(u, insn->variant.unop.src); 593 break; 594 595 case S390_INSN_TEST: 596 s390_opnd_RMI_get_reg_usage(u, insn->variant.test.src); 597 break; 598 599 case S390_INSN_CC2BOOL: 600 addHRegUse(u, HRmWrite, insn->variant.cc2bool.dst); 601 break; 602 603 case S390_INSN_CAS: 604 addHRegUse(u, HRmRead, insn->variant.cas.op1); 605 s390_amode_get_reg_usage(u, insn->variant.cas.op2); 606 addHRegUse(u, HRmRead, insn->variant.cas.op3); 607 addHRegUse(u, HRmWrite, insn->variant.cas.old_mem); 608 break; 609 610 case S390_INSN_COMPARE: 611 addHRegUse(u, HRmRead, insn->variant.compare.src1); 612 s390_opnd_RMI_get_reg_usage(u, insn->variant.compare.src2); 613 break; 614 615 case S390_INSN_BRANCH: 616 s390_opnd_RMI_get_reg_usage(u, insn->variant.branch.dst); 617 /* The destination address is loaded into S390_REGNO_RETURN_VALUE. 618 See s390_insn_branch_emit. */ 619 addHRegUse(u, HRmWrite, 620 mkHReg(S390_REGNO_RETURN_VALUE, HRcInt64, False)); 621 break; 622 623 case S390_INSN_HELPER_CALL: { 624 UInt i; 625 626 /* Assume that all volatile registers are clobbered. ABI says, 627 volatile registers are: r0 - r5. Valgrind's register allocator 628 does not know about r0, so we can leave that out */ 629 for (i = 1; i <= 5; ++i) { 630 addHRegUse(u, HRmWrite, mkHReg(i, HRcInt64, False)); 631 } 632 633 /* Ditto for floating point registers. f0 - f7 are volatile */ 634 for (i = 0; i <= 7; ++i) { 635 addHRegUse(u, HRmWrite, mkHReg(i, HRcFlt64, False)); 636 } 637 638 /* The registers that are used for passing arguments will be read. 639 Not all of them may, but in general we need to assume that. */ 640 for (i = 0; i < insn->variant.helper_call.num_args; ++i) { 641 addHRegUse(u, HRmRead, mkHReg(s390_gprno_from_arg_index(i), 642 HRcInt64, False)); 643 } 644 645 /* s390_insn_helper_call_emit also reads / writes the link register 646 and stack pointer. But those registers are not visible to the 647 register allocator. So we don't need to do anything for them. */ 648 break; 649 } 650 651 case S390_INSN_BFP_TRIOP: 652 addHRegUse(u, HRmWrite, insn->variant.bfp_triop.dst); 653 addHRegUse(u, HRmRead, insn->variant.bfp_triop.dst); /* first */ 654 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op2); /* second */ 655 addHRegUse(u, HRmRead, insn->variant.bfp_triop.op3); /* third */ 656 break; 657 658 case S390_INSN_BFP_BINOP: 659 addHRegUse(u, HRmWrite, insn->variant.bfp_binop.dst); 660 addHRegUse(u, HRmRead, insn->variant.bfp_binop.dst); /* left */ 661 addHRegUse(u, HRmRead, insn->variant.bfp_binop.op2); /* right */ 662 break; 663 664 case S390_INSN_BFP_UNOP: 665 addHRegUse(u, HRmWrite, insn->variant.bfp_unop.dst); 666 addHRegUse(u, HRmRead, insn->variant.bfp_unop.op); /* operand */ 667 break; 668 669 case S390_INSN_BFP_COMPARE: 670 addHRegUse(u, HRmWrite, insn->variant.bfp_compare.dst); 671 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op1); /* left */ 672 addHRegUse(u, HRmRead, insn->variant.bfp_compare.op2); /* right */ 673 break; 674 675 case S390_INSN_BFP128_BINOP: 676 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_hi); 677 addHRegUse(u, HRmWrite, insn->variant.bfp128_binop.dst_lo); 678 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_hi); /* left */ 679 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.dst_lo); /* left */ 680 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_hi); /* right */ 681 addHRegUse(u, HRmRead, insn->variant.bfp128_binop.op2_lo); /* right */ 682 break; 683 684 case S390_INSN_BFP128_COMPARE: 685 addHRegUse(u, HRmWrite, insn->variant.bfp128_compare.dst); 686 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_hi); /* left */ 687 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op1_lo); /* left */ 688 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_hi); /* right */ 689 addHRegUse(u, HRmRead, insn->variant.bfp128_compare.op2_lo); /* right */ 690 break; 691 692 case S390_INSN_BFP128_UNOP: 693 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi); 694 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo); 695 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi); 696 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo); 697 break; 698 699 case S390_INSN_BFP128_CONVERT_TO: 700 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi); 701 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_lo); 702 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi); 703 break; 704 705 case S390_INSN_BFP128_CONVERT_FROM: 706 addHRegUse(u, HRmWrite, insn->variant.bfp128_unop.dst_hi); 707 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_hi); 708 addHRegUse(u, HRmRead, insn->variant.bfp128_unop.op_lo); 709 break; 710 711 case S390_INSN_MFENCE: 712 break; 713 714 default: 715 vpanic("s390_insn_get_reg_usage"); 716 } 717 } 718 719 720 /* Helper function for s390_insn_map_regs */ 721 static void 722 s390_opnd_RMI_map_regs(HRegRemap *m, s390_opnd_RMI *op) 723 { 724 switch (op->tag) { 725 case S390_OPND_REG: 726 op->variant.reg = lookupHRegRemap(m, op->variant.reg); 727 break; 728 729 case S390_OPND_IMMEDIATE: 730 break; 731 732 case S390_OPND_AMODE: 733 s390_amode_map_regs(m, op->variant.am); 734 break; 735 736 default: 737 vpanic("s390_opnd_RMI_map_regs"); 738 } 739 } 740 741 742 static void 743 s390_insn_map_regs(HRegRemap *m, s390_insn *insn) 744 { 745 switch (insn->tag) { 746 case S390_INSN_LOAD: 747 insn->variant.load.dst = lookupHRegRemap(m, insn->variant.load.dst); 748 s390_amode_map_regs(m, insn->variant.load.src); 749 break; 750 751 case S390_INSN_STORE: 752 s390_amode_map_regs(m, insn->variant.store.dst); 753 insn->variant.store.src = lookupHRegRemap(m, insn->variant.store.src); 754 break; 755 756 case S390_INSN_MOVE: 757 insn->variant.move.dst = lookupHRegRemap(m, insn->variant.move.dst); 758 insn->variant.move.src = lookupHRegRemap(m, insn->variant.move.src); 759 break; 760 761 case S390_INSN_COND_MOVE: 762 insn->variant.cond_move.dst = lookupHRegRemap(m, insn->variant.cond_move.dst); 763 s390_opnd_RMI_map_regs(m, &insn->variant.cond_move.src); 764 break; 765 766 case S390_INSN_LOAD_IMMEDIATE: 767 insn->variant.load_immediate.dst = 768 lookupHRegRemap(m, insn->variant.load_immediate.dst); 769 break; 770 771 case S390_INSN_ALU: 772 insn->variant.alu.dst = lookupHRegRemap(m, insn->variant.alu.dst); 773 s390_opnd_RMI_map_regs(m, &insn->variant.alu.op2); 774 break; 775 776 case S390_INSN_MUL: 777 insn->variant.mul.dst_hi = lookupHRegRemap(m, insn->variant.mul.dst_hi); 778 insn->variant.mul.dst_lo = lookupHRegRemap(m, insn->variant.mul.dst_lo); 779 s390_opnd_RMI_map_regs(m, &insn->variant.mul.op2); 780 break; 781 782 case S390_INSN_DIV: 783 insn->variant.div.op1_hi = lookupHRegRemap(m, insn->variant.div.op1_hi); 784 insn->variant.div.op1_lo = lookupHRegRemap(m, insn->variant.div.op1_lo); 785 s390_opnd_RMI_map_regs(m, &insn->variant.div.op2); 786 break; 787 788 case S390_INSN_DIVS: 789 insn->variant.divs.op1 = lookupHRegRemap(m, insn->variant.divs.op1); 790 insn->variant.divs.rem = lookupHRegRemap(m, insn->variant.divs.rem); 791 s390_opnd_RMI_map_regs(m, &insn->variant.divs.op2); 792 break; 793 794 case S390_INSN_CLZ: 795 insn->variant.clz.num_bits = lookupHRegRemap(m, insn->variant.clz.num_bits); 796 insn->variant.clz.clobber = lookupHRegRemap(m, insn->variant.clz.clobber); 797 s390_opnd_RMI_map_regs(m, &insn->variant.clz.src); 798 break; 799 800 case S390_INSN_UNOP: 801 insn->variant.unop.dst = lookupHRegRemap(m, insn->variant.unop.dst); 802 s390_opnd_RMI_map_regs(m, &insn->variant.unop.src); 803 break; 804 805 case S390_INSN_TEST: 806 s390_opnd_RMI_map_regs(m, &insn->variant.test.src); 807 break; 808 809 case S390_INSN_CC2BOOL: 810 insn->variant.cc2bool.dst = lookupHRegRemap(m, insn->variant.cc2bool.dst); 811 break; 812 813 case S390_INSN_CAS: 814 insn->variant.cas.op1 = lookupHRegRemap(m, insn->variant.cas.op1); 815 s390_amode_map_regs(m, insn->variant.cas.op2); 816 insn->variant.cas.op3 = lookupHRegRemap(m, insn->variant.cas.op3); 817 insn->variant.cas.old_mem = lookupHRegRemap(m, insn->variant.cas.old_mem); 818 break; 819 820 case S390_INSN_COMPARE: 821 insn->variant.compare.src1 = lookupHRegRemap(m, insn->variant.compare.src1); 822 s390_opnd_RMI_map_regs(m, &insn->variant.compare.src2); 823 break; 824 825 case S390_INSN_BRANCH: 826 s390_opnd_RMI_map_regs(m, &insn->variant.branch.dst); 827 /* No need to map S390_REGNO_RETURN_VALUE. It's not virtual */ 828 break; 829 830 case S390_INSN_HELPER_CALL: 831 /* s390_insn_helper_call_emit also reads / writes the link register 832 and stack pointer. But those registers are not visible to the 833 register allocator. So we don't need to do anything for them. 834 As for the arguments of the helper call -- they will be loaded into 835 non-virtual registers. Again, we don't need to do anything for those 836 here. */ 837 break; 838 839 case S390_INSN_BFP_TRIOP: 840 insn->variant.bfp_triop.dst = lookupHRegRemap(m, insn->variant.bfp_triop.dst); 841 insn->variant.bfp_triop.op2 = lookupHRegRemap(m, insn->variant.bfp_triop.op2); 842 insn->variant.bfp_triop.op3 = lookupHRegRemap(m, insn->variant.bfp_triop.op3); 843 break; 844 845 case S390_INSN_BFP_BINOP: 846 insn->variant.bfp_binop.dst = lookupHRegRemap(m, insn->variant.bfp_binop.dst); 847 insn->variant.bfp_binop.op2 = lookupHRegRemap(m, insn->variant.bfp_binop.op2); 848 break; 849 850 case S390_INSN_BFP_UNOP: 851 insn->variant.bfp_unop.dst = lookupHRegRemap(m, insn->variant.bfp_unop.dst); 852 insn->variant.bfp_unop.op = lookupHRegRemap(m, insn->variant.bfp_unop.op); 853 break; 854 855 case S390_INSN_BFP_COMPARE: 856 insn->variant.bfp_compare.dst = lookupHRegRemap(m, insn->variant.bfp_compare.dst); 857 insn->variant.bfp_compare.op1 = lookupHRegRemap(m, insn->variant.bfp_compare.op1); 858 insn->variant.bfp_compare.op2 = lookupHRegRemap(m, insn->variant.bfp_compare.op2); 859 break; 860 861 case S390_INSN_BFP128_BINOP: 862 insn->variant.bfp128_binop.dst_hi = 863 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_hi); 864 insn->variant.bfp128_binop.dst_lo = 865 lookupHRegRemap(m, insn->variant.bfp128_binop.dst_lo); 866 insn->variant.bfp128_binop.op2_hi = 867 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_hi); 868 insn->variant.bfp128_binop.op2_lo = 869 lookupHRegRemap(m, insn->variant.bfp128_binop.op2_lo); 870 break; 871 872 case S390_INSN_BFP128_COMPARE: 873 insn->variant.bfp128_compare.dst = 874 lookupHRegRemap(m, insn->variant.bfp128_compare.dst); 875 insn->variant.bfp128_compare.op1_hi = 876 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_hi); 877 insn->variant.bfp128_compare.op1_lo = 878 lookupHRegRemap(m, insn->variant.bfp128_compare.op1_lo); 879 insn->variant.bfp128_compare.op2_hi = 880 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_hi); 881 insn->variant.bfp128_compare.op2_lo = 882 lookupHRegRemap(m, insn->variant.bfp128_compare.op2_lo); 883 break; 884 885 case S390_INSN_BFP128_UNOP: 886 insn->variant.bfp128_unop.dst_hi = 887 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi); 888 insn->variant.bfp128_unop.dst_lo = 889 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo); 890 insn->variant.bfp128_unop.op_hi = 891 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi); 892 insn->variant.bfp128_unop.op_lo = 893 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo); 894 break; 895 896 case S390_INSN_BFP128_CONVERT_TO: 897 insn->variant.bfp128_unop.dst_hi = 898 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi); 899 insn->variant.bfp128_unop.dst_lo = 900 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_lo); 901 insn->variant.bfp128_unop.op_hi = 902 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi); 903 break; 904 905 case S390_INSN_BFP128_CONVERT_FROM: 906 insn->variant.bfp128_unop.dst_hi = 907 lookupHRegRemap(m, insn->variant.bfp128_unop.dst_hi); 908 insn->variant.bfp128_unop.op_hi = 909 lookupHRegRemap(m, insn->variant.bfp128_unop.op_hi); 910 insn->variant.bfp128_unop.op_lo = 911 lookupHRegRemap(m, insn->variant.bfp128_unop.op_lo); 912 break; 913 914 case S390_INSN_MFENCE: 915 break; 916 917 default: 918 vpanic("s390_insn_map_regs"); 919 } 920 } 921 922 923 /* Return True, if INSN is a move between two registers of the same class. 924 In that case assign the source and destination registers to SRC and DST, 925 respectively. */ 926 static Bool 927 s390_insn_is_reg_reg_move(const s390_insn *insn, HReg *src, HReg *dst) 928 { 929 if (insn->tag == S390_INSN_MOVE && 930 hregClass(insn->variant.move.src) == hregClass(insn->variant.move.dst)) { 931 *src = insn->variant.move.src; 932 *dst = insn->variant.move.dst; 933 return True; 934 } 935 936 return False; 937 } 938 939 940 /*------------------------------------------------------------*/ 941 /*--- Functions to emit a sequence of bytes ---*/ 942 /*------------------------------------------------------------*/ 943 944 static __inline__ UChar * 945 emit_2bytes(UChar *p, ULong val) 946 { 947 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 6, 2) + 2; 948 } 949 950 951 static __inline__ UChar * 952 emit_4bytes(UChar *p, ULong val) 953 { 954 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 4, 4) + 4; 955 } 956 957 958 static __inline__ UChar * 959 emit_6bytes(UChar *p, ULong val) 960 { 961 return (UChar *)__builtin_memcpy(p, ((UChar *)&val) + 2, 6) + 6; 962 } 963 964 965 /*------------------------------------------------------------*/ 966 /*--- Functions to emit various instruction formats ---*/ 967 /*------------------------------------------------------------*/ 968 969 static UChar * 970 emit_RI(UChar *p, UInt op, UChar r1, UShort i2) 971 { 972 ULong the_insn = op; 973 974 the_insn |= ((ULong)r1) << 20; 975 the_insn |= ((ULong)i2) << 0; 976 977 return emit_4bytes(p, the_insn); 978 } 979 980 981 static UChar * 982 emit_RIL(UChar *p, ULong op, UChar r1, UInt i2) 983 { 984 ULong the_insn = op; 985 986 the_insn |= ((ULong)r1) << 36; 987 the_insn |= ((ULong)i2) << 0; 988 989 return emit_6bytes(p, the_insn); 990 } 991 992 993 static UChar * 994 emit_RR(UChar *p, UInt op, UChar r1, UChar r2) 995 { 996 ULong the_insn = op; 997 998 the_insn |= ((ULong)r1) << 4; 999 the_insn |= ((ULong)r2) << 0; 1000 1001 return emit_2bytes(p, the_insn); 1002 } 1003 1004 1005 static UChar * 1006 emit_RRE(UChar *p, UInt op, UChar r1, UChar r2) 1007 { 1008 ULong the_insn = op; 1009 1010 the_insn |= ((ULong)r1) << 4; 1011 the_insn |= ((ULong)r2) << 0; 1012 1013 return emit_4bytes(p, the_insn); 1014 } 1015 1016 1017 static UChar * 1018 emit_RRF(UChar *p, UInt op, UChar r1, UChar r3, UChar r2) 1019 { 1020 ULong the_insn = op; 1021 1022 the_insn |= ((ULong)r1) << 12; 1023 the_insn |= ((ULong)r3) << 4; 1024 the_insn |= ((ULong)r2) << 0; 1025 1026 return emit_4bytes(p, the_insn); 1027 } 1028 1029 1030 static UChar * 1031 emit_RRF3(UChar *p, UInt op, UChar r3, UChar r1, UChar r2) 1032 { 1033 ULong the_insn = op; 1034 1035 the_insn |= ((ULong)r3) << 12; 1036 the_insn |= ((ULong)r1) << 4; 1037 the_insn |= ((ULong)r2) << 0; 1038 1039 return emit_4bytes(p, the_insn); 1040 } 1041 1042 1043 static UChar * 1044 emit_RS(UChar *p, UInt op, UChar r1, UChar r3, UChar b2, UShort d2) 1045 { 1046 ULong the_insn = op; 1047 1048 the_insn |= ((ULong)r1) << 20; 1049 the_insn |= ((ULong)r3) << 16; 1050 the_insn |= ((ULong)b2) << 12; 1051 the_insn |= ((ULong)d2) << 0; 1052 1053 return emit_4bytes(p, the_insn); 1054 } 1055 1056 1057 static UChar * 1058 emit_RSY(UChar *p, ULong op, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1059 { 1060 ULong the_insn = op; 1061 1062 the_insn |= ((ULong)r1) << 36; 1063 the_insn |= ((ULong)r3) << 32; 1064 the_insn |= ((ULong)b2) << 28; 1065 the_insn |= ((ULong)dl2) << 16; 1066 the_insn |= ((ULong)dh2) << 8; 1067 1068 return emit_6bytes(p, the_insn); 1069 } 1070 1071 1072 static UChar * 1073 emit_RX(UChar *p, UInt op, UChar r1, UChar x2, UChar b2, UShort d2) 1074 { 1075 ULong the_insn = op; 1076 1077 the_insn |= ((ULong)r1) << 20; 1078 the_insn |= ((ULong)x2) << 16; 1079 the_insn |= ((ULong)b2) << 12; 1080 the_insn |= ((ULong)d2) << 0; 1081 1082 return emit_4bytes(p, the_insn); 1083 } 1084 1085 1086 static UChar * 1087 emit_RXY(UChar *p, ULong op, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1088 { 1089 ULong the_insn = op; 1090 1091 the_insn |= ((ULong)r1) << 36; 1092 the_insn |= ((ULong)x2) << 32; 1093 the_insn |= ((ULong)b2) << 28; 1094 the_insn |= ((ULong)dl2) << 16; 1095 the_insn |= ((ULong)dh2) << 8; 1096 1097 return emit_6bytes(p, the_insn); 1098 } 1099 1100 1101 static UChar * 1102 emit_S(UChar *p, UInt op, UChar b2, UShort d2) 1103 { 1104 ULong the_insn = op; 1105 1106 the_insn |= ((ULong)b2) << 12; 1107 the_insn |= ((ULong)d2) << 0; 1108 1109 return emit_4bytes(p, the_insn); 1110 } 1111 1112 1113 /*------------------------------------------------------------*/ 1114 /*--- Functions to emit particular instructions ---*/ 1115 /*------------------------------------------------------------*/ 1116 1117 static UChar * 1118 s390_emit_AR(UChar *p, UChar r1, UChar r2) 1119 { 1120 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1121 s390_disasm(ENC3(MNM, GPR, GPR), "ar", r1, r2); 1122 1123 return emit_RR(p, 0x1a00, r1, r2); 1124 } 1125 1126 1127 static UChar * 1128 s390_emit_AGR(UChar *p, UChar r1, UChar r2) 1129 { 1130 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1131 s390_disasm(ENC3(MNM, GPR, GPR), "agr", r1, r2); 1132 1133 return emit_RRE(p, 0xb9080000, r1, r2); 1134 } 1135 1136 1137 static UChar * 1138 s390_emit_A(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1139 { 1140 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1141 s390_disasm(ENC3(MNM, GPR, UDXB), "a", r1, d2, x2, b2); 1142 1143 return emit_RX(p, 0x5a000000, r1, x2, b2, d2); 1144 } 1145 1146 1147 static UChar * 1148 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1149 { 1150 vassert(s390_host_has_ldisp); 1151 1152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1153 s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2); 1154 1155 return emit_RXY(p, 0xe3000000005aULL, r1, x2, b2, dl2, dh2); 1156 } 1157 1158 1159 static UChar * 1160 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1161 { 1162 vassert(s390_host_has_ldisp || dh2 == 0); 1163 1164 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1165 s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2); 1166 1167 return emit_RXY(p, 0xe30000000008ULL, r1, x2, b2, dl2, dh2); 1168 } 1169 1170 1171 static UChar * 1172 s390_emit_AFI(UChar *p, UChar r1, UInt i2) 1173 { 1174 vassert(s390_host_has_eimm); 1175 1176 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1177 s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2); 1178 1179 return emit_RIL(p, 0xc20900000000ULL, r1, i2); 1180 } 1181 1182 1183 static UChar * 1184 s390_emit_AGFI(UChar *p, UChar r1, UInt i2) 1185 { 1186 vassert(s390_host_has_eimm); 1187 1188 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1189 s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2); 1190 1191 return emit_RIL(p, 0xc20800000000ULL, r1, i2); 1192 } 1193 1194 1195 static UChar * 1196 s390_emit_AH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1197 { 1198 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1199 s390_disasm(ENC3(MNM, GPR, UDXB), "ah", r1, d2, x2, b2); 1200 1201 return emit_RX(p, 0x4a000000, r1, x2, b2, d2); 1202 } 1203 1204 1205 static UChar * 1206 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1207 { 1208 vassert(s390_host_has_ldisp); 1209 1210 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1211 s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2); 1212 1213 return emit_RXY(p, 0xe3000000007aULL, r1, x2, b2, dl2, dh2); 1214 } 1215 1216 1217 static UChar * 1218 s390_emit_AHI(UChar *p, UChar r1, UShort i2) 1219 { 1220 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1221 s390_disasm(ENC3(MNM, GPR, INT), "ahi", r1, (Int)(Short)i2); 1222 1223 return emit_RI(p, 0xa70a0000, r1, i2); 1224 } 1225 1226 1227 static UChar * 1228 s390_emit_AGHI(UChar *p, UChar r1, UShort i2) 1229 { 1230 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1231 s390_disasm(ENC3(MNM, GPR, INT), "aghi", r1, (Int)(Short)i2); 1232 1233 return emit_RI(p, 0xa70b0000, r1, i2); 1234 } 1235 1236 1237 static UChar * 1238 s390_emit_NR(UChar *p, UChar r1, UChar r2) 1239 { 1240 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1241 s390_disasm(ENC3(MNM, GPR, GPR), "nr", r1, r2); 1242 1243 return emit_RR(p, 0x1400, r1, r2); 1244 } 1245 1246 1247 static UChar * 1248 s390_emit_NGR(UChar *p, UChar r1, UChar r2) 1249 { 1250 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1251 s390_disasm(ENC3(MNM, GPR, GPR), "ngr", r1, r2); 1252 1253 return emit_RRE(p, 0xb9800000, r1, r2); 1254 } 1255 1256 1257 static UChar * 1258 s390_emit_N(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1259 { 1260 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1261 s390_disasm(ENC3(MNM, GPR, UDXB), "n", r1, d2, x2, b2); 1262 1263 return emit_RX(p, 0x54000000, r1, x2, b2, d2); 1264 } 1265 1266 1267 static UChar * 1268 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1269 { 1270 vassert(s390_host_has_ldisp); 1271 1272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1273 s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2); 1274 1275 return emit_RXY(p, 0xe30000000054ULL, r1, x2, b2, dl2, dh2); 1276 } 1277 1278 1279 static UChar * 1280 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1281 { 1282 vassert(s390_host_has_ldisp || dh2 == 0); 1283 1284 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1285 s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2); 1286 1287 return emit_RXY(p, 0xe30000000080ULL, r1, x2, b2, dl2, dh2); 1288 } 1289 1290 1291 static UChar * 1292 s390_emit_NIHF(UChar *p, UChar r1, UInt i2) 1293 { 1294 vassert(s390_host_has_eimm); 1295 1296 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1297 s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2); 1298 1299 return emit_RIL(p, 0xc00a00000000ULL, r1, i2); 1300 } 1301 1302 1303 static UChar * 1304 s390_emit_NILF(UChar *p, UChar r1, UInt i2) 1305 { 1306 vassert(s390_host_has_eimm); 1307 1308 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1309 s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2); 1310 1311 return emit_RIL(p, 0xc00b00000000ULL, r1, i2); 1312 } 1313 1314 1315 static UChar * 1316 s390_emit_NILL(UChar *p, UChar r1, UShort i2) 1317 { 1318 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1319 s390_disasm(ENC3(MNM, GPR, UINT), "nill", r1, i2); 1320 1321 return emit_RI(p, 0xa5070000, r1, i2); 1322 } 1323 1324 1325 static UChar * 1326 s390_emit_BASR(UChar *p, UChar r1, UChar r2) 1327 { 1328 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1329 s390_disasm(ENC3(MNM, GPR, GPR), "basr", r1, r2); 1330 1331 return emit_RR(p, 0x0d00, r1, r2); 1332 } 1333 1334 1335 static UChar * 1336 s390_emit_BCR(UChar *p, UChar r1, UChar r2) 1337 { 1338 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1339 s390_disasm(ENC2(XMNM, GPR), S390_XMNM_BCR, r1, r2); 1340 1341 return emit_RR(p, 0x0700, r1, r2); 1342 } 1343 1344 1345 static UChar * 1346 s390_emit_BRC(UChar *p, UChar r1, UShort i2) 1347 { 1348 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1349 s390_disasm(ENC2(XMNM, PCREL), S390_XMNM_BRC, r1, (Int)(Short)i2); 1350 1351 return emit_RI(p, 0xa7040000, r1, i2); 1352 } 1353 1354 1355 static UChar * 1356 s390_emit_CR(UChar *p, UChar r1, UChar r2) 1357 { 1358 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1359 s390_disasm(ENC3(MNM, GPR, GPR), "cr", r1, r2); 1360 1361 return emit_RR(p, 0x1900, r1, r2); 1362 } 1363 1364 1365 static UChar * 1366 s390_emit_CGR(UChar *p, UChar r1, UChar r2) 1367 { 1368 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1369 s390_disasm(ENC3(MNM, GPR, GPR), "cgr", r1, r2); 1370 1371 return emit_RRE(p, 0xb9200000, r1, r2); 1372 } 1373 1374 1375 static UChar * 1376 s390_emit_C(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1377 { 1378 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1379 s390_disasm(ENC3(MNM, GPR, UDXB), "c", r1, d2, x2, b2); 1380 1381 return emit_RX(p, 0x59000000, r1, x2, b2, d2); 1382 } 1383 1384 1385 static UChar * 1386 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1387 { 1388 vassert(s390_host_has_ldisp); 1389 1390 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1391 s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2); 1392 1393 return emit_RXY(p, 0xe30000000059ULL, r1, x2, b2, dl2, dh2); 1394 } 1395 1396 1397 static UChar * 1398 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1399 { 1400 vassert(s390_host_has_ldisp || dh2 == 0); 1401 1402 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1403 s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2); 1404 1405 return emit_RXY(p, 0xe30000000020ULL, r1, x2, b2, dl2, dh2); 1406 } 1407 1408 1409 static UChar * 1410 s390_emit_CFI(UChar *p, UChar r1, UInt i2) 1411 { 1412 vassert(s390_host_has_eimm); 1413 1414 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1415 s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2); 1416 1417 return emit_RIL(p, 0xc20d00000000ULL, r1, i2); 1418 } 1419 1420 1421 static UChar * 1422 s390_emit_CS(UChar *p, UChar r1, UChar r3, UChar b2, UShort d2) 1423 { 1424 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1425 s390_disasm(ENC4(MNM, GPR, GPR, UDXB), "cs", r1, r3, d2, 0, b2); 1426 1427 return emit_RS(p, 0xba000000, r1, r3, b2, d2); 1428 } 1429 1430 1431 static UChar * 1432 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1433 { 1434 vassert(s390_host_has_ldisp); 1435 1436 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1437 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2); 1438 1439 return emit_RSY(p, 0xeb0000000014ULL, r1, r3, b2, dl2, dh2); 1440 } 1441 1442 1443 static UChar * 1444 s390_emit_CSG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 1445 { 1446 vassert(s390_host_has_ldisp || dh2 == 0); 1447 1448 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1449 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2); 1450 1451 return emit_RSY(p, 0xeb0000000030ULL, r1, r3, b2, dl2, dh2); 1452 } 1453 1454 1455 static UChar * 1456 s390_emit_CLR(UChar *p, UChar r1, UChar r2) 1457 { 1458 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1459 s390_disasm(ENC3(MNM, GPR, GPR), "clr", r1, r2); 1460 1461 return emit_RR(p, 0x1500, r1, r2); 1462 } 1463 1464 1465 static UChar * 1466 s390_emit_CLGR(UChar *p, UChar r1, UChar r2) 1467 { 1468 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1469 s390_disasm(ENC3(MNM, GPR, GPR), "clgr", r1, r2); 1470 1471 return emit_RRE(p, 0xb9210000, r1, r2); 1472 } 1473 1474 1475 static UChar * 1476 s390_emit_CL(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1477 { 1478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1479 s390_disasm(ENC3(MNM, GPR, UDXB), "cl", r1, d2, x2, b2); 1480 1481 return emit_RX(p, 0x55000000, r1, x2, b2, d2); 1482 } 1483 1484 1485 static UChar * 1486 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1487 { 1488 vassert(s390_host_has_ldisp); 1489 1490 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1491 s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2); 1492 1493 return emit_RXY(p, 0xe30000000055ULL, r1, x2, b2, dl2, dh2); 1494 } 1495 1496 1497 static UChar * 1498 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1499 { 1500 vassert(s390_host_has_ldisp || dh2 == 0); 1501 1502 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1503 s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2); 1504 1505 return emit_RXY(p, 0xe30000000021ULL, r1, x2, b2, dl2, dh2); 1506 } 1507 1508 1509 static UChar * 1510 s390_emit_CLFI(UChar *p, UChar r1, UInt i2) 1511 { 1512 vassert(s390_host_has_eimm); 1513 1514 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1515 s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2); 1516 1517 return emit_RIL(p, 0xc20f00000000ULL, r1, i2); 1518 } 1519 1520 1521 static UChar * 1522 s390_emit_DR(UChar *p, UChar r1, UChar r2) 1523 { 1524 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1525 s390_disasm(ENC3(MNM, GPR, GPR), "dr", r1, r2); 1526 1527 return emit_RR(p, 0x1d00, r1, r2); 1528 } 1529 1530 1531 static UChar * 1532 s390_emit_D(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1533 { 1534 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1535 s390_disasm(ENC3(MNM, GPR, UDXB), "d", r1, d2, x2, b2); 1536 1537 return emit_RX(p, 0x5d000000, r1, x2, b2, d2); 1538 } 1539 1540 1541 static UChar * 1542 s390_emit_DLR(UChar *p, UChar r1, UChar r2) 1543 { 1544 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1545 s390_disasm(ENC3(MNM, GPR, GPR), "dlr", r1, r2); 1546 1547 return emit_RRE(p, 0xb9970000, r1, r2); 1548 } 1549 1550 1551 static UChar * 1552 s390_emit_DLGR(UChar *p, UChar r1, UChar r2) 1553 { 1554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1555 s390_disasm(ENC3(MNM, GPR, GPR), "dlgr", r1, r2); 1556 1557 return emit_RRE(p, 0xb9870000, r1, r2); 1558 } 1559 1560 1561 static UChar * 1562 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1563 { 1564 vassert(s390_host_has_ldisp || dh2 == 0); 1565 1566 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1567 s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2); 1568 1569 return emit_RXY(p, 0xe30000000097ULL, r1, x2, b2, dl2, dh2); 1570 } 1571 1572 1573 static UChar * 1574 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1575 { 1576 vassert(s390_host_has_ldisp || dh2 == 0); 1577 1578 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1579 s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2); 1580 1581 return emit_RXY(p, 0xe30000000087ULL, r1, x2, b2, dl2, dh2); 1582 } 1583 1584 1585 static UChar * 1586 s390_emit_DSGR(UChar *p, UChar r1, UChar r2) 1587 { 1588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1589 s390_disasm(ENC3(MNM, GPR, GPR), "dsgr", r1, r2); 1590 1591 return emit_RRE(p, 0xb90d0000, r1, r2); 1592 } 1593 1594 1595 static UChar * 1596 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1597 { 1598 vassert(s390_host_has_ldisp || dh2 == 0); 1599 1600 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1601 s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2); 1602 1603 return emit_RXY(p, 0xe3000000000dULL, r1, x2, b2, dl2, dh2); 1604 } 1605 1606 1607 static UChar * 1608 s390_emit_XR(UChar *p, UChar r1, UChar r2) 1609 { 1610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1611 s390_disasm(ENC3(MNM, GPR, GPR), "xr", r1, r2); 1612 1613 return emit_RR(p, 0x1700, r1, r2); 1614 } 1615 1616 1617 static UChar * 1618 s390_emit_XGR(UChar *p, UChar r1, UChar r2) 1619 { 1620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1621 s390_disasm(ENC3(MNM, GPR, GPR), "xgr", r1, r2); 1622 1623 return emit_RRE(p, 0xb9820000, r1, r2); 1624 } 1625 1626 1627 static UChar * 1628 s390_emit_X(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1629 { 1630 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1631 s390_disasm(ENC3(MNM, GPR, UDXB), "x", r1, d2, x2, b2); 1632 1633 return emit_RX(p, 0x57000000, r1, x2, b2, d2); 1634 } 1635 1636 1637 static UChar * 1638 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1639 { 1640 vassert(s390_host_has_ldisp); 1641 1642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1643 s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2); 1644 1645 return emit_RXY(p, 0xe30000000057ULL, r1, x2, b2, dl2, dh2); 1646 } 1647 1648 1649 static UChar * 1650 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1651 { 1652 vassert(s390_host_has_ldisp || dh2 == 0); 1653 1654 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1655 s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2); 1656 1657 return emit_RXY(p, 0xe30000000082ULL, r1, x2, b2, dl2, dh2); 1658 } 1659 1660 1661 static UChar * 1662 s390_emit_XIHF(UChar *p, UChar r1, UInt i2) 1663 { 1664 vassert(s390_host_has_eimm); 1665 1666 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1667 s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2); 1668 1669 return emit_RIL(p, 0xc00600000000ULL, r1, i2); 1670 } 1671 1672 1673 static UChar * 1674 s390_emit_XILF(UChar *p, UChar r1, UInt i2) 1675 { 1676 vassert(s390_host_has_eimm); 1677 1678 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1679 s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2); 1680 1681 return emit_RIL(p, 0xc00700000000ULL, r1, i2); 1682 } 1683 1684 1685 static UChar * 1686 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2) 1687 { 1688 vassert(s390_host_has_eimm); 1689 1690 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1691 s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2); 1692 1693 return emit_RRE(p, 0xb9830000, r1, r2); 1694 } 1695 1696 1697 static UChar * 1698 s390_emit_IC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1699 { 1700 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1701 s390_disasm(ENC3(MNM, GPR, UDXB), "ic", r1, d2, x2, b2); 1702 1703 return emit_RX(p, 0x43000000, r1, x2, b2, d2); 1704 } 1705 1706 1707 static UChar * 1708 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1709 { 1710 vassert(s390_host_has_ldisp); 1711 1712 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1713 s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2); 1714 1715 return emit_RXY(p, 0xe30000000073ULL, r1, x2, b2, dl2, dh2); 1716 } 1717 1718 1719 static UChar * 1720 s390_emit_IIHF(UChar *p, UChar r1, UInt i2) 1721 { 1722 vassert(s390_host_has_eimm); 1723 1724 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1725 s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2); 1726 1727 return emit_RIL(p, 0xc00800000000ULL, r1, i2); 1728 } 1729 1730 1731 static UChar * 1732 s390_emit_IIHH(UChar *p, UChar r1, UShort i2) 1733 { 1734 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1735 s390_disasm(ENC3(MNM, GPR, UINT), "iihh", r1, i2); 1736 1737 return emit_RI(p, 0xa5000000, r1, i2); 1738 } 1739 1740 1741 static UChar * 1742 s390_emit_IIHL(UChar *p, UChar r1, UShort i2) 1743 { 1744 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1745 s390_disasm(ENC3(MNM, GPR, UINT), "iihl", r1, i2); 1746 1747 return emit_RI(p, 0xa5010000, r1, i2); 1748 } 1749 1750 1751 static UChar * 1752 s390_emit_IILF(UChar *p, UChar r1, UInt i2) 1753 { 1754 vassert(s390_host_has_eimm); 1755 1756 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1757 s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2); 1758 1759 return emit_RIL(p, 0xc00900000000ULL, r1, i2); 1760 } 1761 1762 1763 static UChar * 1764 s390_emit_IILH(UChar *p, UChar r1, UShort i2) 1765 { 1766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1767 s390_disasm(ENC3(MNM, GPR, UINT), "iilh", r1, i2); 1768 1769 return emit_RI(p, 0xa5020000, r1, i2); 1770 } 1771 1772 1773 static UChar * 1774 s390_emit_IILL(UChar *p, UChar r1, UShort i2) 1775 { 1776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1777 s390_disasm(ENC3(MNM, GPR, UINT), "iill", r1, i2); 1778 1779 return emit_RI(p, 0xa5030000, r1, i2); 1780 } 1781 1782 1783 static UChar * 1784 s390_emit_IPM(UChar *p, UChar r1, UChar r2) 1785 { 1786 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1787 s390_disasm(ENC2(MNM, GPR), "ipm", r1); 1788 1789 return emit_RRE(p, 0xb2220000, r1, r2); 1790 } 1791 1792 1793 static UChar * 1794 s390_emit_LR(UChar *p, UChar r1, UChar r2) 1795 { 1796 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1797 s390_disasm(ENC3(MNM, GPR, GPR), "lr", r1, r2); 1798 1799 return emit_RR(p, 0x1800, r1, r2); 1800 } 1801 1802 1803 static UChar * 1804 s390_emit_LGR(UChar *p, UChar r1, UChar r2) 1805 { 1806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1807 s390_disasm(ENC3(MNM, GPR, GPR), "lgr", r1, r2); 1808 1809 return emit_RRE(p, 0xb9040000, r1, r2); 1810 } 1811 1812 1813 static UChar * 1814 s390_emit_LGFR(UChar *p, UChar r1, UChar r2) 1815 { 1816 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1817 s390_disasm(ENC3(MNM, GPR, GPR), "lgfr", r1, r2); 1818 1819 return emit_RRE(p, 0xb9140000, r1, r2); 1820 } 1821 1822 1823 static UChar * 1824 s390_emit_L(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 1825 { 1826 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1827 s390_disasm(ENC3(MNM, GPR, UDXB), "l", r1, d2, x2, b2); 1828 1829 return emit_RX(p, 0x58000000, r1, x2, b2, d2); 1830 } 1831 1832 1833 static UChar * 1834 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1835 { 1836 vassert(s390_host_has_ldisp); 1837 1838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1839 s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2); 1840 1841 return emit_RXY(p, 0xe30000000058ULL, r1, x2, b2, dl2, dh2); 1842 } 1843 1844 1845 static UChar * 1846 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1847 { 1848 vassert(s390_host_has_ldisp || dh2 == 0); 1849 1850 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1851 s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2); 1852 1853 return emit_RXY(p, 0xe30000000004ULL, r1, x2, b2, dl2, dh2); 1854 } 1855 1856 1857 static UChar * 1858 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1859 { 1860 vassert(s390_host_has_ldisp || dh2 == 0); 1861 1862 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1863 s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2); 1864 1865 return emit_RXY(p, 0xe30000000014ULL, r1, x2, b2, dl2, dh2); 1866 } 1867 1868 1869 static UChar * 1870 s390_emit_LGFI(UChar *p, UChar r1, UInt i2) 1871 { 1872 vassert(s390_host_has_eimm); 1873 1874 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1875 s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2); 1876 1877 return emit_RIL(p, 0xc00100000000ULL, r1, i2); 1878 } 1879 1880 1881 static UChar * 1882 s390_emit_LTR(UChar *p, UChar r1, UChar r2) 1883 { 1884 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1885 s390_disasm(ENC3(MNM, GPR, GPR), "ltr", r1, r2); 1886 1887 return emit_RR(p, 0x1200, r1, r2); 1888 } 1889 1890 1891 static UChar * 1892 s390_emit_LTGR(UChar *p, UChar r1, UChar r2) 1893 { 1894 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1895 s390_disasm(ENC3(MNM, GPR, GPR), "ltgr", r1, r2); 1896 1897 return emit_RRE(p, 0xb9020000, r1, r2); 1898 } 1899 1900 1901 static UChar * 1902 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1903 { 1904 vassert(s390_host_has_eimm); 1905 1906 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1907 s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2); 1908 1909 return emit_RXY(p, 0xe30000000012ULL, r1, x2, b2, dl2, dh2); 1910 } 1911 1912 1913 static UChar * 1914 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1915 { 1916 vassert(s390_host_has_eimm); 1917 1918 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1919 s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2); 1920 1921 return emit_RXY(p, 0xe30000000002ULL, r1, x2, b2, dl2, dh2); 1922 } 1923 1924 1925 static UChar * 1926 s390_emit_LBR(UChar *p, UChar r1, UChar r2) 1927 { 1928 vassert(s390_host_has_eimm); 1929 1930 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1931 s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2); 1932 1933 return emit_RRE(p, 0xb9260000, r1, r2); 1934 } 1935 1936 1937 static UChar * 1938 s390_emit_LGBR(UChar *p, UChar r1, UChar r2) 1939 { 1940 vassert(s390_host_has_eimm); 1941 1942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1943 s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2); 1944 1945 return emit_RRE(p, 0xb9060000, r1, r2); 1946 } 1947 1948 1949 static UChar * 1950 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1951 { 1952 vassert(s390_host_has_ldisp); 1953 1954 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1955 s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2); 1956 1957 return emit_RXY(p, 0xe30000000076ULL, r1, x2, b2, dl2, dh2); 1958 } 1959 1960 1961 static UChar * 1962 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 1963 { 1964 vassert(s390_host_has_ldisp); 1965 1966 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1967 s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2); 1968 1969 return emit_RXY(p, 0xe30000000077ULL, r1, x2, b2, dl2, dh2); 1970 } 1971 1972 1973 static UChar * 1974 s390_emit_LCR(UChar *p, UChar r1, UChar r2) 1975 { 1976 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1977 s390_disasm(ENC3(MNM, GPR, GPR), "lcr", r1, r2); 1978 1979 return emit_RR(p, 0x1300, r1, r2); 1980 } 1981 1982 1983 static UChar * 1984 s390_emit_LCGR(UChar *p, UChar r1, UChar r2) 1985 { 1986 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1987 s390_disasm(ENC3(MNM, GPR, GPR), "lcgr", r1, r2); 1988 1989 return emit_RRE(p, 0xb9030000, r1, r2); 1990 } 1991 1992 1993 static UChar * 1994 s390_emit_LHR(UChar *p, UChar r1, UChar r2) 1995 { 1996 vassert(s390_host_has_eimm); 1997 1998 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 1999 s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2); 2000 2001 return emit_RRE(p, 0xb9270000, r1, r2); 2002 } 2003 2004 2005 static UChar * 2006 s390_emit_LGHR(UChar *p, UChar r1, UChar r2) 2007 { 2008 vassert(s390_host_has_eimm); 2009 2010 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2011 s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2); 2012 2013 return emit_RRE(p, 0xb9070000, r1, r2); 2014 } 2015 2016 2017 static UChar * 2018 s390_emit_LH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2019 { 2020 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2021 s390_disasm(ENC3(MNM, GPR, UDXB), "lh", r1, d2, x2, b2); 2022 2023 return emit_RX(p, 0x48000000, r1, x2, b2, d2); 2024 } 2025 2026 2027 static UChar * 2028 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2029 { 2030 vassert(s390_host_has_ldisp); 2031 2032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2033 s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2); 2034 2035 return emit_RXY(p, 0xe30000000078ULL, r1, x2, b2, dl2, dh2); 2036 } 2037 2038 2039 static UChar * 2040 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2041 { 2042 vassert(s390_host_has_ldisp || dh2 == 0); 2043 2044 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2045 s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2); 2046 2047 return emit_RXY(p, 0xe30000000015ULL, r1, x2, b2, dl2, dh2); 2048 } 2049 2050 2051 static UChar * 2052 s390_emit_LHI(UChar *p, UChar r1, UShort i2) 2053 { 2054 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2055 s390_disasm(ENC3(MNM, GPR, INT), "lhi", r1, (Int)(Short)i2); 2056 2057 return emit_RI(p, 0xa7080000, r1, i2); 2058 } 2059 2060 2061 static UChar * 2062 s390_emit_LGHI(UChar *p, UChar r1, UShort i2) 2063 { 2064 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2065 s390_disasm(ENC3(MNM, GPR, INT), "lghi", r1, (Int)(Short)i2); 2066 2067 return emit_RI(p, 0xa7090000, r1, i2); 2068 } 2069 2070 2071 static UChar * 2072 s390_emit_LLGFR(UChar *p, UChar r1, UChar r2) 2073 { 2074 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2075 s390_disasm(ENC3(MNM, GPR, GPR), "llgfr", r1, r2); 2076 2077 return emit_RRE(p, 0xb9160000, r1, r2); 2078 } 2079 2080 2081 static UChar * 2082 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2083 { 2084 vassert(s390_host_has_ldisp || dh2 == 0); 2085 2086 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2087 s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2); 2088 2089 return emit_RXY(p, 0xe30000000016ULL, r1, x2, b2, dl2, dh2); 2090 } 2091 2092 2093 static UChar * 2094 s390_emit_LLCR(UChar *p, UChar r1, UChar r2) 2095 { 2096 vassert(s390_host_has_eimm); 2097 2098 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2099 s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2); 2100 2101 return emit_RRE(p, 0xb9940000, r1, r2); 2102 } 2103 2104 2105 static UChar * 2106 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2) 2107 { 2108 vassert(s390_host_has_eimm); 2109 2110 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2111 s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2); 2112 2113 return emit_RRE(p, 0xb9840000, r1, r2); 2114 } 2115 2116 2117 static UChar * 2118 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2119 { 2120 vassert(s390_host_has_eimm); 2121 2122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2123 s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2); 2124 2125 return emit_RXY(p, 0xe30000000094ULL, r1, x2, b2, dl2, dh2); 2126 } 2127 2128 2129 static UChar * 2130 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2131 { 2132 vassert(s390_host_has_ldisp || dh2 == 0); 2133 2134 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2135 s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2); 2136 2137 return emit_RXY(p, 0xe30000000090ULL, r1, x2, b2, dl2, dh2); 2138 } 2139 2140 2141 static UChar * 2142 s390_emit_LLHR(UChar *p, UChar r1, UChar r2) 2143 { 2144 vassert(s390_host_has_eimm); 2145 2146 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2147 s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2); 2148 2149 return emit_RRE(p, 0xb9950000, r1, r2); 2150 } 2151 2152 2153 static UChar * 2154 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2) 2155 { 2156 vassert(s390_host_has_eimm); 2157 2158 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2159 s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2); 2160 2161 return emit_RRE(p, 0xb9850000, r1, r2); 2162 } 2163 2164 2165 static UChar * 2166 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2167 { 2168 vassert(s390_host_has_eimm); 2169 2170 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2171 s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2); 2172 2173 return emit_RXY(p, 0xe30000000095ULL, r1, x2, b2, dl2, dh2); 2174 } 2175 2176 2177 static UChar * 2178 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2179 { 2180 vassert(s390_host_has_ldisp || dh2 == 0); 2181 2182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2183 s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2); 2184 2185 return emit_RXY(p, 0xe30000000091ULL, r1, x2, b2, dl2, dh2); 2186 } 2187 2188 2189 static UChar * 2190 s390_emit_LLILF(UChar *p, UChar r1, UInt i2) 2191 { 2192 vassert(s390_host_has_eimm); 2193 2194 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2195 s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2); 2196 2197 return emit_RIL(p, 0xc00f00000000ULL, r1, i2); 2198 } 2199 2200 2201 static UChar * 2202 s390_emit_LLILH(UChar *p, UChar r1, UShort i2) 2203 { 2204 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2205 s390_disasm(ENC3(MNM, GPR, UINT), "llilh", r1, i2); 2206 2207 return emit_RI(p, 0xa50e0000, r1, i2); 2208 } 2209 2210 2211 static UChar * 2212 s390_emit_LLILL(UChar *p, UChar r1, UShort i2) 2213 { 2214 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2215 s390_disasm(ENC3(MNM, GPR, UINT), "llill", r1, i2); 2216 2217 return emit_RI(p, 0xa50f0000, r1, i2); 2218 } 2219 2220 2221 static UChar * 2222 s390_emit_MR(UChar *p, UChar r1, UChar r2) 2223 { 2224 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2225 s390_disasm(ENC3(MNM, GPR, GPR), "mr", r1, r2); 2226 2227 return emit_RR(p, 0x1c00, r1, r2); 2228 } 2229 2230 2231 static UChar * 2232 s390_emit_M(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2233 { 2234 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2235 s390_disasm(ENC3(MNM, GPR, UDXB), "m", r1, d2, x2, b2); 2236 2237 return emit_RX(p, 0x5c000000, r1, x2, b2, d2); 2238 } 2239 2240 2241 static UChar * 2242 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2243 { 2244 vassert(s390_host_has_gie); 2245 2246 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2247 s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2); 2248 2249 return emit_RXY(p, 0xe3000000005cULL, r1, x2, b2, dl2, dh2); 2250 } 2251 2252 2253 static UChar * 2254 s390_emit_MH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2255 { 2256 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2257 s390_disasm(ENC3(MNM, GPR, UDXB), "mh", r1, d2, x2, b2); 2258 2259 return emit_RX(p, 0x4c000000, r1, x2, b2, d2); 2260 } 2261 2262 2263 static UChar * 2264 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2265 { 2266 vassert(s390_host_has_gie); 2267 2268 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2269 s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2); 2270 2271 return emit_RXY(p, 0xe3000000007cULL, r1, x2, b2, dl2, dh2); 2272 } 2273 2274 2275 static UChar * 2276 s390_emit_MHI(UChar *p, UChar r1, UShort i2) 2277 { 2278 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2279 s390_disasm(ENC3(MNM, GPR, INT), "mhi", r1, (Int)(Short)i2); 2280 2281 return emit_RI(p, 0xa70c0000, r1, i2); 2282 } 2283 2284 2285 static UChar * 2286 s390_emit_MLR(UChar *p, UChar r1, UChar r2) 2287 { 2288 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2289 s390_disasm(ENC3(MNM, GPR, GPR), "mlr", r1, r2); 2290 2291 return emit_RRE(p, 0xb9960000, r1, r2); 2292 } 2293 2294 2295 static UChar * 2296 s390_emit_MLGR(UChar *p, UChar r1, UChar r2) 2297 { 2298 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2299 s390_disasm(ENC3(MNM, GPR, GPR), "mlgr", r1, r2); 2300 2301 return emit_RRE(p, 0xb9860000, r1, r2); 2302 } 2303 2304 2305 static UChar * 2306 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2307 { 2308 vassert(s390_host_has_ldisp || dh2 == 0); 2309 2310 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2311 s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2); 2312 2313 return emit_RXY(p, 0xe30000000096ULL, r1, x2, b2, dl2, dh2); 2314 } 2315 2316 2317 static UChar * 2318 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2319 { 2320 vassert(s390_host_has_ldisp || dh2 == 0); 2321 2322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2323 s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2); 2324 2325 return emit_RXY(p, 0xe30000000086ULL, r1, x2, b2, dl2, dh2); 2326 } 2327 2328 2329 static UChar * 2330 s390_emit_MSR(UChar *p, UChar r1, UChar r2) 2331 { 2332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2333 s390_disasm(ENC3(MNM, GPR, GPR), "msr", r1, r2); 2334 2335 return emit_RRE(p, 0xb2520000, r1, r2); 2336 } 2337 2338 2339 static UChar * 2340 s390_emit_MSGR(UChar *p, UChar r1, UChar r2) 2341 { 2342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2343 s390_disasm(ENC3(MNM, GPR, GPR), "msgr", r1, r2); 2344 2345 return emit_RRE(p, 0xb90c0000, r1, r2); 2346 } 2347 2348 2349 static UChar * 2350 s390_emit_MS(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2351 { 2352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2353 s390_disasm(ENC3(MNM, GPR, UDXB), "ms", r1, d2, x2, b2); 2354 2355 return emit_RX(p, 0x71000000, r1, x2, b2, d2); 2356 } 2357 2358 2359 static UChar * 2360 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2361 { 2362 vassert(s390_host_has_ldisp); 2363 2364 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2365 s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2); 2366 2367 return emit_RXY(p, 0xe30000000051ULL, r1, x2, b2, dl2, dh2); 2368 } 2369 2370 2371 static UChar * 2372 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2373 { 2374 vassert(s390_host_has_ldisp || dh2 == 0); 2375 2376 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2377 s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2); 2378 2379 return emit_RXY(p, 0xe3000000000cULL, r1, x2, b2, dl2, dh2); 2380 } 2381 2382 2383 static UChar * 2384 s390_emit_MSFI(UChar *p, UChar r1, UInt i2) 2385 { 2386 vassert(s390_host_has_gie); 2387 2388 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2389 s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2); 2390 2391 return emit_RIL(p, 0xc20100000000ULL, r1, i2); 2392 } 2393 2394 2395 static UChar * 2396 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2) 2397 { 2398 vassert(s390_host_has_gie); 2399 2400 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2401 s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2); 2402 2403 return emit_RIL(p, 0xc20000000000ULL, r1, i2); 2404 } 2405 2406 2407 static UChar * 2408 s390_emit_OR(UChar *p, UChar r1, UChar r2) 2409 { 2410 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2411 s390_disasm(ENC3(MNM, GPR, GPR), "or", r1, r2); 2412 2413 return emit_RR(p, 0x1600, r1, r2); 2414 } 2415 2416 2417 static UChar * 2418 s390_emit_OGR(UChar *p, UChar r1, UChar r2) 2419 { 2420 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2421 s390_disasm(ENC3(MNM, GPR, GPR), "ogr", r1, r2); 2422 2423 return emit_RRE(p, 0xb9810000, r1, r2); 2424 } 2425 2426 2427 static UChar * 2428 s390_emit_O(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2429 { 2430 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2431 s390_disasm(ENC3(MNM, GPR, UDXB), "o", r1, d2, x2, b2); 2432 2433 return emit_RX(p, 0x56000000, r1, x2, b2, d2); 2434 } 2435 2436 2437 static UChar * 2438 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2439 { 2440 vassert(s390_host_has_ldisp); 2441 2442 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2443 s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2); 2444 2445 return emit_RXY(p, 0xe30000000056ULL, r1, x2, b2, dl2, dh2); 2446 } 2447 2448 2449 static UChar * 2450 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2451 { 2452 vassert(s390_host_has_ldisp || dh2 == 0); 2453 2454 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2455 s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2); 2456 2457 return emit_RXY(p, 0xe30000000081ULL, r1, x2, b2, dl2, dh2); 2458 } 2459 2460 2461 static UChar * 2462 s390_emit_OIHF(UChar *p, UChar r1, UInt i2) 2463 { 2464 vassert(s390_host_has_eimm); 2465 2466 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2467 s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2); 2468 2469 return emit_RIL(p, 0xc00c00000000ULL, r1, i2); 2470 } 2471 2472 2473 static UChar * 2474 s390_emit_OILF(UChar *p, UChar r1, UInt i2) 2475 { 2476 vassert(s390_host_has_eimm); 2477 2478 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2479 s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2); 2480 2481 return emit_RIL(p, 0xc00d00000000ULL, r1, i2); 2482 } 2483 2484 2485 static UChar * 2486 s390_emit_OILL(UChar *p, UChar r1, UShort i2) 2487 { 2488 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2489 s390_disasm(ENC3(MNM, GPR, UINT), "oill", r1, i2); 2490 2491 return emit_RI(p, 0xa50b0000, r1, i2); 2492 } 2493 2494 2495 static UChar * 2496 s390_emit_SLL(UChar *p, UChar r1, UChar b2, UShort d2) 2497 { 2498 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2499 s390_disasm(ENC3(MNM, GPR, UDXB), "sll", r1, d2, 0, b2); 2500 2501 return emit_RS(p, 0x89000000, r1, 0, b2, d2); 2502 } 2503 2504 2505 static UChar * 2506 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 2507 { 2508 vassert(s390_host_has_ldisp || dh2 == 0); 2509 2510 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2511 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2); 2512 2513 return emit_RSY(p, 0xeb000000000dULL, r1, r3, b2, dl2, dh2); 2514 } 2515 2516 2517 static UChar * 2518 s390_emit_SRA(UChar *p, UChar r1, UChar b2, UShort d2) 2519 { 2520 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2521 s390_disasm(ENC3(MNM, GPR, UDXB), "sra", r1, d2, 0, b2); 2522 2523 return emit_RS(p, 0x8a000000, r1, 0, b2, d2); 2524 } 2525 2526 2527 static UChar * 2528 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 2529 { 2530 vassert(s390_host_has_ldisp || dh2 == 0); 2531 2532 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2533 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2); 2534 2535 return emit_RSY(p, 0xeb000000000aULL, r1, r3, b2, dl2, dh2); 2536 } 2537 2538 2539 static UChar * 2540 s390_emit_SRL(UChar *p, UChar r1, UChar b2, UShort d2) 2541 { 2542 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2543 s390_disasm(ENC3(MNM, GPR, UDXB), "srl", r1, d2, 0, b2); 2544 2545 return emit_RS(p, 0x88000000, r1, 0, b2, d2); 2546 } 2547 2548 2549 static UChar * 2550 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2) 2551 { 2552 vassert(s390_host_has_ldisp || dh2 == 0); 2553 2554 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2555 s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2); 2556 2557 return emit_RSY(p, 0xeb000000000cULL, r1, r3, b2, dl2, dh2); 2558 } 2559 2560 2561 static UChar * 2562 s390_emit_ST(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2563 { 2564 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2565 s390_disasm(ENC3(MNM, GPR, UDXB), "st", r1, d2, x2, b2); 2566 2567 return emit_RX(p, 0x50000000, r1, x2, b2, d2); 2568 } 2569 2570 2571 static UChar * 2572 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2573 { 2574 vassert(s390_host_has_ldisp); 2575 2576 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2577 s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2); 2578 2579 return emit_RXY(p, 0xe30000000050ULL, r1, x2, b2, dl2, dh2); 2580 } 2581 2582 2583 static UChar * 2584 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2585 { 2586 vassert(s390_host_has_ldisp || dh2 == 0); 2587 2588 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2589 s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2); 2590 2591 return emit_RXY(p, 0xe30000000024ULL, r1, x2, b2, dl2, dh2); 2592 } 2593 2594 2595 static UChar * 2596 s390_emit_STC(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2597 { 2598 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2599 s390_disasm(ENC3(MNM, GPR, UDXB), "stc", r1, d2, x2, b2); 2600 2601 return emit_RX(p, 0x42000000, r1, x2, b2, d2); 2602 } 2603 2604 2605 static UChar * 2606 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2607 { 2608 vassert(s390_host_has_ldisp); 2609 2610 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2611 s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2); 2612 2613 return emit_RXY(p, 0xe30000000072ULL, r1, x2, b2, dl2, dh2); 2614 } 2615 2616 2617 static UChar * 2618 s390_emit_STH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2619 { 2620 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2621 s390_disasm(ENC3(MNM, GPR, UDXB), "sth", r1, d2, x2, b2); 2622 2623 return emit_RX(p, 0x40000000, r1, x2, b2, d2); 2624 } 2625 2626 2627 static UChar * 2628 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2629 { 2630 vassert(s390_host_has_ldisp); 2631 2632 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2633 s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2); 2634 2635 return emit_RXY(p, 0xe30000000070ULL, r1, x2, b2, dl2, dh2); 2636 } 2637 2638 2639 static UChar * 2640 s390_emit_SR(UChar *p, UChar r1, UChar r2) 2641 { 2642 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2643 s390_disasm(ENC3(MNM, GPR, GPR), "sr", r1, r2); 2644 2645 return emit_RR(p, 0x1b00, r1, r2); 2646 } 2647 2648 2649 static UChar * 2650 s390_emit_SGR(UChar *p, UChar r1, UChar r2) 2651 { 2652 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2653 s390_disasm(ENC3(MNM, GPR, GPR), "sgr", r1, r2); 2654 2655 return emit_RRE(p, 0xb9090000, r1, r2); 2656 } 2657 2658 2659 static UChar * 2660 s390_emit_S(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2661 { 2662 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2663 s390_disasm(ENC3(MNM, GPR, UDXB), "s", r1, d2, x2, b2); 2664 2665 return emit_RX(p, 0x5b000000, r1, x2, b2, d2); 2666 } 2667 2668 2669 static UChar * 2670 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2671 { 2672 vassert(s390_host_has_ldisp); 2673 2674 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2675 s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2); 2676 2677 return emit_RXY(p, 0xe3000000005bULL, r1, x2, b2, dl2, dh2); 2678 } 2679 2680 2681 static UChar * 2682 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2683 { 2684 vassert(s390_host_has_ldisp || dh2 == 0); 2685 2686 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2687 s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2); 2688 2689 return emit_RXY(p, 0xe30000000009ULL, r1, x2, b2, dl2, dh2); 2690 } 2691 2692 2693 static UChar * 2694 s390_emit_SH(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2695 { 2696 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2697 s390_disasm(ENC3(MNM, GPR, UDXB), "sh", r1, d2, x2, b2); 2698 2699 return emit_RX(p, 0x4b000000, r1, x2, b2, d2); 2700 } 2701 2702 2703 static UChar * 2704 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2705 { 2706 vassert(s390_host_has_ldisp); 2707 2708 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2709 s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2); 2710 2711 return emit_RXY(p, 0xe3000000007bULL, r1, x2, b2, dl2, dh2); 2712 } 2713 2714 2715 static UChar * 2716 s390_emit_SLFI(UChar *p, UChar r1, UInt i2) 2717 { 2718 vassert(s390_host_has_eimm); 2719 2720 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2721 s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2); 2722 2723 return emit_RIL(p, 0xc20500000000ULL, r1, i2); 2724 } 2725 2726 2727 static UChar * 2728 s390_emit_SLGFI(UChar *p, UChar r1, UInt i2) 2729 { 2730 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2731 s390_disasm(ENC3(MNM, GPR, UINT), "slgfi", r1, i2); 2732 2733 return emit_RIL(p, 0xc20400000000ULL, r1, i2); 2734 } 2735 2736 2737 static UChar * 2738 s390_emit_LDR(UChar *p, UChar r1, UChar r2) 2739 { 2740 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2741 s390_disasm(ENC3(MNM, FPR, FPR), "ldr", r1, r2); 2742 2743 return emit_RR(p, 0x2800, r1, r2); 2744 } 2745 2746 2747 static UChar * 2748 s390_emit_LE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2749 { 2750 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2751 s390_disasm(ENC3(MNM, FPR, UDXB), "le", r1, d2, x2, b2); 2752 2753 return emit_RX(p, 0x78000000, r1, x2, b2, d2); 2754 } 2755 2756 2757 static UChar * 2758 s390_emit_LD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2759 { 2760 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2761 s390_disasm(ENC3(MNM, FPR, UDXB), "ld", r1, d2, x2, b2); 2762 2763 return emit_RX(p, 0x68000000, r1, x2, b2, d2); 2764 } 2765 2766 2767 static UChar * 2768 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2769 { 2770 vassert(s390_host_has_ldisp); 2771 2772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2773 s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2); 2774 2775 return emit_RXY(p, 0xed0000000064ULL, r1, x2, b2, dl2, dh2); 2776 } 2777 2778 2779 static UChar * 2780 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2781 { 2782 vassert(s390_host_has_ldisp); 2783 2784 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2785 s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2); 2786 2787 return emit_RXY(p, 0xed0000000065ULL, r1, x2, b2, dl2, dh2); 2788 } 2789 2790 2791 static UChar * 2792 s390_emit_LFPC(UChar *p, UChar b2, UShort d2) 2793 { 2794 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2795 s390_disasm(ENC2(MNM, UDXB), "lfpc", d2, 0, b2); 2796 2797 return emit_S(p, 0xb29d0000, b2, d2); 2798 } 2799 2800 2801 static UChar * 2802 s390_emit_LDGR(UChar *p, UChar r1, UChar r2) 2803 { 2804 vassert(s390_host_has_fgx); 2805 2806 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2807 s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2); 2808 2809 return emit_RRE(p, 0xb3c10000, r1, r2); 2810 } 2811 2812 2813 static UChar * 2814 s390_emit_LGDR(UChar *p, UChar r1, UChar r2) 2815 { 2816 vassert(s390_host_has_fgx); 2817 2818 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2819 s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2); 2820 2821 return emit_RRE(p, 0xb3cd0000, r1, r2); 2822 } 2823 2824 2825 static UChar * 2826 s390_emit_LZER(UChar *p, UChar r1, UChar r2) 2827 { 2828 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2829 s390_disasm(ENC2(MNM, FPR), "lzer", r1); 2830 2831 return emit_RRE(p, 0xb3740000, r1, r2); 2832 } 2833 2834 2835 static UChar * 2836 s390_emit_LZDR(UChar *p, UChar r1, UChar r2) 2837 { 2838 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2839 s390_disasm(ENC2(MNM, FPR), "lzdr", r1); 2840 2841 return emit_RRE(p, 0xb3750000, r1, r2); 2842 } 2843 2844 2845 static UChar * 2846 s390_emit_SFPC(UChar *p, UChar r1, UChar r2) 2847 { 2848 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2849 s390_disasm(ENC2(MNM, GPR), "sfpc", r1); 2850 2851 return emit_RRE(p, 0xb3840000, r1, r2); 2852 } 2853 2854 2855 static UChar * 2856 s390_emit_STE(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2857 { 2858 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2859 s390_disasm(ENC3(MNM, FPR, UDXB), "ste", r1, d2, x2, b2); 2860 2861 return emit_RX(p, 0x70000000, r1, x2, b2, d2); 2862 } 2863 2864 2865 static UChar * 2866 s390_emit_STD(UChar *p, UChar r1, UChar x2, UChar b2, UShort d2) 2867 { 2868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2869 s390_disasm(ENC3(MNM, FPR, UDXB), "std", r1, d2, x2, b2); 2870 2871 return emit_RX(p, 0x60000000, r1, x2, b2, d2); 2872 } 2873 2874 2875 static UChar * 2876 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2877 { 2878 vassert(s390_host_has_ldisp); 2879 2880 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2881 s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2); 2882 2883 return emit_RXY(p, 0xed0000000066ULL, r1, x2, b2, dl2, dh2); 2884 } 2885 2886 2887 static UChar * 2888 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 2889 { 2890 vassert(s390_host_has_ldisp); 2891 2892 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2893 s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2); 2894 2895 return emit_RXY(p, 0xed0000000067ULL, r1, x2, b2, dl2, dh2); 2896 } 2897 2898 2899 static UChar * 2900 s390_emit_STFPC(UChar *p, UChar b2, UShort d2) 2901 { 2902 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2903 s390_disasm(ENC2(MNM, UDXB), "stfpc", d2, 0, b2); 2904 2905 return emit_S(p, 0xb29c0000, b2, d2); 2906 } 2907 2908 2909 static UChar * 2910 s390_emit_AEBR(UChar *p, UChar r1, UChar r2) 2911 { 2912 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2913 s390_disasm(ENC3(MNM, FPR, FPR), "aebr", r1, r2); 2914 2915 return emit_RRE(p, 0xb30a0000, r1, r2); 2916 } 2917 2918 2919 static UChar * 2920 s390_emit_ADBR(UChar *p, UChar r1, UChar r2) 2921 { 2922 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2923 s390_disasm(ENC3(MNM, FPR, FPR), "adbr", r1, r2); 2924 2925 return emit_RRE(p, 0xb31a0000, r1, r2); 2926 } 2927 2928 2929 static UChar * 2930 s390_emit_AXBR(UChar *p, UChar r1, UChar r2) 2931 { 2932 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2933 s390_disasm(ENC3(MNM, FPR, FPR), "axbr", r1, r2); 2934 2935 return emit_RRE(p, 0xb34a0000, r1, r2); 2936 } 2937 2938 2939 static UChar * 2940 s390_emit_CEBR(UChar *p, UChar r1, UChar r2) 2941 { 2942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2943 s390_disasm(ENC3(MNM, FPR, FPR), "cebr", r1, r2); 2944 2945 return emit_RRE(p, 0xb3090000, r1, r2); 2946 } 2947 2948 2949 static UChar * 2950 s390_emit_CDBR(UChar *p, UChar r1, UChar r2) 2951 { 2952 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2953 s390_disasm(ENC3(MNM, FPR, FPR), "cdbr", r1, r2); 2954 2955 return emit_RRE(p, 0xb3190000, r1, r2); 2956 } 2957 2958 2959 static UChar * 2960 s390_emit_CXBR(UChar *p, UChar r1, UChar r2) 2961 { 2962 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2963 s390_disasm(ENC3(MNM, FPR, FPR), "cxbr", r1, r2); 2964 2965 return emit_RRE(p, 0xb3490000, r1, r2); 2966 } 2967 2968 2969 static UChar * 2970 s390_emit_CEFBR(UChar *p, UChar r1, UChar r2) 2971 { 2972 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2973 s390_disasm(ENC3(MNM, FPR, GPR), "cefbr", r1, r2); 2974 2975 return emit_RRE(p, 0xb3940000, r1, r2); 2976 } 2977 2978 2979 static UChar * 2980 s390_emit_CDFBR(UChar *p, UChar r1, UChar r2) 2981 { 2982 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2983 s390_disasm(ENC3(MNM, FPR, GPR), "cdfbr", r1, r2); 2984 2985 return emit_RRE(p, 0xb3950000, r1, r2); 2986 } 2987 2988 2989 static UChar * 2990 s390_emit_CXFBR(UChar *p, UChar r1, UChar r2) 2991 { 2992 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 2993 s390_disasm(ENC3(MNM, FPR, GPR), "cxfbr", r1, r2); 2994 2995 return emit_RRE(p, 0xb3960000, r1, r2); 2996 } 2997 2998 2999 static UChar * 3000 s390_emit_CEGBR(UChar *p, UChar r1, UChar r2) 3001 { 3002 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3003 s390_disasm(ENC3(MNM, FPR, GPR), "cegbr", r1, r2); 3004 3005 return emit_RRE(p, 0xb3a40000, r1, r2); 3006 } 3007 3008 3009 static UChar * 3010 s390_emit_CDGBR(UChar *p, UChar r1, UChar r2) 3011 { 3012 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3013 s390_disasm(ENC3(MNM, FPR, GPR), "cdgbr", r1, r2); 3014 3015 return emit_RRE(p, 0xb3a50000, r1, r2); 3016 } 3017 3018 3019 static UChar * 3020 s390_emit_CXGBR(UChar *p, UChar r1, UChar r2) 3021 { 3022 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3023 s390_disasm(ENC3(MNM, FPR, GPR), "cxgbr", r1, r2); 3024 3025 return emit_RRE(p, 0xb3a60000, r1, r2); 3026 } 3027 3028 3029 static UChar * 3030 s390_emit_CFEBR(UChar *p, UChar r3, UChar r1, UChar r2) 3031 { 3032 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3033 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfebr", r1, r3, r2); 3034 3035 return emit_RRF3(p, 0xb3980000, r3, r1, r2); 3036 } 3037 3038 3039 static UChar * 3040 s390_emit_CFDBR(UChar *p, UChar r3, UChar r1, UChar r2) 3041 { 3042 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3043 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfdbr", r1, r3, r2); 3044 3045 return emit_RRF3(p, 0xb3990000, r3, r1, r2); 3046 } 3047 3048 3049 static UChar * 3050 s390_emit_CFXBR(UChar *p, UChar r3, UChar r1, UChar r2) 3051 { 3052 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3053 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cfxbr", r1, r3, r2); 3054 3055 return emit_RRF3(p, 0xb39a0000, r3, r1, r2); 3056 } 3057 3058 3059 static UChar * 3060 s390_emit_CGEBR(UChar *p, UChar r3, UChar r1, UChar r2) 3061 { 3062 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3063 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgebr", r1, r3, r2); 3064 3065 return emit_RRF3(p, 0xb3a80000, r3, r1, r2); 3066 } 3067 3068 3069 static UChar * 3070 s390_emit_CGDBR(UChar *p, UChar r3, UChar r1, UChar r2) 3071 { 3072 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3073 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgdbr", r1, r3, r2); 3074 3075 return emit_RRF3(p, 0xb3a90000, r3, r1, r2); 3076 } 3077 3078 3079 static UChar * 3080 s390_emit_CGXBR(UChar *p, UChar r3, UChar r1, UChar r2) 3081 { 3082 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3083 s390_disasm(ENC4(MNM, GPR, UINT, FPR), "cgxbr", r1, r3, r2); 3084 3085 return emit_RRF3(p, 0xb3aa0000, r3, r1, r2); 3086 } 3087 3088 3089 static UChar * 3090 s390_emit_DEBR(UChar *p, UChar r1, UChar r2) 3091 { 3092 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3093 s390_disasm(ENC3(MNM, FPR, FPR), "debr", r1, r2); 3094 3095 return emit_RRE(p, 0xb30d0000, r1, r2); 3096 } 3097 3098 3099 static UChar * 3100 s390_emit_DDBR(UChar *p, UChar r1, UChar r2) 3101 { 3102 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3103 s390_disasm(ENC3(MNM, FPR, FPR), "ddbr", r1, r2); 3104 3105 return emit_RRE(p, 0xb31d0000, r1, r2); 3106 } 3107 3108 3109 static UChar * 3110 s390_emit_DXBR(UChar *p, UChar r1, UChar r2) 3111 { 3112 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3113 s390_disasm(ENC3(MNM, FPR, FPR), "dxbr", r1, r2); 3114 3115 return emit_RRE(p, 0xb34d0000, r1, r2); 3116 } 3117 3118 3119 static UChar * 3120 s390_emit_LCEBR(UChar *p, UChar r1, UChar r2) 3121 { 3122 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3123 s390_disasm(ENC3(MNM, FPR, FPR), "lcebr", r1, r2); 3124 3125 return emit_RRE(p, 0xb3030000, r1, r2); 3126 } 3127 3128 3129 static UChar * 3130 s390_emit_LCDBR(UChar *p, UChar r1, UChar r2) 3131 { 3132 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3133 s390_disasm(ENC3(MNM, FPR, FPR), "lcdbr", r1, r2); 3134 3135 return emit_RRE(p, 0xb3130000, r1, r2); 3136 } 3137 3138 3139 static UChar * 3140 s390_emit_LCXBR(UChar *p, UChar r1, UChar r2) 3141 { 3142 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3143 s390_disasm(ENC3(MNM, FPR, FPR), "lcxbr", r1, r2); 3144 3145 return emit_RRE(p, 0xb3430000, r1, r2); 3146 } 3147 3148 3149 static UChar * 3150 s390_emit_LDEBR(UChar *p, UChar r1, UChar r2) 3151 { 3152 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3153 s390_disasm(ENC3(MNM, FPR, FPR), "ldebr", r1, r2); 3154 3155 return emit_RRE(p, 0xb3040000, r1, r2); 3156 } 3157 3158 3159 static UChar * 3160 s390_emit_LXDBR(UChar *p, UChar r1, UChar r2) 3161 { 3162 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3163 s390_disasm(ENC3(MNM, FPR, FPR), "lxdbr", r1, r2); 3164 3165 return emit_RRE(p, 0xb3050000, r1, r2); 3166 } 3167 3168 3169 static UChar * 3170 s390_emit_LXEBR(UChar *p, UChar r1, UChar r2) 3171 { 3172 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3173 s390_disasm(ENC3(MNM, FPR, FPR), "lxebr", r1, r2); 3174 3175 return emit_RRE(p, 0xb3060000, r1, r2); 3176 } 3177 3178 3179 static UChar * 3180 s390_emit_LNEBR(UChar *p, UChar r1, UChar r2) 3181 { 3182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3183 s390_disasm(ENC3(MNM, FPR, FPR), "lnebr", r1, r2); 3184 3185 return emit_RRE(p, 0xb3010000, r1, r2); 3186 } 3187 3188 3189 static UChar * 3190 s390_emit_LNDBR(UChar *p, UChar r1, UChar r2) 3191 { 3192 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3193 s390_disasm(ENC3(MNM, FPR, FPR), "lndbr", r1, r2); 3194 3195 return emit_RRE(p, 0xb3110000, r1, r2); 3196 } 3197 3198 3199 static UChar * 3200 s390_emit_LNXBR(UChar *p, UChar r1, UChar r2) 3201 { 3202 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3203 s390_disasm(ENC3(MNM, FPR, FPR), "lnxbr", r1, r2); 3204 3205 return emit_RRE(p, 0xb3410000, r1, r2); 3206 } 3207 3208 3209 static UChar * 3210 s390_emit_LPEBR(UChar *p, UChar r1, UChar r2) 3211 { 3212 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3213 s390_disasm(ENC3(MNM, FPR, FPR), "lpebr", r1, r2); 3214 3215 return emit_RRE(p, 0xb3000000, r1, r2); 3216 } 3217 3218 3219 static UChar * 3220 s390_emit_LPDBR(UChar *p, UChar r1, UChar r2) 3221 { 3222 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3223 s390_disasm(ENC3(MNM, FPR, FPR), "lpdbr", r1, r2); 3224 3225 return emit_RRE(p, 0xb3100000, r1, r2); 3226 } 3227 3228 3229 static UChar * 3230 s390_emit_LPXBR(UChar *p, UChar r1, UChar r2) 3231 { 3232 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3233 s390_disasm(ENC3(MNM, FPR, FPR), "lpxbr", r1, r2); 3234 3235 return emit_RRE(p, 0xb3400000, r1, r2); 3236 } 3237 3238 3239 static UChar * 3240 s390_emit_LEDBR(UChar *p, UChar r1, UChar r2) 3241 { 3242 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3243 s390_disasm(ENC3(MNM, FPR, FPR), "ledbr", r1, r2); 3244 3245 return emit_RRE(p, 0xb3440000, r1, r2); 3246 } 3247 3248 3249 static UChar * 3250 s390_emit_LDXBR(UChar *p, UChar r1, UChar r2) 3251 { 3252 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3253 s390_disasm(ENC3(MNM, FPR, FPR), "ldxbr", r1, r2); 3254 3255 return emit_RRE(p, 0xb3450000, r1, r2); 3256 } 3257 3258 3259 static UChar * 3260 s390_emit_LEXBR(UChar *p, UChar r1, UChar r2) 3261 { 3262 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3263 s390_disasm(ENC3(MNM, FPR, FPR), "lexbr", r1, r2); 3264 3265 return emit_RRE(p, 0xb3460000, r1, r2); 3266 } 3267 3268 3269 static UChar * 3270 s390_emit_MEEBR(UChar *p, UChar r1, UChar r2) 3271 { 3272 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3273 s390_disasm(ENC3(MNM, FPR, FPR), "meebr", r1, r2); 3274 3275 return emit_RRE(p, 0xb3170000, r1, r2); 3276 } 3277 3278 3279 static UChar * 3280 s390_emit_MDBR(UChar *p, UChar r1, UChar r2) 3281 { 3282 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3283 s390_disasm(ENC3(MNM, FPR, FPR), "mdbr", r1, r2); 3284 3285 return emit_RRE(p, 0xb31c0000, r1, r2); 3286 } 3287 3288 3289 static UChar * 3290 s390_emit_MXBR(UChar *p, UChar r1, UChar r2) 3291 { 3292 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3293 s390_disasm(ENC3(MNM, FPR, FPR), "mxbr", r1, r2); 3294 3295 return emit_RRE(p, 0xb34c0000, r1, r2); 3296 } 3297 3298 3299 static UChar * 3300 s390_emit_MAEBR(UChar *p, UChar r1, UChar r3, UChar r2) 3301 { 3302 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3303 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "maebr", r1, r3, r2); 3304 3305 return emit_RRF(p, 0xb30e0000, r1, r3, r2); 3306 } 3307 3308 3309 static UChar * 3310 s390_emit_MADBR(UChar *p, UChar r1, UChar r3, UChar r2) 3311 { 3312 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3313 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "madbr", r1, r3, r2); 3314 3315 return emit_RRF(p, 0xb31e0000, r1, r3, r2); 3316 } 3317 3318 3319 static UChar * 3320 s390_emit_MSEBR(UChar *p, UChar r1, UChar r3, UChar r2) 3321 { 3322 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3323 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msebr", r1, r3, r2); 3324 3325 return emit_RRF(p, 0xb30f0000, r1, r3, r2); 3326 } 3327 3328 3329 static UChar * 3330 s390_emit_MSDBR(UChar *p, UChar r1, UChar r3, UChar r2) 3331 { 3332 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3333 s390_disasm(ENC4(MNM, FPR, FPR, FPR), "msdbr", r1, r3, r2); 3334 3335 return emit_RRF(p, 0xb31f0000, r1, r3, r2); 3336 } 3337 3338 3339 static UChar * 3340 s390_emit_SQEBR(UChar *p, UChar r1, UChar r2) 3341 { 3342 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3343 s390_disasm(ENC3(MNM, FPR, FPR), "sqebr", r1, r2); 3344 3345 return emit_RRE(p, 0xb3140000, r1, r2); 3346 } 3347 3348 3349 static UChar * 3350 s390_emit_SQDBR(UChar *p, UChar r1, UChar r2) 3351 { 3352 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3353 s390_disasm(ENC3(MNM, FPR, FPR), "sqdbr", r1, r2); 3354 3355 return emit_RRE(p, 0xb3150000, r1, r2); 3356 } 3357 3358 3359 static UChar * 3360 s390_emit_SQXBR(UChar *p, UChar r1, UChar r2) 3361 { 3362 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3363 s390_disasm(ENC3(MNM, FPR, FPR), "sqxbr", r1, r2); 3364 3365 return emit_RRE(p, 0xb3160000, r1, r2); 3366 } 3367 3368 3369 static UChar * 3370 s390_emit_SEBR(UChar *p, UChar r1, UChar r2) 3371 { 3372 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3373 s390_disasm(ENC3(MNM, FPR, FPR), "sebr", r1, r2); 3374 3375 return emit_RRE(p, 0xb30b0000, r1, r2); 3376 } 3377 3378 3379 static UChar * 3380 s390_emit_SDBR(UChar *p, UChar r1, UChar r2) 3381 { 3382 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3383 s390_disasm(ENC3(MNM, FPR, FPR), "sdbr", r1, r2); 3384 3385 return emit_RRE(p, 0xb31b0000, r1, r2); 3386 } 3387 3388 3389 static UChar * 3390 s390_emit_SXBR(UChar *p, UChar r1, UChar r2) 3391 { 3392 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) 3393 s390_disasm(ENC3(MNM, FPR, FPR), "sxbr", r1, r2); 3394 3395 return emit_RRE(p, 0xb34b0000, r1, r2); 3396 } 3397 3398 3399 /* Provide a symbolic name for register "R0" */ 3400 #define R0 0 3401 3402 /* Split up a 20-bit displacement into its high and low piece 3403 suitable for passing as function arguments */ 3404 #define DISP20(d) (((UInt)d) & 0xFFF), ((((UInt)d) >> 12) & 0xFF) 3405 3406 /*---------------------------------------------------------------*/ 3407 /*--- Helper functions ---*/ 3408 /*---------------------------------------------------------------*/ 3409 3410 static __inline__ Bool 3411 uint_fits_signed_16bit(UInt val) 3412 { 3413 int v = val & 0xFFFFu; 3414 3415 /* sign extend */ 3416 v = (v << 16) >> 16; 3417 3418 return val == (UInt)v; 3419 } 3420 3421 3422 static __inline__ Bool 3423 ulong_fits_signed_16bit(ULong val) 3424 { 3425 Long v = val & 0xFFFFu; 3426 3427 /* sign extend */ 3428 v = (v << 48) >> 48; 3429 3430 return val == (ULong)v; 3431 } 3432 3433 3434 static __inline__ Bool 3435 ulong_fits_signed_32bit(ULong val) 3436 { 3437 Long v = val & 0xFFFFFFFFu; 3438 3439 /* sign extend */ 3440 v = (v << 32) >> 32; 3441 3442 return val == (ULong)v; 3443 } 3444 3445 3446 static __inline__ Bool 3447 ulong_fits_unsigned_32bit(ULong val) 3448 { 3449 return (val & 0xFFFFFFFFu) == val; 3450 } 3451 3452 3453 /* Load a 64-bit immediate VAL into register REG. */ 3454 static UChar * 3455 s390_emit_load_64imm(UChar *p, UChar reg, ULong val) 3456 { 3457 if (ulong_fits_signed_16bit(val)) { 3458 return s390_emit_LGHI(p, reg, val); 3459 } 3460 3461 if (s390_host_has_eimm) { 3462 if (ulong_fits_unsigned_32bit(val)) { 3463 return s390_emit_LLILF(p, reg, val); 3464 } 3465 if (ulong_fits_signed_32bit(val)) { 3466 /* LGFI's sign extension will recreate the correct 64-bit value */ 3467 return s390_emit_LGFI(p, reg, val); 3468 } 3469 /* Do it in two steps: upper half [0:31] and lower half [32:63] */ 3470 p = s390_emit_IIHF(p, reg, val >> 32); 3471 return s390_emit_IILF(p, reg, val & 0xFFFFFFFF); 3472 } 3473 3474 /* Fall back */ 3475 if (ulong_fits_unsigned_32bit(val)) { 3476 p = s390_emit_LLILH(p, reg, (val >> 16) & 0xFFFF); /* sets val[32:47] 3477 val[0:31] = 0 */ 3478 p = s390_emit_IILL(p, reg, val & 0xFFFF); /* sets val[48:63] */ 3479 return p; 3480 } 3481 3482 p = s390_emit_IIHH(p, reg, (val >> 48) & 0xFFFF); 3483 p = s390_emit_IIHL(p, reg, (val >> 32) & 0xFFFF); 3484 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF); 3485 p = s390_emit_IILL(p, reg, val & 0xFFFF); 3486 3487 return p; 3488 } 3489 3490 /* Load a 32-bit immediate VAL into register REG. */ 3491 static UChar * 3492 s390_emit_load_32imm(UChar *p, UChar reg, UInt val) 3493 { 3494 if (uint_fits_signed_16bit(val)) { 3495 /* LHI's sign extension will recreate the correct 32-bit value */ 3496 return s390_emit_LHI(p, reg, val); 3497 } 3498 if (s390_host_has_eimm) { 3499 return s390_emit_IILF(p, reg, val); 3500 } 3501 /* val[0:15] --> (val >> 16) & 0xFFFF 3502 val[16:31] --> val & 0xFFFF */ 3503 p = s390_emit_IILH(p, reg, (val >> 16) & 0xFFFF); 3504 return s390_emit_IILL(p, reg, val & 0xFFFF); 3505 } 3506 3507 /*------------------------------------------------------------*/ 3508 /*--- Wrapper functions ---*/ 3509 /*------------------------------------------------------------*/ 3510 3511 /* r1[32:63],r1+1[32:63] = r1+1[32:63] * memory[op2addr][0:31] */ 3512 static UChar * 3513 s390_emit_MFYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh) 3514 { 3515 if (s390_host_has_gie) { 3516 return s390_emit_MFY(p, r1, x, b, dl, dh); 3517 } 3518 3519 /* Load from memory into R0, then MULTIPLY with R1 */ 3520 p = s390_emit_LY(p, R0, x, b, dl, dh); 3521 return s390_emit_MR(p, r1, R0); 3522 } 3523 3524 /* r1[32:63] = r1[32:63] * memory[op2addr][0:15] */ 3525 static UChar * 3526 s390_emit_MHYw(UChar *p, UChar r1, UChar x, UChar b, UShort dl, UChar dh) 3527 { 3528 if (s390_host_has_gie) { 3529 return s390_emit_MHY(p, r1, x, b, dl, dh); 3530 } 3531 3532 /* Load from memory into R0, then MULTIPLY with R1 */ 3533 p = s390_emit_LHY(p, R0, x, b, dl, dh); 3534 return s390_emit_MSR(p, r1, R0); 3535 } 3536 3537 /* r1[32:63] = r1[32:63] * i2 */ 3538 static UChar * 3539 s390_emit_MSFIw(UChar *p, UChar r1, UInt i2) 3540 { 3541 if (s390_host_has_gie) { 3542 return s390_emit_MSFI(p, r1, i2); 3543 } 3544 3545 /* Load I2 into R0; then MULTIPLY R0 with R1 */ 3546 p = s390_emit_load_32imm(p, R0, i2); 3547 return s390_emit_MSR(p, r1, R0); 3548 } 3549 3550 3551 /* r1[32:63] = r1[32:63] & i2 */ 3552 static UChar * 3553 s390_emit_NILFw(UChar *p, UChar r1, UInt i2) 3554 { 3555 if (s390_host_has_eimm) { 3556 return s390_emit_NILF(p, r1, i2); 3557 } 3558 3559 /* Load I2 into R0; then AND R0 with R1 */ 3560 p = s390_emit_load_32imm(p, R0, i2); 3561 return s390_emit_NR(p, r1, R0); 3562 } 3563 3564 3565 /* r1[32:63] = r1[32:63] | i2 */ 3566 static UChar * 3567 s390_emit_OILFw(UChar *p, UChar r1, UInt i2) 3568 { 3569 if (s390_host_has_eimm) { 3570 return s390_emit_OILF(p, r1, i2); 3571 } 3572 3573 /* Load I2 into R0; then AND R0 with R1 */ 3574 p = s390_emit_load_32imm(p, R0, i2); 3575 return s390_emit_OR(p, r1, R0); 3576 } 3577 3578 3579 /* r1[32:63] = r1[32:63] ^ i2 */ 3580 static UChar * 3581 s390_emit_XILFw(UChar *p, UChar r1, UInt i2) 3582 { 3583 if (s390_host_has_eimm) { 3584 return s390_emit_XILF(p, r1, i2); 3585 } 3586 3587 /* Load I2 into R0; then AND R0 with R1 */ 3588 p = s390_emit_load_32imm(p, R0, i2); 3589 return s390_emit_XR(p, r1, R0); 3590 } 3591 3592 3593 /* r1[32:63] = sign_extend(mem[op2addr][0:7]) */ 3594 static UChar * 3595 s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3596 { 3597 vassert(s390_host_has_ldisp || dh2 == 0); 3598 3599 if (s390_host_has_ldisp) { 3600 return s390_emit_LB(p, r1, x2, b2, dl2, dh2); 3601 } 3602 3603 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */ 3604 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */ 3605 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */ 3606 } 3607 3608 3609 /* r1[32:63] = sign_extend(r2[56:63]) */ 3610 static UChar * 3611 s390_emit_LBRw(UChar *p, UChar r1, UChar r2) 3612 { 3613 if (s390_host_has_eimm) { 3614 return s390_emit_LBR(p, r1, r2); 3615 } 3616 3617 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 3618 p = s390_emit_SLL(p, r1, R0, 24); /* r1 = r1 << 24 */ 3619 return s390_emit_SRA(p, r1, R0, 24); /* r1 = r1 >>a 24 */ 3620 } 3621 3622 3623 /* r1[0:63] = sign_extend(mem[op2addr][0:7]) */ 3624 static UChar * 3625 s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2) 3626 { 3627 vassert(s390_host_has_ldisp || dh2 == 0); 3628 3629 if (s390_host_has_ldisp) { 3630 return s390_emit_LGB(p, r1, x2, b2, dl2, dh2); 3631 } 3632 3633 p = s390_emit_IC(p, r1, x2, b2, dl2); /* r1[56:63] = mem[op2addr][0:7] */ 3634 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */ 3635 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */ 3636 } 3637 3638 3639 /* r1[0:63] = sign_extend(r2[56:63]) */ 3640 static UChar * 3641 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2) 3642 { 3643 if (s390_host_has_eimm) { 3644 return s390_emit_LGBR(p, r1, r2); 3645 } 3646 3647 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 3648 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 << 56 */ 3649 return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */ 3650 } 3651 3652 3653 /* r1[32:63] = sign_extend(r2[48:63]) */ 3654 static UChar * 3655 s390_emit_LHRw(UChar *p, UChar r1, UChar r2) 3656 { 3657 if (s390_host_has_eimm) { 3658 return s390_emit_LHR(p, r1, r2); 3659 } 3660 3661 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 3662 p = s390_emit_SLL(p, r1, R0, 16); /* r1 = r1 << 16 */ 3663 return s390_emit_SRA(p, r1, R0, 16); /* r1 = r1 >>a 16 */ 3664 } 3665 3666 3667 /* r1[0:63] = sign_extend(r2[48:63]) */ 3668 static UChar * 3669 s390_emit_LGHRw(UChar *p, UChar r1, UChar r2) 3670 { 3671 if (s390_host_has_eimm) { 3672 return s390_emit_LGHR(p, r1, r2); 3673 } 3674 3675 p = s390_emit_LR(p, r1, r2); /* r1 = r2 */ 3676 p = s390_emit_SLLG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 << 48 */ 3677 return s390_emit_SRAG(p, r1, r1, R0, DISP20(48)); /* r1 = r1 >>a 48 */ 3678 } 3679 3680 3681 /* r1[0:63] = sign_extend(i2) */ 3682 static UChar * 3683 s390_emit_LGFIw(UChar *p, UChar r1, UInt i2) 3684 { 3685 if (s390_host_has_eimm) { 3686 return s390_emit_LGFI(p, r1, i2); 3687 } 3688 3689 p = s390_emit_load_32imm(p, R0, i2); 3690 return s390_emit_LGFR(p, r1, R0); 3691 } 3692 3693 3694 /* r1[32:63] = zero_extend($r2[56:63]) */ 3695 static UChar * 3696 s390_emit_LLCRw(UChar *p, UChar r1, UChar r2) 3697 { 3698 if (s390_host_has_eimm) { 3699 return s390_emit_LLCR(p, r1, r2); 3700 } 3701 3702 p = s390_emit_LR(p, r1, r2); 3703 p = s390_emit_LHI(p, R0, 0xFF); 3704 return s390_emit_NR(p, r1, R0); 3705 } 3706 3707 3708 /* r1[0:63] = zero_extend($r2[56:63]) */ 3709 static UChar * 3710 s390_emit_LLGCRw(UChar *p, UChar r1, UChar r2) 3711 { 3712 if (s390_host_has_eimm) { 3713 return s390_emit_LLGCR(p, r1, r2); 3714 } 3715 3716 p = s390_emit_LR(p, r1, r2); 3717 p = s390_emit_LLILL(p, R0, 0xFF); 3718 return s390_emit_NGR(p, r1, R0); 3719 } 3720 3721 3722 /* r1[32:63] = zero_extend(r2[48:63]) */ 3723 static UChar * 3724 s390_emit_LLHRw(UChar *p, UChar r1, UChar r2) 3725 { 3726 if (s390_host_has_eimm) { 3727 return s390_emit_LLHR(p, r1, r2); 3728 } 3729 3730 p = s390_emit_LR(p, r1, r2); 3731 p = s390_emit_LLILL(p, R0, 0xFFFF); 3732 return s390_emit_NR(p, r1, R0); 3733 } 3734 3735 3736 /* r1[0:63] = zero_extend(r2[48:63]) */ 3737 static UChar * 3738 s390_emit_LLGHRw(UChar *p, UChar r1, UChar r2) 3739 { 3740 if (s390_host_has_eimm) { 3741 return s390_emit_LLGHR(p, r1, r2); 3742 } 3743 3744 p = s390_emit_LR(p, r1, r2); 3745 p = s390_emit_LLILL(p, R0, 0xFFFF); 3746 return s390_emit_NGR(p, r1, R0); 3747 } 3748 3749 3750 /* r1[32:63] = zero_extend(mem[op2addr][0:7]) */ 3751 static UChar * 3752 s390_emit_LLCw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 3753 { 3754 if (s390_host_has_eimm) { 3755 return s390_emit_LLC(p, r1, x2, b2, dl, dh); 3756 } 3757 3758 if (dh == 0) { 3759 p = s390_emit_IC(p, r1, x2, b2, dl); 3760 } else { 3761 p = s390_emit_ICY(p, r1, x2, b2, dl, dh); 3762 } 3763 p = s390_emit_LLILL(p, R0, 0xFF); 3764 return s390_emit_NR(p, r1, R0); 3765 } 3766 3767 3768 /* r1[32:63] = zero_extend(mem[op2addr][0:15]) */ 3769 static UChar * 3770 s390_emit_LLHw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 3771 { 3772 if (s390_host_has_eimm) { 3773 return s390_emit_LLH(p, r1, x2, b2, dl, dh); 3774 } 3775 3776 p = s390_emit_LLGH(p, r1, x2, b2, dl, dh); 3777 p = s390_emit_LLILL(p, R0, 0xFFFF); 3778 return s390_emit_NR(p, r1, R0); 3779 } 3780 3781 3782 /* r1[0:63] = zero_extend(i2) */ 3783 static UChar * 3784 s390_emit_LLILFw(UChar *p, UChar r1, UInt i2) 3785 { 3786 if (s390_host_has_eimm) { 3787 return s390_emit_LLILF(p, r1, i2); 3788 } 3789 3790 p = s390_emit_LLILH(p, r1, (i2 >> 16) & 0xFFFF); /* i2[0:15] */ 3791 return s390_emit_OILL(p, r1, i2 & 0xFFFF); 3792 } 3793 3794 3795 /* r1[32:63] = r1[32:63] + i2 */ 3796 static UChar * 3797 s390_emit_AFIw(UChar *p, UChar r1, UInt i2) 3798 { 3799 if (s390_host_has_eimm) { 3800 return s390_emit_AFI(p, r1, i2); 3801 } 3802 /* Load 32 bit immediate to R0 then add */ 3803 p = s390_emit_load_32imm(p, R0, i2); 3804 return s390_emit_AR(p, r1, R0); 3805 } 3806 3807 3808 /* r1[32:63] = r1[32:63] - i2 */ 3809 static UChar * 3810 s390_emit_SLFIw(UChar *p, UChar r1, UInt i2) 3811 { 3812 if (s390_host_has_eimm) { 3813 return s390_emit_SLFI(p, r1, i2); 3814 } 3815 3816 /* Load 32 bit immediate to R0 then subtract */ 3817 p = s390_emit_load_32imm(p, R0, i2); 3818 return s390_emit_SR(p, r1, R0); 3819 } 3820 3821 3822 /* r1[0:63] = r1[0:63] - zero_extend(i2) */ 3823 static UChar * 3824 s390_emit_SLGFIw(UChar *p, UChar r1, UInt i2) 3825 { 3826 if (s390_host_has_eimm) { 3827 return s390_emit_SLGFI(p, r1, i2); 3828 } 3829 3830 /* Load zero-extended 32 bit immediate to R0 then subtract */ 3831 p = s390_emit_load_64imm(p, R0, i2); 3832 return s390_emit_SGR(p, r1, R0); 3833 } 3834 3835 3836 static UChar * 3837 s390_emit_LTw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 3838 { 3839 if (s390_host_has_eimm) { 3840 return s390_emit_LT(p, r1, x2, b2, dl, dh); 3841 } 3842 /* Load 32 bit from memory to R0 then compare */ 3843 if (dh == 0) { 3844 p = s390_emit_L(p, R0, x2, b2, dl); 3845 } else { 3846 p = s390_emit_LY(p, R0, x2, b2, dl, dh); 3847 } 3848 return s390_emit_LTR(p, r1, R0); 3849 } 3850 3851 3852 static UChar * 3853 s390_emit_LTGw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl, UChar dh) 3854 { 3855 if (s390_host_has_eimm) { 3856 return s390_emit_LTG(p, r1, x2, b2, dl, dh); 3857 } 3858 /* Load 64 bit from memory to R0 then compare */ 3859 p = s390_emit_LG(p, R0, x2, b2, dl, dh); 3860 return s390_emit_LTGR(p, r1, R0); 3861 } 3862 3863 3864 static UChar * 3865 s390_emit_CFIw(UChar *p, UChar r1, UInt i2) 3866 { 3867 if (s390_host_has_eimm) { 3868 return s390_emit_CFI(p, r1, i2); 3869 } 3870 /* Load 32 bit immediate to R0 then compare */ 3871 p = s390_emit_load_32imm(p, R0, i2); 3872 return s390_emit_CR(p, r1, R0); 3873 } 3874 3875 3876 static UChar * 3877 s390_emit_CLFIw(UChar *p, UChar r1, UInt i2) 3878 { 3879 if (s390_host_has_eimm) { 3880 return s390_emit_CLFI(p, r1, i2); 3881 } 3882 /* Load 32 bit immediate to R0 then compare */ 3883 p = s390_emit_load_32imm(p, R0, i2); 3884 return s390_emit_CLR(p, r1, R0); 3885 } 3886 3887 3888 static UChar * 3889 s390_emit_LGDRw(UChar *p, UChar r1, UChar r2) 3890 { 3891 if (s390_host_has_fgx) { 3892 return s390_emit_LGDR(p, r1, r2); 3893 } 3894 3895 /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards 3896 smaller addresses and is 8-byte aligned. Then load the GPR from that 3897 memory location/ */ 3898 if (s390_host_has_ldisp) { 3899 p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 3900 return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 3901 } 3902 3903 /* No long displacement. Need to adjust SP explicitly as to avoid negative 3904 displacements. */ 3905 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8); 3906 p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0); 3907 p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0)); 3908 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8); 3909 } 3910 3911 3912 static UChar * 3913 s390_emit_LDGRw(UChar *p, UChar r1, UChar r2) 3914 { 3915 if (s390_host_has_fgx) { 3916 return s390_emit_LDGR(p, r1, r2); 3917 } 3918 3919 /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards 3920 smaller addresses and is 8-byte aligned. Then load the FPR from that 3921 memory location/ */ 3922 if (s390_host_has_ldisp) { 3923 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 3924 return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8)); 3925 } 3926 3927 /* No long displacement. Need to adjust SP explicitly as to avoid negative 3928 displacements. */ 3929 p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8); 3930 p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0)); 3931 p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0); 3932 return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8); 3933 } 3934 3935 3936 /*---------------------------------------------------------------*/ 3937 /*--- Constructors for the various s390_insn kinds ---*/ 3938 /*---------------------------------------------------------------*/ 3939 3940 s390_insn * 3941 s390_insn_load(UChar size, HReg dst, s390_amode *src) 3942 { 3943 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 3944 3945 insn->tag = S390_INSN_LOAD; 3946 insn->size = size; 3947 insn->variant.load.src = src; 3948 insn->variant.load.dst = dst; 3949 3950 vassert(size == 1 || size == 2 || size == 4 || size == 8); 3951 3952 return insn; 3953 } 3954 3955 3956 s390_insn * 3957 s390_insn_store(UChar size, s390_amode *dst, HReg src) 3958 { 3959 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 3960 3961 insn->tag = S390_INSN_STORE; 3962 insn->size = size; 3963 insn->variant.store.src = src; 3964 insn->variant.store.dst = dst; 3965 3966 vassert(size == 1 || size == 2 || size == 4 || size == 8); 3967 3968 return insn; 3969 } 3970 3971 3972 s390_insn * 3973 s390_insn_move(UChar size, HReg dst, HReg src) 3974 { 3975 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 3976 3977 insn->tag = S390_INSN_MOVE; 3978 insn->size = size; 3979 insn->variant.move.src = src; 3980 insn->variant.move.dst = dst; 3981 3982 vassert(size == 1 || size == 2 || size == 4 || size == 8); 3983 3984 return insn; 3985 } 3986 3987 3988 s390_insn * 3989 s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, s390_opnd_RMI src) 3990 { 3991 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 3992 3993 insn->tag = S390_INSN_COND_MOVE; 3994 insn->size = size; 3995 insn->variant.cond_move.cond = cond; 3996 insn->variant.cond_move.src = src; 3997 insn->variant.cond_move.dst = dst; 3998 3999 vassert(size == 1 || size == 2 || size == 4 || size == 8); 4000 4001 return insn; 4002 } 4003 4004 4005 s390_insn * 4006 s390_insn_load_immediate(UChar size, HReg dst, ULong value) 4007 { 4008 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4009 4010 insn->tag = S390_INSN_LOAD_IMMEDIATE; 4011 insn->size = size; 4012 insn->variant.load_immediate.dst = dst; 4013 insn->variant.load_immediate.value = value; 4014 4015 return insn; 4016 } 4017 4018 4019 s390_insn * 4020 s390_insn_alu(UChar size, s390_alu_t tag, HReg dst, s390_opnd_RMI op2) 4021 { 4022 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4023 4024 insn->tag = S390_INSN_ALU; 4025 insn->size = size; 4026 insn->variant.alu.tag = tag; 4027 insn->variant.alu.dst = dst; 4028 insn->variant.alu.op2 = op2; 4029 4030 return insn; 4031 } 4032 4033 4034 s390_insn * 4035 s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, s390_opnd_RMI op2, 4036 Bool signed_multiply) 4037 { 4038 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4039 4040 vassert(! hregIsVirtual(dst_hi)); 4041 vassert(! hregIsVirtual(dst_lo)); 4042 4043 insn->tag = S390_INSN_MUL; 4044 insn->size = size; 4045 insn->variant.mul.dst_hi = dst_hi; 4046 insn->variant.mul.dst_lo = dst_lo; 4047 insn->variant.mul.op2 = op2; 4048 insn->variant.mul.signed_multiply = signed_multiply; 4049 4050 return insn; 4051 } 4052 4053 4054 s390_insn * 4055 s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, s390_opnd_RMI op2, 4056 Bool signed_divide) 4057 { 4058 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4059 4060 vassert(size == 4 || size == 8); 4061 vassert(! hregIsVirtual(op1_hi)); 4062 vassert(! hregIsVirtual(op1_lo)); 4063 4064 insn->tag = S390_INSN_DIV; 4065 insn->size = size; 4066 insn->variant.div.op1_hi = op1_hi; 4067 insn->variant.div.op1_lo = op1_lo; 4068 insn->variant.div.op2 = op2; 4069 insn->variant.div.signed_divide = signed_divide; 4070 4071 return insn; 4072 } 4073 4074 4075 s390_insn * 4076 s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2) 4077 { 4078 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4079 4080 vassert(size == 8); 4081 vassert(! hregIsVirtual(op1)); 4082 vassert(! hregIsVirtual(rem)); 4083 4084 insn->tag = S390_INSN_DIVS; 4085 insn->size = size; 4086 insn->variant.divs.rem = rem; /* remainder */ 4087 insn->variant.divs.op1 = op1; /* also quotient */ 4088 insn->variant.divs.op2 = op2; 4089 4090 return insn; 4091 } 4092 4093 4094 s390_insn * 4095 s390_insn_clz(UChar size, HReg num_bits, HReg clobber, s390_opnd_RMI src) 4096 { 4097 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4098 4099 vassert(size == 8); 4100 vassert(! hregIsVirtual(num_bits)); 4101 vassert(! hregIsVirtual(clobber)); 4102 4103 insn->tag = S390_INSN_CLZ; 4104 insn->size = size; 4105 insn->variant.clz.num_bits = num_bits; 4106 insn->variant.clz.clobber = clobber; 4107 insn->variant.clz.src = src; 4108 4109 return insn; 4110 } 4111 4112 4113 s390_insn * 4114 s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, s390_opnd_RMI opnd) 4115 { 4116 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4117 4118 insn->tag = S390_INSN_UNOP; 4119 insn->size = size; 4120 insn->variant.unop.tag = tag; 4121 insn->variant.unop.dst = dst; 4122 insn->variant.unop.src = opnd; 4123 4124 return insn; 4125 } 4126 4127 4128 s390_insn * 4129 s390_insn_test(UChar size, s390_opnd_RMI src) 4130 { 4131 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4132 4133 vassert(size == 4 || size == 8); 4134 4135 insn->tag = S390_INSN_TEST; 4136 insn->size = size; 4137 insn->variant.test.src = src; 4138 4139 return insn; 4140 } 4141 4142 4143 s390_insn * 4144 s390_insn_cc2bool(HReg dst, s390_cc_t cond) 4145 { 4146 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4147 4148 insn->tag = S390_INSN_CC2BOOL; 4149 insn->size = 0; /* does not matter */ 4150 insn->variant.cc2bool.cond = cond; 4151 insn->variant.cc2bool.dst = dst; 4152 4153 return insn; 4154 } 4155 4156 4157 s390_insn * 4158 s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem) 4159 { 4160 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4161 4162 vassert(size == 4 || size == 8); 4163 vassert(op2->x == 0); 4164 4165 insn->tag = S390_INSN_CAS; 4166 insn->size = size; 4167 insn->variant.cas.op1 = op1; 4168 insn->variant.cas.op2 = op2; 4169 insn->variant.cas.op3 = op3; 4170 insn->variant.cas.old_mem = old_mem; 4171 4172 return insn; 4173 } 4174 4175 4176 s390_insn * 4177 s390_insn_compare(UChar size, HReg src1, s390_opnd_RMI src2, 4178 Bool signed_comparison) 4179 { 4180 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4181 4182 vassert(size == 4 || size == 8); 4183 4184 insn->tag = S390_INSN_COMPARE; 4185 insn->size = size; 4186 insn->variant.compare.src1 = src1; 4187 insn->variant.compare.src2 = src2; 4188 insn->variant.compare.signed_comparison = signed_comparison; 4189 4190 return insn; 4191 } 4192 4193 4194 s390_insn * 4195 s390_insn_branch(IRJumpKind kind, s390_cc_t cond, s390_opnd_RMI dst) 4196 { 4197 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4198 4199 insn->tag = S390_INSN_BRANCH; 4200 insn->size = 0; /* does not matter */ 4201 insn->variant.branch.kind = kind; 4202 insn->variant.branch.dst = dst; 4203 insn->variant.branch.cond = cond; 4204 4205 return insn; 4206 } 4207 4208 4209 s390_insn * 4210 s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args, 4211 HChar *name) 4212 { 4213 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4214 4215 insn->tag = S390_INSN_HELPER_CALL; 4216 insn->size = 0; /* does not matter */ 4217 insn->variant.helper_call.cond = cond; 4218 insn->variant.helper_call.target = target; 4219 insn->variant.helper_call.num_args = num_args; 4220 insn->variant.helper_call.name = name; 4221 4222 return insn; 4223 } 4224 4225 4226 s390_insn * 4227 s390_insn_bfp_triop(UChar size, s390_bfp_triop_t tag, HReg dst, HReg op2, 4228 HReg op3, s390_round_t rounding_mode) 4229 { 4230 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4231 4232 insn->tag = S390_INSN_BFP_TRIOP; 4233 insn->size = size; 4234 insn->variant.bfp_triop.tag = tag; 4235 insn->variant.bfp_triop.dst = dst; 4236 insn->variant.bfp_triop.op2 = op2; 4237 insn->variant.bfp_triop.op3 = op3; 4238 insn->variant.bfp_triop.rounding_mode = rounding_mode; 4239 4240 return insn; 4241 } 4242 4243 4244 s390_insn * 4245 s390_insn_bfp_binop(UChar size, s390_bfp_binop_t tag, HReg dst, HReg op2, 4246 s390_round_t rounding_mode) 4247 { 4248 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4249 4250 insn->tag = S390_INSN_BFP_BINOP; 4251 insn->size = size; 4252 insn->variant.bfp_binop.tag = tag; 4253 insn->variant.bfp_binop.dst = dst; 4254 insn->variant.bfp_binop.op2 = op2; 4255 insn->variant.bfp_binop.rounding_mode = rounding_mode; 4256 4257 return insn; 4258 } 4259 4260 4261 s390_insn * 4262 s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, HReg op, 4263 s390_round_t rounding_mode) 4264 { 4265 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4266 4267 insn->tag = S390_INSN_BFP_UNOP; 4268 insn->size = size; 4269 insn->variant.bfp_unop.tag = tag; 4270 insn->variant.bfp_unop.dst = dst; 4271 insn->variant.bfp_unop.op = op; 4272 insn->variant.bfp_unop.rounding_mode = rounding_mode; 4273 4274 return insn; 4275 } 4276 4277 4278 s390_insn * 4279 s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2) 4280 { 4281 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4282 4283 vassert(size == 4 || size == 8); 4284 4285 insn->tag = S390_INSN_BFP_COMPARE; 4286 insn->size = size; 4287 insn->variant.bfp_compare.dst = dst; 4288 insn->variant.bfp_compare.op1 = op1; 4289 insn->variant.bfp_compare.op2 = op2; 4290 4291 return insn; 4292 } 4293 4294 4295 s390_insn * 4296 s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t tag, HReg dst_hi, 4297 HReg dst_lo, HReg op2_hi, HReg op2_lo, 4298 s390_round_t rounding_mode) 4299 { 4300 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4301 4302 insn->tag = S390_INSN_BFP128_BINOP; 4303 insn->size = size; 4304 insn->variant.bfp128_binop.tag = tag; 4305 insn->variant.bfp128_binop.dst_hi = dst_hi; 4306 insn->variant.bfp128_binop.dst_lo = dst_lo; 4307 insn->variant.bfp128_binop.op2_hi = op2_hi; 4308 insn->variant.bfp128_binop.op2_lo = op2_lo; 4309 insn->variant.bfp128_binop.rounding_mode = rounding_mode; 4310 4311 return insn; 4312 } 4313 4314 4315 s390_insn * 4316 s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t tag, HReg dst_hi, 4317 HReg dst_lo, HReg op_hi, HReg op_lo, 4318 s390_round_t rounding_mode) 4319 { 4320 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4321 4322 insn->tag = S390_INSN_BFP128_UNOP; 4323 insn->size = size; 4324 insn->variant.bfp128_unop.tag = tag; 4325 insn->variant.bfp128_unop.dst_hi = dst_hi; 4326 insn->variant.bfp128_unop.dst_lo = dst_lo; 4327 insn->variant.bfp128_unop.op_hi = op_hi; 4328 insn->variant.bfp128_unop.op_lo = op_lo; 4329 insn->variant.bfp128_unop.rounding_mode = rounding_mode; 4330 4331 return insn; 4332 } 4333 4334 4335 s390_insn * 4336 s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, HReg op1_lo, 4337 HReg op2_hi, HReg op2_lo) 4338 { 4339 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4340 4341 insn->tag = S390_INSN_BFP128_COMPARE; 4342 insn->size = size; 4343 insn->variant.bfp128_compare.dst = dst; 4344 insn->variant.bfp128_compare.op1_hi = op1_hi; 4345 insn->variant.bfp128_compare.op1_lo = op1_lo; 4346 insn->variant.bfp128_compare.op2_hi = op2_hi; 4347 insn->variant.bfp128_compare.op2_lo = op2_lo; 4348 4349 return insn; 4350 } 4351 4352 4353 s390_insn * 4354 s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t tag, HReg dst_hi, 4355 HReg dst_lo, HReg op) 4356 { 4357 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4358 4359 insn->tag = S390_INSN_BFP128_CONVERT_TO; 4360 insn->size = size; 4361 insn->variant.bfp128_unop.tag = tag; 4362 insn->variant.bfp128_unop.dst_hi = dst_hi; 4363 insn->variant.bfp128_unop.dst_lo = dst_lo; 4364 insn->variant.bfp128_unop.op_hi = op; 4365 insn->variant.bfp128_unop.op_lo = INVALID_HREG; /* unused */ 4366 insn->variant.bfp128_unop.rounding_mode = S390_ROUND_NEAREST_EVEN; /* unused */ 4367 4368 return insn; 4369 } 4370 4371 4372 s390_insn * 4373 s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t tag, HReg dst, 4374 HReg op_hi, HReg op_lo, 4375 s390_round_t rounding_mode) 4376 { 4377 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4378 4379 insn->tag = S390_INSN_BFP128_CONVERT_FROM; 4380 insn->size = size; 4381 insn->variant.bfp128_unop.tag = tag; 4382 insn->variant.bfp128_unop.dst_hi = dst; 4383 insn->variant.bfp128_unop.dst_lo = INVALID_HREG; /* unused */ 4384 insn->variant.bfp128_unop.op_hi = op_hi; 4385 insn->variant.bfp128_unop.op_lo = op_lo; 4386 insn->variant.bfp128_unop.rounding_mode = rounding_mode; 4387 4388 return insn; 4389 } 4390 4391 4392 s390_insn * 4393 s390_insn_mfence(void) 4394 { 4395 s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn)); 4396 4397 insn->tag = S390_INSN_MFENCE; 4398 insn->size = 0; /* not needed */ 4399 4400 return insn; 4401 } 4402 4403 4404 /*---------------------------------------------------------------*/ 4405 /*--- Debug print ---*/ 4406 /*---------------------------------------------------------------*/ 4407 4408 static const HChar * 4409 s390_cc_as_string(s390_cc_t cc) 4410 { 4411 switch (cc) { 4412 case S390_CC_NEVER: return "never"; 4413 case S390_CC_OVFL: return "overflow"; 4414 case S390_CC_H: return "greater than"; /* A > B ; high */ 4415 case S390_CC_NLE: return "not low or equal"; 4416 case S390_CC_L: return "less than"; /* A < B ; low */ 4417 case S390_CC_NHE: return "not high or equal"; 4418 case S390_CC_LH: return "low or high"; 4419 case S390_CC_NE: return "not equal"; /* A != B ; not zero */ 4420 case S390_CC_E: return "equal"; /* A == B ; zero */ 4421 case S390_CC_NLH: return "not low or high"; 4422 case S390_CC_HE: return "greater or equal"; /* A >= B ; high or equal*/ 4423 case S390_CC_NL: return "not low"; /* not low */ 4424 case S390_CC_LE: return "less or equal"; /* A <= B ; low or equal */ 4425 case S390_CC_NH: return "not high"; 4426 case S390_CC_NO: return "not overflow"; 4427 case S390_CC_ALWAYS: return "always"; 4428 default: 4429 vpanic("s390_cc_as_string"); 4430 } 4431 } 4432 4433 4434 /* Helper function for writing out a V insn */ 4435 static void 4436 s390_sprintf(HChar *buf, HChar *fmt, ...) 4437 { 4438 HChar *p; 4439 ULong value; 4440 va_list args; 4441 va_start(args, fmt); 4442 4443 p = buf; 4444 for ( ; *fmt; ++fmt) { 4445 Int c = *fmt; 4446 4447 if (c != '%') { 4448 *p++ = c; 4449 continue; 4450 } 4451 4452 c = *++fmt; /* next char */ 4453 switch (c) { 4454 case '%': 4455 *p++ = c; /* %% */ 4456 continue; 4457 4458 case 's': /* %s */ 4459 p += vex_sprintf(p, "%s", va_arg(args, HChar *)); 4460 continue; 4461 4462 case 'M': /* %M = mnemonic */ 4463 p += vex_sprintf(p, "%-8s", va_arg(args, HChar *)); 4464 continue; 4465 4466 case 'R': /* %R = register */ 4467 p += vex_sprintf(p, "%s", s390_hreg_as_string(va_arg(args, HReg))); 4468 continue; 4469 4470 case 'A': /* %A = amode */ 4471 p += vex_sprintf(p, "%s", 4472 s390_amode_as_string(va_arg(args, s390_amode *))); 4473 continue; 4474 4475 case 'C': /* %C = condition code */ 4476 p += vex_sprintf(p, "%s", s390_cc_as_string(va_arg(args, s390_cc_t))); 4477 continue; 4478 4479 case 'L': { /* %L = argument list in helper call*/ 4480 UInt i, num_args; 4481 4482 num_args = va_arg(args, UInt); 4483 4484 for (i = 0; i < num_args; ++i) { 4485 if (i != 0) p += vex_sprintf(p, ", "); 4486 p += vex_sprintf(p, "r%d", s390_gprno_from_arg_index(i)); 4487 } 4488 continue; 4489 } 4490 4491 case 'O': { /* %O = RMI operand */ 4492 s390_opnd_RMI *op = va_arg(args, s390_opnd_RMI *); 4493 4494 switch (op->tag) { 4495 case S390_OPND_REG: 4496 p += vex_sprintf(p, "%s", s390_hreg_as_string(op->variant.reg)); 4497 continue; 4498 4499 case S390_OPND_AMODE: 4500 p += vex_sprintf(p, "%s", s390_amode_as_string(op->variant.am)); 4501 continue; 4502 4503 case S390_OPND_IMMEDIATE: 4504 value = op->variant.imm; 4505 goto print_value; 4506 4507 default: 4508 goto fail; 4509 } 4510 } 4511 4512 case 'I': /* %I = immediate value */ 4513 value = va_arg(args, ULong); 4514 goto print_value; 4515 4516 print_value: 4517 if ((Long)value < 0) 4518 p += vex_sprintf(p, "%lld", (Long)value); 4519 else if (value < 100) 4520 p += vex_sprintf(p, "%llu", value); 4521 else 4522 p += vex_sprintf(p, "0x%llx", value); 4523 continue; 4524 4525 default: 4526 goto fail; 4527 } 4528 } 4529 *p = '\0'; 4530 va_end(args); 4531 4532 return; 4533 4534 fail: vpanic("s390_printf"); 4535 } 4536 4537 4538 /* Decompile the given insn into a static buffer and return it */ 4539 const HChar * 4540 s390_insn_as_string(const s390_insn *insn) 4541 { 4542 static HChar buf[300]; 4543 const HChar *op; 4544 HChar *p; 4545 4546 buf[0] = '\0'; 4547 4548 switch (insn->tag) { 4549 case S390_INSN_LOAD: 4550 s390_sprintf(buf, "%M %R,%A", "v-load", insn->variant.load.dst, 4551 insn->variant.load.src); 4552 break; 4553 4554 case S390_INSN_STORE: 4555 s390_sprintf(buf, "%M %R,%A", "v-store", insn->variant.store.src, 4556 insn->variant.store.dst); 4557 break; 4558 4559 case S390_INSN_MOVE: 4560 s390_sprintf(buf, "%M %R,%R", "v-move", insn->variant.move.dst, 4561 insn->variant.move.src); 4562 break; 4563 4564 case S390_INSN_COND_MOVE: 4565 s390_sprintf(buf, "%M if (%C) %R,%O", "v-move", 4566 insn->variant.cond_move.cond, insn->variant.cond_move.dst, 4567 &insn->variant.cond_move.src); 4568 break; 4569 4570 case S390_INSN_LOAD_IMMEDIATE: 4571 s390_sprintf(buf, "%M %R,%I", "v-loadi", insn->variant.load_immediate.dst, 4572 insn->variant.load_immediate.value); 4573 break; 4574 4575 case S390_INSN_ALU: 4576 switch (insn->variant.alu.tag) { 4577 case S390_ALU_ADD: op = "v-add"; break; 4578 case S390_ALU_SUB: op = "v-sub"; break; 4579 case S390_ALU_MUL: op = "v-mul"; break; 4580 case S390_ALU_AND: op = "v-and"; break; 4581 case S390_ALU_OR: op = "v-or"; break; 4582 case S390_ALU_XOR: op = "v-xor"; break; 4583 case S390_ALU_LSH: op = "v-lsh"; break; 4584 case S390_ALU_RSH: op = "v-rsh"; break; 4585 case S390_ALU_RSHA: op = "v-rsha"; break; 4586 default: goto fail; 4587 } 4588 s390_sprintf(buf, "%M %R,%R,%O", op, insn->variant.alu.dst, 4589 insn->variant.alu.dst /* op1 same as dst */, 4590 &insn->variant.alu.op2); 4591 break; 4592 4593 case S390_INSN_MUL: 4594 if (insn->variant.mul.signed_multiply) { 4595 op = "v-muls"; 4596 } else { 4597 op = "v-mulu"; 4598 } 4599 s390_sprintf(buf, "%M %R,%O", op, insn->variant.mul.dst_hi, 4600 &insn->variant.mul.op2); 4601 break; 4602 4603 case S390_INSN_DIV: 4604 if (insn->variant.div.signed_divide) { 4605 op = "v-divs"; 4606 } else { 4607 op = "v-divu"; 4608 } 4609 s390_sprintf(buf, "%M %R,%O", op, insn->variant.div.op1_hi, 4610 &insn->variant.div.op2); 4611 break; 4612 4613 case S390_INSN_DIVS: 4614 s390_sprintf(buf, "%M %R,%O", "v-divsi", insn->variant.divs.op1, 4615 &insn->variant.divs.op2); 4616 break; 4617 4618 case S390_INSN_CLZ: 4619 s390_sprintf(buf, "%M %R,%O", "v-clz", insn->variant.clz.num_bits, 4620 &insn->variant.clz.src); 4621 break; 4622 4623 case S390_INSN_UNOP: 4624 switch (insn->variant.unop.tag) { 4625 case S390_ZERO_EXTEND_8: 4626 case S390_ZERO_EXTEND_16: 4627 case S390_ZERO_EXTEND_32: 4628 op = "v-zerox"; 4629 break; 4630 4631 case S390_SIGN_EXTEND_8: 4632 case S390_SIGN_EXTEND_16: 4633 case S390_SIGN_EXTEND_32: 4634 op = "v-signx"; 4635 break; 4636 4637 case S390_NEGATE: 4638 op = "v-neg"; 4639 break; 4640 4641 default: 4642 goto fail; 4643 } 4644 s390_sprintf(buf, "%M %R,%O", op, insn->variant.unop.dst, 4645 &insn->variant.unop.src); 4646 break; 4647 4648 case S390_INSN_TEST: 4649 s390_sprintf(buf, "%M %O", "v-test", &insn->variant.test.src); 4650 break; 4651 4652 case S390_INSN_CC2BOOL: 4653 s390_sprintf(buf, "%M %R,%C", "v-cc2b", insn->variant.cc2bool.dst, 4654 insn->variant.cc2bool.cond); 4655 break; 4656 4657 case S390_INSN_CAS: 4658 s390_sprintf(buf, "%M %R,%A,%R,%R", "v-cas", insn->variant.cas.op1, 4659 insn->variant.cas.op2, insn->variant.cas.op3, 4660 insn->variant.cas.old_mem); 4661 break; 4662 4663 case S390_INSN_COMPARE: 4664 if (insn->variant.compare.signed_comparison) { 4665 op = "v-cmps"; 4666 } else { 4667 op = "v-cmpu"; 4668 } 4669 s390_sprintf(buf, "%M %R,%O", op, insn->variant.compare.src1, 4670 &insn->variant.compare.src2); 4671 break; 4672 4673 case S390_INSN_BRANCH: 4674 switch (insn->variant.branch.kind) { 4675 case Ijk_ClientReq: op = "clientreq"; break; 4676 case Ijk_Sys_syscall: op = "syscall"; break; 4677 case Ijk_Yield: op = "yield"; break; 4678 case Ijk_EmWarn: op = "emwarn"; break; 4679 case Ijk_EmFail: op = "emfail"; break; 4680 case Ijk_MapFail: op = "mapfail"; break; 4681 case Ijk_NoDecode: op = "nodecode"; break; 4682 case Ijk_TInval: op = "tinval"; break; 4683 case Ijk_NoRedir: op = "noredir"; break; 4684 case Ijk_SigTRAP: op = "sigtrap"; break; 4685 case Ijk_Boring: op = "goto"; break; 4686 case Ijk_Call: op = "call"; break; 4687 case Ijk_Ret: op = "return"; break; 4688 default: 4689 goto fail; 4690 } 4691 s390_sprintf(buf, "if (%C) %s %O", insn->variant.branch.cond, op, 4692 &insn->variant.branch.dst); 4693 break; 4694 4695 case S390_INSN_HELPER_CALL: { 4696 4697 if (insn->variant.helper_call.cond != S390_CC_ALWAYS) { 4698 s390_sprintf(buf, "%M if (%C) %s{%I}(%L)", "v-call", 4699 insn->variant.helper_call.cond, 4700 insn->variant.helper_call.name, 4701 insn->variant.helper_call.target, 4702 insn->variant.helper_call.num_args); 4703 } else { 4704 s390_sprintf(buf, "%M %s{%I}(%L)", "v-call", 4705 insn->variant.helper_call.name, 4706 insn->variant.helper_call.target, 4707 insn->variant.helper_call.num_args); 4708 } 4709 break; 4710 } 4711 4712 case S390_INSN_BFP_TRIOP: 4713 switch (insn->variant.bfp_triop.tag) { 4714 case S390_BFP_MADD: op = "v-fmadd"; break; 4715 case S390_BFP_MSUB: op = "v-fmsub"; break; 4716 default: goto fail; 4717 } 4718 s390_sprintf(buf, "%M %R,%R,%R,%R", op, insn->variant.bfp_triop.dst, 4719 insn->variant.bfp_triop.dst /* op1 same as dst */, 4720 insn->variant.bfp_triop.op2, insn->variant.bfp_triop.op3); 4721 break; 4722 4723 case S390_INSN_BFP_BINOP: 4724 switch (insn->variant.bfp_binop.tag) { 4725 case S390_BFP_ADD: op = "v-fadd"; break; 4726 case S390_BFP_SUB: op = "v-fsub"; break; 4727 case S390_BFP_MUL: op = "v-fmul"; break; 4728 case S390_BFP_DIV: op = "v-fdiv"; break; 4729 default: goto fail; 4730 } 4731 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp_binop.dst, 4732 insn->variant.bfp_binop.dst /* op1 same as dst */, 4733 insn->variant.bfp_binop.op2); 4734 break; 4735 4736 case S390_INSN_BFP_COMPARE: 4737 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp_compare.dst, 4738 insn->variant.bfp_compare.op1, insn->variant.bfp_compare.op2); 4739 break; 4740 4741 case S390_INSN_BFP_UNOP: 4742 switch (insn->variant.bfp_unop.tag) { 4743 case S390_BFP_ABS: op = "v-fabs"; break; 4744 case S390_BFP_NABS: op = "v-fnabs"; break; 4745 case S390_BFP_NEG: op = "v-fneg"; break; 4746 case S390_BFP_SQRT: op = "v-fsqrt"; break; 4747 case S390_BFP_I32_TO_F32: 4748 case S390_BFP_I32_TO_F64: 4749 case S390_BFP_I32_TO_F128: 4750 case S390_BFP_I64_TO_F32: 4751 case S390_BFP_I64_TO_F64: 4752 case S390_BFP_I64_TO_F128: op = "v-i2f"; break; 4753 case S390_BFP_F32_TO_I32: 4754 case S390_BFP_F32_TO_I64: 4755 case S390_BFP_F64_TO_I32: 4756 case S390_BFP_F64_TO_I64: 4757 case S390_BFP_F128_TO_I32: 4758 case S390_BFP_F128_TO_I64: op = "v-f2i"; break; 4759 case S390_BFP_F32_TO_F64: 4760 case S390_BFP_F32_TO_F128: 4761 case S390_BFP_F64_TO_F32: 4762 case S390_BFP_F64_TO_F128: 4763 case S390_BFP_F128_TO_F32: 4764 case S390_BFP_F128_TO_F64: op = "v-f2f"; break; 4765 default: goto fail; 4766 } 4767 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp_unop.dst, 4768 insn->variant.bfp_unop.op); 4769 break; 4770 4771 case S390_INSN_BFP128_BINOP: 4772 switch (insn->variant.bfp128_binop.tag) { 4773 case S390_BFP_ADD: op = "v-fadd"; break; 4774 case S390_BFP_SUB: op = "v-fsub"; break; 4775 case S390_BFP_MUL: op = "v-fmul"; break; 4776 case S390_BFP_DIV: op = "v-fdiv"; break; 4777 default: goto fail; 4778 } 4779 /* Only write the register that identifies the register pair */ 4780 s390_sprintf(buf, "%M %R,%R,%R", op, insn->variant.bfp128_binop.dst_hi, 4781 insn->variant.bfp128_binop.dst_hi /* op1 same as dst */, 4782 insn->variant.bfp128_binop.op2_hi); 4783 break; 4784 4785 case S390_INSN_BFP128_COMPARE: 4786 /* Only write the register that identifies the register pair */ 4787 s390_sprintf(buf, "%M %R,%R,%R", "v-fcmp", insn->variant.bfp128_compare.dst, 4788 insn->variant.bfp128_compare.op1_hi, 4789 insn->variant.bfp128_compare.op2_hi); 4790 break; 4791 4792 case S390_INSN_BFP128_UNOP: 4793 case S390_INSN_BFP128_CONVERT_TO: 4794 case S390_INSN_BFP128_CONVERT_FROM: 4795 switch (insn->variant.bfp128_unop.tag) { 4796 case S390_BFP_ABS: op = "v-fabs"; break; 4797 case S390_BFP_NABS: op = "v-fnabs"; break; 4798 case S390_BFP_NEG: op = "v-fneg"; break; 4799 case S390_BFP_SQRT: op = "v-fsqrt"; break; 4800 case S390_BFP_I32_TO_F128: 4801 case S390_BFP_I64_TO_F128: op = "v-i2f"; break; 4802 case S390_BFP_F128_TO_I32: 4803 case S390_BFP_F128_TO_I64: op = "v-f2i"; break; 4804 case S390_BFP_F32_TO_F128: 4805 case S390_BFP_F64_TO_F128: 4806 case S390_BFP_F128_TO_F32: 4807 case S390_BFP_F128_TO_F64: op = "v-f2f"; break; 4808 default: goto fail; 4809 } 4810 /* Only write the register that identifies the register pair */ 4811 s390_sprintf(buf, "%M %R,%R", op, insn->variant.bfp128_unop.dst_hi, 4812 insn->variant.bfp128_unop.op_hi); 4813 break; 4814 4815 case S390_INSN_MFENCE: 4816 s390_sprintf(buf, "%M", "v-mfence"); 4817 return buf; /* avoid printing "size = ..." which is meaningless */ 4818 4819 default: goto fail; 4820 } 4821 4822 /* Write out how many bytes are involved in the operation */ 4823 4824 { 4825 UInt len, i; 4826 4827 for (p = buf; *p; ++p) 4828 continue; 4829 4830 len = p - buf; 4831 4832 if (len < 32) { 4833 for (i = len; i < 32; ++i) 4834 p += vex_sprintf(p, " "); 4835 } else { 4836 p += vex_sprintf(p, "\t"); 4837 } 4838 } 4839 4840 /* Special cases first */ 4841 switch (insn->tag) { 4842 case S390_INSN_UNOP: 4843 switch (insn->variant.unop.tag) { 4844 case S390_SIGN_EXTEND_8: 4845 case S390_ZERO_EXTEND_8: p += vex_sprintf(p, "1 -> "); goto common; 4846 case S390_SIGN_EXTEND_16: 4847 case S390_ZERO_EXTEND_16: p += vex_sprintf(p, "2 -> "); goto common; 4848 case S390_SIGN_EXTEND_32: 4849 case S390_ZERO_EXTEND_32: p += vex_sprintf(p, "4 -> "); goto common; 4850 default: 4851 goto common; 4852 } 4853 4854 case S390_INSN_BFP_UNOP: 4855 switch (insn->variant.bfp_unop.tag) { 4856 case S390_BFP_I32_TO_F32: 4857 case S390_BFP_I32_TO_F64: 4858 case S390_BFP_I32_TO_F128: 4859 case S390_BFP_F32_TO_I32: 4860 case S390_BFP_F32_TO_I64: 4861 case S390_BFP_F32_TO_F64: 4862 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common; 4863 case S390_BFP_I64_TO_F32: 4864 case S390_BFP_I64_TO_F64: 4865 case S390_BFP_I64_TO_F128: 4866 case S390_BFP_F64_TO_I32: 4867 case S390_BFP_F64_TO_I64: 4868 case S390_BFP_F64_TO_F32: 4869 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common; 4870 case S390_BFP_F128_TO_I32: 4871 case S390_BFP_F128_TO_I64: 4872 case S390_BFP_F128_TO_F32: 4873 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common; 4874 default: 4875 goto common; 4876 } 4877 4878 case S390_INSN_BFP128_UNOP: 4879 case S390_INSN_BFP128_CONVERT_TO: 4880 case S390_INSN_BFP128_CONVERT_FROM: 4881 switch (insn->variant.bfp128_unop.tag) { 4882 case S390_BFP_I32_TO_F128: 4883 case S390_BFP_F32_TO_F128: p += vex_sprintf(p, "4 -> "); goto common; 4884 case S390_BFP_I64_TO_F128: 4885 case S390_BFP_F64_TO_F128: p += vex_sprintf(p, "8 -> "); goto common; 4886 case S390_BFP_F128_TO_I32: 4887 case S390_BFP_F128_TO_I64: 4888 case S390_BFP_F128_TO_F32: 4889 case S390_BFP_F128_TO_F64: p += vex_sprintf(p, "16 -> "); goto common; 4890 default: 4891 goto common; 4892 } 4893 4894 default: 4895 goto common; 4896 } 4897 4898 /* Common case */ 4899 common: 4900 vex_sprintf(p, "%u bytes", (UInt)insn->size); 4901 4902 return buf; 4903 4904 fail: vpanic("s390_insn_as_string"); 4905 } 4906 4907 4908 4909 /* Load NUM bytes from memory into register REG using addressing mode AM. */ 4910 static UChar * 4911 s390_emit_load_mem(UChar *p, UInt num, UChar reg, const s390_amode *am) 4912 { 4913 UInt b = hregNumber(am->b); 4914 UInt x = hregNumber(am->x); /* 0 for B12 and B20 */ 4915 UInt d = am->d; 4916 4917 switch (am->tag) { 4918 case S390_AMODE_B12: 4919 case S390_AMODE_BX12: 4920 switch (num) { 4921 case 1: return s390_emit_IC(p, reg, x, b, d); 4922 case 2: return s390_emit_LH(p, reg, x, b, d); 4923 case 4: return s390_emit_L(p, reg, x, b, d); 4924 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d)); 4925 default: goto fail; 4926 } 4927 break; 4928 4929 case S390_AMODE_B20: 4930 case S390_AMODE_BX20: 4931 switch (num) { 4932 case 1: return s390_emit_ICY(p, reg, x, b, DISP20(d)); 4933 case 2: return s390_emit_LHY(p, reg, x, b, DISP20(d)); 4934 case 4: return s390_emit_LY(p, reg, x, b, DISP20(d)); 4935 case 8: return s390_emit_LG(p, reg, x, b, DISP20(d)); 4936 default: goto fail; 4937 } 4938 break; 4939 4940 default: goto fail; 4941 } 4942 4943 fail: 4944 vpanic("s390_emit_load_mem"); 4945 } 4946 4947 4948 /* Load condition code into register REG */ 4949 static UChar * 4950 s390_emit_load_cc(UChar *p, UChar reg) 4951 { 4952 p = s390_emit_LGHI(p, reg, 0); /* Clear out, cc not affected */ 4953 p = s390_emit_IPM(p, reg, reg); 4954 /* Shift 28 bits to the right --> [0,1,2,3] */ 4955 return s390_emit_SRL(p, reg, 0, 28); /* REG = cc */ 4956 } 4957 4958 4959 /*---------------------------------------------------------------*/ 4960 /*--- Code generation ---*/ 4961 /*---------------------------------------------------------------*/ 4962 4963 /* Do not load more bytes than requested. */ 4964 static UChar * 4965 s390_insn_load_emit(UChar *buf, const s390_insn *insn) 4966 { 4967 UInt r, x, b, d; 4968 const s390_amode *src; 4969 4970 src = insn->variant.load.src; 4971 4972 r = hregNumber(insn->variant.load.dst); 4973 4974 if (hregClass(insn->variant.load.dst) == HRcFlt64) { 4975 b = hregNumber(src->b); 4976 x = hregNumber(src->x); /* 0 for B12 and B20 */ 4977 d = src->d; 4978 4979 switch (insn->size) { 4980 4981 case 4: 4982 switch (src->tag) { 4983 case S390_AMODE_B12: 4984 case S390_AMODE_BX12: 4985 return s390_emit_LE(buf, r, x, b, d); 4986 4987 case S390_AMODE_B20: 4988 case S390_AMODE_BX20: 4989 return s390_emit_LEY(buf, r, x, b, DISP20(d)); 4990 } 4991 break; 4992 4993 case 8: 4994 switch (src->tag) { 4995 case S390_AMODE_B12: 4996 case S390_AMODE_BX12: 4997 return s390_emit_LD(buf, r, x, b, d); 4998 4999 case S390_AMODE_B20: 5000 case S390_AMODE_BX20: 5001 return s390_emit_LDY(buf, r, x, b, DISP20(d)); 5002 } 5003 break; 5004 } 5005 vpanic("s390_insn_load_emit"); 5006 } 5007 5008 /* Integer stuff */ 5009 return s390_emit_load_mem(buf, insn->size, r, src); 5010 } 5011 5012 5013 static UChar * 5014 s390_insn_store_emit(UChar *buf, const s390_insn *insn) 5015 { 5016 UInt r, x, b, d; 5017 const s390_amode *dst; 5018 5019 dst = insn->variant.store.dst; 5020 5021 r = hregNumber(insn->variant.store.src); 5022 b = hregNumber(dst->b); 5023 x = hregNumber(dst->x); /* 0 for B12 and B20 */ 5024 d = dst->d; 5025 5026 if (hregClass(insn->variant.store.src) == HRcFlt64) { 5027 switch (insn->size) { 5028 5029 case 4: 5030 switch (dst->tag) { 5031 case S390_AMODE_B12: 5032 case S390_AMODE_BX12: 5033 return s390_emit_STE(buf, r, x, b, d); 5034 5035 case S390_AMODE_B20: 5036 case S390_AMODE_BX20: 5037 return s390_emit_STEY(buf, r, x, b, DISP20(d)); 5038 } 5039 break; 5040 5041 case 8: 5042 switch (dst->tag) { 5043 case S390_AMODE_B12: 5044 case S390_AMODE_BX12: 5045 return s390_emit_STD(buf, r, x, b, d); 5046 5047 case S390_AMODE_B20: 5048 case S390_AMODE_BX20: 5049 return s390_emit_STDY(buf, r, x, b, DISP20(d)); 5050 } 5051 break; 5052 } 5053 vpanic("s390_insn_store_emit"); 5054 } 5055 5056 /* Integer stuff */ 5057 switch (insn->size) { 5058 case 1: 5059 switch (dst->tag) { 5060 case S390_AMODE_B12: 5061 case S390_AMODE_BX12: 5062 return s390_emit_STC(buf, r, x, b, d); 5063 5064 case S390_AMODE_B20: 5065 case S390_AMODE_BX20: 5066 return s390_emit_STCY(buf, r, x, b, DISP20(d)); 5067 } 5068 break; 5069 5070 case 2: 5071 switch (dst->tag) { 5072 case S390_AMODE_B12: 5073 case S390_AMODE_BX12: 5074 return s390_emit_STH(buf, r, x, b, d); 5075 5076 case S390_AMODE_B20: 5077 case S390_AMODE_BX20: 5078 return s390_emit_STHY(buf, r, x, b, DISP20(d)); 5079 } 5080 break; 5081 5082 case 4: 5083 switch (dst->tag) { 5084 case S390_AMODE_B12: 5085 case S390_AMODE_BX12: 5086 return s390_emit_ST(buf, r, x, b, d); 5087 5088 case S390_AMODE_B20: 5089 case S390_AMODE_BX20: 5090 return s390_emit_STY(buf, r, x, b, DISP20(d)); 5091 } 5092 break; 5093 5094 case 8: 5095 return s390_emit_STG(buf, r, x, b, DISP20(d)); 5096 5097 default: 5098 break; 5099 } 5100 5101 vpanic("s390_insn_store_emit"); 5102 } 5103 5104 5105 static UChar * 5106 s390_insn_move_emit(UChar *buf, const s390_insn *insn) 5107 { 5108 UInt dst, src; 5109 HRegClass dst_class, src_class; 5110 5111 dst = hregNumber(insn->variant.move.dst); 5112 src = hregNumber(insn->variant.move.src); 5113 5114 dst_class = hregClass(insn->variant.move.dst); 5115 src_class = hregClass(insn->variant.move.src); 5116 5117 if (dst_class == src_class) { 5118 if (dst_class == HRcInt64) 5119 return s390_emit_LGR(buf, dst, src); 5120 if (dst_class == HRcFlt64) 5121 return s390_emit_LDR(buf, dst, src); 5122 } else { 5123 if (dst_class == HRcFlt64 && src_class == HRcInt64) 5124 return s390_emit_LDGRw(buf, dst, src); 5125 if (dst_class == HRcInt64 && src_class == HRcFlt64) 5126 return s390_emit_LGDRw(buf, dst, src); 5127 /* A move between floating point registers and general purpose 5128 registers of different size should never occur and indicates 5129 an error elsewhere. */ 5130 } 5131 5132 vpanic("s390_insn_move_emit"); 5133 } 5134 5135 5136 static UChar * 5137 s390_insn_load_immediate_emit(UChar *buf, const s390_insn *insn) 5138 { 5139 UInt r; 5140 ULong value = insn->variant.load_immediate.value; 5141 5142 r = hregNumber(insn->variant.load_immediate.dst); 5143 5144 if (hregClass(insn->variant.load_immediate.dst) == HRcFlt64) { 5145 vassert(value == 0); 5146 switch (insn->size) { 5147 case 4: return s390_emit_LZER(buf, r, value); 5148 case 8: return s390_emit_LZDR(buf, r, value); 5149 } 5150 vpanic("s390_insn_load_immediate_emit"); 5151 } 5152 5153 switch (insn->size) { 5154 case 1: 5155 case 2: 5156 /* Load the immediate values as a 4 byte value. That does not hurt as 5157 those extra bytes will not be looked at. Fall through .... */ 5158 case 4: 5159 return s390_emit_load_32imm(buf, r, value); 5160 5161 case 8: 5162 return s390_emit_load_64imm(buf, r, value); 5163 } 5164 5165 vpanic("s390_insn_load_immediate_emit"); 5166 } 5167 5168 5169 /* There is no easy way to do ALU operations on 1-byte or 2-byte operands. 5170 So we simply perform a 4-byte operation. Doing so uses possibly undefined 5171 bits and produces an undefined result in those extra bit positions. But 5172 upstream does not look at those positions, so this is OK. */ 5173 static UChar * 5174 s390_insn_alu_emit(UChar *buf, const s390_insn *insn) 5175 { 5176 s390_opnd_RMI op2; 5177 UInt dst; 5178 5179 dst = hregNumber(insn->variant.alu.dst); 5180 op2 = insn->variant.alu.op2; 5181 5182 /* Second operand is in a register */ 5183 if (op2.tag == S390_OPND_REG) { 5184 UInt r2 = hregNumber(op2.variant.reg); 5185 5186 switch (insn->size) { 5187 case 1: 5188 case 2: 5189 case 4: 5190 switch (insn->variant.alu.tag) { 5191 case S390_ALU_ADD: return s390_emit_AR(buf, dst, r2); 5192 case S390_ALU_SUB: return s390_emit_SR(buf, dst, r2); 5193 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, r2); 5194 case S390_ALU_AND: return s390_emit_NR(buf, dst, r2); 5195 case S390_ALU_OR: return s390_emit_OR(buf, dst, r2); 5196 case S390_ALU_XOR: return s390_emit_XR(buf, dst, r2); 5197 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, r2, 0); 5198 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, r2, 0); 5199 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, r2, 0); 5200 } 5201 goto fail; 5202 5203 case 8: 5204 switch (insn->variant.alu.tag) { 5205 case S390_ALU_ADD: return s390_emit_AGR(buf, dst, r2); 5206 case S390_ALU_SUB: return s390_emit_SGR(buf, dst, r2); 5207 case S390_ALU_MUL: return s390_emit_MSGR(buf, dst, r2); 5208 case S390_ALU_AND: return s390_emit_NGR(buf, dst, r2); 5209 case S390_ALU_OR: return s390_emit_OGR(buf, dst, r2); 5210 case S390_ALU_XOR: return s390_emit_XGR(buf, dst, r2); 5211 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, r2, DISP20(0)); 5212 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, r2, DISP20(0)); 5213 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, r2, DISP20(0)); 5214 } 5215 goto fail; 5216 } 5217 goto fail; 5218 } 5219 5220 /* 2nd operand is in memory */ 5221 if (op2.tag == S390_OPND_AMODE) { 5222 UInt b, x, d; 5223 const s390_amode *src = op2.variant.am; 5224 5225 b = hregNumber(src->b); 5226 x = hregNumber(src->x); /* 0 for B12 and B20 */ 5227 d = src->d; 5228 5229 /* Shift operands are special here as there are no opcodes that 5230 allow a memory operand. So we first load the 2nd operand into 5231 some register. R0 is used to save restore the contents of the 5232 chosen register.. */ 5233 5234 if (insn->variant.alu.tag == S390_ALU_LSH || 5235 insn->variant.alu.tag == S390_ALU_RSH || 5236 insn->variant.alu.tag == S390_ALU_RSHA) { 5237 UInt b2; 5238 5239 /* Choose a register (other than DST or R0) into which to stick the 5240 shift amount. The following works because r15 is reserved and 5241 thusly dst != 15. */ 5242 vassert(dst != 15); /* extra paranoia */ 5243 b2 = (dst + 1) % 16; 5244 5245 buf = s390_emit_LGR(buf, R0, b2); /* save */ 5246 5247 /* Loading SRC to B2 does not modify R0. */ 5248 buf = s390_emit_load_mem(buf, insn->size, b2, src); 5249 5250 if (insn->size == 8) { 5251 switch (insn->variant.alu.tag) { 5252 case S390_ALU_LSH: 5253 buf = s390_emit_SLLG(buf, dst, dst, b2, DISP20(0)); 5254 break; 5255 case S390_ALU_RSH: 5256 buf = s390_emit_SRLG(buf, dst, dst, b2, DISP20(0)); 5257 break; 5258 case S390_ALU_RSHA: 5259 buf = s390_emit_SRAG(buf, dst, dst, b2, DISP20(0)); 5260 break; 5261 default: /* unreachable */ 5262 goto fail; 5263 } 5264 } else { 5265 switch (insn->variant.alu.tag) { 5266 case S390_ALU_LSH: 5267 buf = s390_emit_SLL(buf, dst, b2, 0); 5268 break; 5269 case S390_ALU_RSH: 5270 buf = s390_emit_SRL(buf, dst, b2, 0); 5271 break; 5272 case S390_ALU_RSHA: 5273 buf = s390_emit_SRA(buf, dst, b2, 0); 5274 break; 5275 default: /* unreachable */ 5276 goto fail; 5277 } 5278 } 5279 return s390_emit_LGR(buf, b2, R0); /* restore */ 5280 } 5281 5282 switch (insn->size) { 5283 case 1: 5284 /* Move the byte from memory into scratch register r0 */ 5285 buf = s390_emit_load_mem(buf, 1, R0, src); 5286 5287 switch (insn->variant.alu.tag) { 5288 case S390_ALU_ADD: return s390_emit_AR(buf, dst, R0); 5289 case S390_ALU_SUB: return s390_emit_SR(buf, dst, R0); 5290 case S390_ALU_MUL: return s390_emit_MSR(buf, dst, R0); 5291 case S390_ALU_AND: return s390_emit_NR(buf, dst, R0); 5292 case S390_ALU_OR: return s390_emit_OR(buf, dst, R0); 5293 case S390_ALU_XOR: return s390_emit_XR(buf, dst, R0); 5294 case S390_ALU_LSH: 5295 case S390_ALU_RSH: 5296 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5297 } 5298 goto fail; 5299 5300 case 2: 5301 switch (src->tag) { 5302 case S390_AMODE_B12: 5303 case S390_AMODE_BX12: 5304 switch (insn->variant.alu.tag) { 5305 case S390_ALU_ADD: 5306 return s390_emit_AH(buf, dst, x, b, d); 5307 5308 case S390_ALU_SUB: 5309 return s390_emit_SH(buf, dst, x, b, d); 5310 5311 case S390_ALU_MUL: 5312 return s390_emit_MH(buf, dst, x, b, d); 5313 5314 /* For bitwise operations: Move two bytes from memory into scratch 5315 register r0; then perform operation */ 5316 case S390_ALU_AND: 5317 buf = s390_emit_LH(buf, R0, x, b, d); 5318 return s390_emit_NR(buf, dst, R0); 5319 5320 case S390_ALU_OR: 5321 buf = s390_emit_LH(buf, R0, x, b, d); 5322 return s390_emit_OR(buf, dst, R0); 5323 5324 case S390_ALU_XOR: 5325 buf = s390_emit_LH(buf, R0, x, b, d); 5326 return s390_emit_XR(buf, dst, R0); 5327 5328 case S390_ALU_LSH: 5329 case S390_ALU_RSH: 5330 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5331 } 5332 goto fail; 5333 5334 case S390_AMODE_B20: 5335 case S390_AMODE_BX20: 5336 switch (insn->variant.alu.tag) { 5337 case S390_ALU_ADD: 5338 return s390_emit_AHY(buf, dst, x, b, DISP20(d)); 5339 5340 case S390_ALU_SUB: 5341 return s390_emit_SHY(buf, dst, x, b, DISP20(d)); 5342 5343 case S390_ALU_MUL: 5344 return s390_emit_MHYw(buf, dst, x, b, DISP20(d)); 5345 5346 /* For bitwise operations: Move two bytes from memory into scratch 5347 register r0; then perform operation */ 5348 case S390_ALU_AND: 5349 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 5350 return s390_emit_NR(buf, dst, R0); 5351 5352 case S390_ALU_OR: 5353 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 5354 return s390_emit_OR(buf, dst, R0); 5355 5356 case S390_ALU_XOR: 5357 buf = s390_emit_LHY(buf, R0, x, b, DISP20(d)); 5358 return s390_emit_XR(buf, dst, R0); 5359 5360 case S390_ALU_LSH: 5361 case S390_ALU_RSH: 5362 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5363 } 5364 goto fail; 5365 } 5366 goto fail; 5367 5368 case 4: 5369 switch (src->tag) { 5370 case S390_AMODE_B12: 5371 case S390_AMODE_BX12: 5372 switch (insn->variant.alu.tag) { 5373 case S390_ALU_ADD: return s390_emit_A(buf, dst, x, b, d); 5374 case S390_ALU_SUB: return s390_emit_S(buf, dst, x, b, d); 5375 case S390_ALU_MUL: return s390_emit_MS(buf, dst, x, b, d); 5376 case S390_ALU_AND: return s390_emit_N(buf, dst, x, b, d); 5377 case S390_ALU_OR: return s390_emit_O(buf, dst, x, b, d); 5378 case S390_ALU_XOR: return s390_emit_X(buf, dst, x, b, d); 5379 case S390_ALU_LSH: 5380 case S390_ALU_RSH: 5381 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5382 } 5383 goto fail; 5384 5385 case S390_AMODE_B20: 5386 case S390_AMODE_BX20: 5387 switch (insn->variant.alu.tag) { 5388 case S390_ALU_ADD: return s390_emit_AY(buf, dst, x, b, DISP20(d)); 5389 case S390_ALU_SUB: return s390_emit_SY(buf, dst, x, b, DISP20(d)); 5390 case S390_ALU_MUL: return s390_emit_MSY(buf, dst, x, b, DISP20(d)); 5391 case S390_ALU_AND: return s390_emit_NY(buf, dst, x, b, DISP20(d)); 5392 case S390_ALU_OR: return s390_emit_OY(buf, dst, x, b, DISP20(d)); 5393 case S390_ALU_XOR: return s390_emit_XY(buf, dst, x, b, DISP20(d)); 5394 case S390_ALU_LSH: 5395 case S390_ALU_RSH: 5396 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5397 } 5398 goto fail; 5399 } 5400 goto fail; 5401 5402 case 8: 5403 switch (insn->variant.alu.tag) { 5404 case S390_ALU_ADD: return s390_emit_AG(buf, dst, x, b, DISP20(d)); 5405 case S390_ALU_SUB: return s390_emit_SG(buf, dst, x, b, DISP20(d)); 5406 case S390_ALU_MUL: return s390_emit_MSG(buf, dst, x, b, DISP20(d)); 5407 case S390_ALU_AND: return s390_emit_NG(buf, dst, x, b, DISP20(d)); 5408 case S390_ALU_OR: return s390_emit_OG(buf, dst, x, b, DISP20(d)); 5409 case S390_ALU_XOR: return s390_emit_XG(buf, dst, x, b, DISP20(d)); 5410 case S390_ALU_LSH: 5411 case S390_ALU_RSH: 5412 case S390_ALU_RSHA: ; /* avoid GCC warning */ 5413 } 5414 goto fail; 5415 } 5416 goto fail; 5417 } 5418 5419 /* 2nd operand is an immediate value */ 5420 if (op2.tag == S390_OPND_IMMEDIATE) { 5421 ULong value; 5422 5423 /* No masking of the value is required as it is not sign extended */ 5424 value = op2.variant.imm; 5425 5426 switch (insn->size) { 5427 case 1: 5428 case 2: 5429 /* There is no 1-byte opcode. Do the computation in 5430 2 bytes. The extra byte will be ignored. */ 5431 switch (insn->variant.alu.tag) { 5432 case S390_ALU_ADD: 5433 return s390_emit_AHI(buf, dst, value); 5434 5435 case S390_ALU_SUB: 5436 return s390_emit_SLFIw(buf, dst, value); 5437 5438 case S390_ALU_MUL: 5439 return s390_emit_MHI(buf, dst, value); 5440 5441 case S390_ALU_AND: return s390_emit_NILL(buf, dst, value); 5442 case S390_ALU_OR: return s390_emit_OILL(buf, dst, value); 5443 case S390_ALU_XOR: 5444 /* There is no XILL instruction. Load the immediate value into 5445 R0 and combine with the destination register. */ 5446 buf = s390_emit_LHI(buf, R0, value); 5447 return s390_emit_XR(buf, dst, R0); 5448 5449 case S390_ALU_LSH: 5450 return s390_emit_SLL(buf, dst, 0, value); 5451 5452 case S390_ALU_RSH: 5453 return s390_emit_SRL(buf, dst, 0, value); 5454 5455 case S390_ALU_RSHA: 5456 return s390_emit_SRA(buf, dst, 0, value); 5457 } 5458 goto fail; 5459 5460 case 4: 5461 switch (insn->variant.alu.tag) { 5462 case S390_ALU_ADD: 5463 if (uint_fits_signed_16bit(value)) { 5464 return s390_emit_AHI(buf, dst, value); 5465 } 5466 return s390_emit_AFIw(buf, dst, value); 5467 5468 case S390_ALU_SUB: return s390_emit_SLFIw(buf, dst, value); 5469 case S390_ALU_MUL: return s390_emit_MSFIw(buf, dst, value); 5470 case S390_ALU_AND: return s390_emit_NILFw(buf, dst, value); 5471 case S390_ALU_OR: return s390_emit_OILFw(buf, dst, value); 5472 case S390_ALU_XOR: return s390_emit_XILFw(buf, dst, value); 5473 case S390_ALU_LSH: return s390_emit_SLL(buf, dst, 0, value); 5474 case S390_ALU_RSH: return s390_emit_SRL(buf, dst, 0, value); 5475 case S390_ALU_RSHA: return s390_emit_SRA(buf, dst, 0, value); 5476 } 5477 goto fail; 5478 5479 case 8: 5480 switch (insn->variant.alu.tag) { 5481 case S390_ALU_ADD: 5482 if (ulong_fits_signed_16bit(value)) { 5483 return s390_emit_AGHI(buf, dst, value); 5484 } 5485 if (ulong_fits_signed_32bit(value) && s390_host_has_eimm) { 5486 return s390_emit_AGFI(buf, dst, value); 5487 } 5488 /* Load constant into R0 then add */ 5489 buf = s390_emit_load_64imm(buf, R0, value); 5490 return s390_emit_AGR(buf, dst, R0); 5491 5492 case S390_ALU_SUB: 5493 if (ulong_fits_unsigned_32bit(value)) { 5494 return s390_emit_SLGFIw(buf, dst, value); 5495 } 5496 /* Load value into R0; then subtract from destination reg */ 5497 buf = s390_emit_load_64imm(buf, R0, value); 5498 return s390_emit_SGR(buf, dst, R0); 5499 5500 case S390_ALU_MUL: 5501 if (ulong_fits_signed_32bit(value) && s390_host_has_gie) { 5502 return s390_emit_MSGFI(buf, dst, value); 5503 } 5504 /* Load constant into R0 then add */ 5505 buf = s390_emit_load_64imm(buf, R0, value); 5506 return s390_emit_MSGR(buf, dst, R0); 5507 5508 /* Do it in two steps: upper half [0:31] and lower half [32:63] */ 5509 case S390_ALU_AND: 5510 if (s390_host_has_eimm) { 5511 buf = s390_emit_NIHF(buf, dst, value >> 32); 5512 return s390_emit_NILF(buf, dst, value & 0xFFFFFFFF); 5513 } 5514 /* Load value into R0; then combine with destination reg */ 5515 buf = s390_emit_load_64imm(buf, R0, value); 5516 return s390_emit_NGR(buf, dst, R0); 5517 5518 case S390_ALU_OR: 5519 if (s390_host_has_eimm) { 5520 buf = s390_emit_OIHF(buf, dst, value >> 32); 5521 return s390_emit_OILF(buf, dst, value & 0xFFFFFFFF); 5522 } 5523 /* Load value into R0; then combine with destination reg */ 5524 buf = s390_emit_load_64imm(buf, R0, value); 5525 return s390_emit_OGR(buf, dst, R0); 5526 5527 case S390_ALU_XOR: 5528 if (s390_host_has_eimm) { 5529 buf = s390_emit_XIHF(buf, dst, value >> 32); 5530 return s390_emit_XILF(buf, dst, value & 0xFFFFFFFF); 5531 } 5532 /* Load value into R0; then combine with destination reg */ 5533 buf = s390_emit_load_64imm(buf, R0, value); 5534 return s390_emit_XGR(buf, dst, R0); 5535 5536 /* No special considerations for long displacement here. Only the six 5537 least significant bits of VALUE will be taken; all other bits are 5538 ignored. So the DH2 bits are irrelevant and do not influence the 5539 shift operation, independent of whether long-displacement is available 5540 or not. */ 5541 case S390_ALU_LSH: return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value)); 5542 case S390_ALU_RSH: return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value)); 5543 case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value)); 5544 } 5545 goto fail; 5546 } 5547 goto fail; 5548 } 5549 5550 fail: 5551 vpanic("s390_insn_alu_emit"); 5552 } 5553 5554 5555 static UChar * 5556 s390_widen_emit(UChar *buf, const s390_insn *insn, UInt from_size, 5557 Bool sign_extend) 5558 { 5559 s390_opnd_RMI opnd = insn->variant.unop.src; 5560 5561 switch (opnd.tag) { 5562 case S390_OPND_REG: { 5563 UChar r1 = hregNumber(insn->variant.unop.dst); 5564 UChar r2 = hregNumber(opnd.variant.reg); 5565 5566 switch (from_size) { 5567 case 1: 5568 /* Widening to a half-word is implemented like widening to a word 5569 because the upper half-word will not be looked at. */ 5570 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */ 5571 if (sign_extend) 5572 return s390_emit_LBRw(buf, r1, r2); 5573 else 5574 return s390_emit_LLCRw(buf, r1, r2); 5575 } 5576 if (insn->size == 8) { /* 8 --> 64 */ 5577 if (sign_extend) 5578 return s390_emit_LGBRw(buf, r1, r2); 5579 else 5580 return s390_emit_LLGCRw(buf, r1, r2); 5581 } 5582 goto fail; 5583 5584 case 2: 5585 if (insn->size == 4) { /* 16 --> 32 */ 5586 if (sign_extend) 5587 return s390_emit_LHRw(buf, r1, r2); 5588 else 5589 return s390_emit_LLHRw(buf, r1, r2); 5590 } 5591 if (insn->size == 8) { /* 16 --> 64 */ 5592 if (sign_extend) 5593 return s390_emit_LGHRw(buf, r1, r2); 5594 else 5595 return s390_emit_LLGHRw(buf, r1, r2); 5596 } 5597 goto fail; 5598 5599 case 4: 5600 if (insn->size == 8) { /* 32 --> 64 */ 5601 if (sign_extend) 5602 return s390_emit_LGFR(buf, r1, r2); 5603 else 5604 return s390_emit_LLGFR(buf, r1, r2); 5605 } 5606 goto fail; 5607 5608 default: /* unexpected "from" size */ 5609 goto fail; 5610 } 5611 } 5612 5613 case S390_OPND_AMODE: { 5614 UChar r1 = hregNumber(insn->variant.unop.dst); 5615 const s390_amode *src = opnd.variant.am; 5616 UChar b = hregNumber(src->b); 5617 UChar x = hregNumber(src->x); 5618 Int d = src->d; 5619 5620 switch (from_size) { 5621 case 1: 5622 if (insn->size == 4 || insn->size == 2) { 5623 if (sign_extend) 5624 return s390_emit_LBw(buf, r1, x, b, DISP20(d)); 5625 else 5626 return s390_emit_LLCw(buf, r1, x, b, DISP20(d)); 5627 } 5628 if (insn->size == 8) { 5629 if (sign_extend) 5630 return s390_emit_LGBw(buf, r1, x, b, DISP20(d)); 5631 else 5632 return s390_emit_LLGC(buf, r1, x, b, DISP20(d)); 5633 } 5634 goto fail; 5635 5636 case 2: 5637 if (insn->size == 4) { /* 16 --> 32 */ 5638 if (sign_extend == 0) 5639 return s390_emit_LLHw(buf, r1, x, b, DISP20(d)); 5640 5641 switch (src->tag) { 5642 case S390_AMODE_B12: 5643 case S390_AMODE_BX12: 5644 return s390_emit_LH(buf, r1, x, b, d); 5645 5646 case S390_AMODE_B20: 5647 case S390_AMODE_BX20: 5648 return s390_emit_LHY(buf, r1, x, b, DISP20(d)); 5649 } 5650 goto fail; 5651 } 5652 if (insn->size == 8) { /* 16 --> 64 */ 5653 if (sign_extend) 5654 return s390_emit_LGH(buf, r1, x, b, DISP20(d)); 5655 else 5656 return s390_emit_LLGH(buf, r1, x, b, DISP20(d)); 5657 } 5658 goto fail; 5659 5660 case 4: 5661 if (insn->size == 8) { /* 32 --> 64 */ 5662 if (sign_extend) 5663 return s390_emit_LGF(buf, r1, x, b, DISP20(d)); 5664 else 5665 return s390_emit_LLGF(buf, r1, x, b, DISP20(d)); 5666 } 5667 goto fail; 5668 5669 default: /* unexpected "from" size */ 5670 goto fail; 5671 } 5672 } 5673 5674 case S390_OPND_IMMEDIATE: { 5675 UChar r1 = hregNumber(insn->variant.unop.dst); 5676 ULong value = opnd.variant.imm; 5677 5678 switch (from_size) { 5679 case 1: 5680 if (insn->size == 4 || insn->size == 2) { /* 8 --> 32 8 --> 16 */ 5681 if (sign_extend) { 5682 /* host can do the sign extension to 16-bit; LHI does the rest */ 5683 return s390_emit_LHI(buf, r1, (Short)(Char)(UChar)value); 5684 } else { 5685 return s390_emit_LHI(buf, r1, value); 5686 } 5687 } 5688 if (insn->size == 8) { /* 8 --> 64 */ 5689 if (sign_extend) { 5690 /* host can do the sign extension to 16-bit; LGHI does the rest */ 5691 return s390_emit_LGHI(buf, r1, (Short)(Char)(UChar)value); 5692 } else { 5693 return s390_emit_LGHI(buf, r1, value); 5694 } 5695 } 5696 goto fail; 5697 5698 case 2: 5699 if (insn->size == 4) { /* 16 --> 32 */ 5700 return s390_emit_LHI(buf, r1, value); 5701 } 5702 if (insn->size == 8) { /* 16 --> 64 */ 5703 if (sign_extend) 5704 return s390_emit_LGHI(buf, r1, value); 5705 else 5706 return s390_emit_LLILL(buf, r1, value); 5707 } 5708 goto fail; 5709 5710 case 4: 5711 if (insn->size == 8) { /* 32 --> 64 */ 5712 if (sign_extend) 5713 return s390_emit_LGFIw(buf, r1, value); 5714 else 5715 return s390_emit_LLILFw(buf, r1, value); 5716 } 5717 goto fail; 5718 5719 default: /* unexpected "from" size */ 5720 goto fail; 5721 } 5722 } 5723 } 5724 5725 fail: 5726 vpanic("s390_widen_emit"); 5727 } 5728 5729 5730 static UChar * 5731 s390_negate_emit(UChar *buf, const s390_insn *insn) 5732 { 5733 s390_opnd_RMI opnd; 5734 5735 opnd = insn->variant.unop.src; 5736 5737 switch (opnd.tag) { 5738 case S390_OPND_REG: { 5739 UChar r1 = hregNumber(insn->variant.unop.dst); 5740 UChar r2 = hregNumber(opnd.variant.reg); 5741 5742 switch (insn->size) { 5743 case 1: 5744 case 2: 5745 case 4: 5746 return s390_emit_LCR(buf, r1, r2); 5747 5748 case 8: 5749 return s390_emit_LCGR(buf, r1, r2); 5750 5751 default: 5752 goto fail; 5753 } 5754 } 5755 5756 case S390_OPND_AMODE: { 5757 UChar r1 = hregNumber(insn->variant.unop.dst); 5758 5759 /* Load bytes into scratch register R0, then negate */ 5760 buf = s390_emit_load_mem(buf, insn->size, R0, opnd.variant.am); 5761 5762 switch (insn->size) { 5763 case 1: 5764 case 2: 5765 case 4: 5766 return s390_emit_LCR(buf, r1, R0); 5767 5768 case 8: 5769 return s390_emit_LCGR(buf, r1, R0); 5770 5771 default: 5772 goto fail; 5773 } 5774 } 5775 5776 case S390_OPND_IMMEDIATE: { 5777 UChar r1 = hregNumber(insn->variant.unop.dst); 5778 ULong value = opnd.variant.imm; 5779 5780 value = ~value + 1; /* two's complement */ 5781 5782 switch (insn->size) { 5783 case 1: 5784 case 2: 5785 /* Load the immediate values as a 4 byte value. That does not hurt as 5786 those extra bytes will not be looked at. Fall through .... */ 5787 case 4: 5788 return s390_emit_load_32imm(buf, r1, value); 5789 5790 case 8: 5791 return s390_emit_load_64imm(buf, r1, value); 5792 5793 default: 5794 goto fail; 5795 } 5796 } 5797 } 5798 5799 fail: 5800 vpanic("s390_negate_emit"); 5801 } 5802 5803 5804 static UChar * 5805 s390_insn_unop_emit(UChar *buf, const s390_insn *insn) 5806 { 5807 switch (insn->variant.unop.tag) { 5808 case S390_ZERO_EXTEND_8: return s390_widen_emit(buf, insn, 1, 0); 5809 case S390_ZERO_EXTEND_16: return s390_widen_emit(buf, insn, 2, 0); 5810 case S390_ZERO_EXTEND_32: return s390_widen_emit(buf, insn, 4, 0); 5811 5812 case S390_SIGN_EXTEND_8: return s390_widen_emit(buf, insn, 1, 1); 5813 case S390_SIGN_EXTEND_16: return s390_widen_emit(buf, insn, 2, 1); 5814 case S390_SIGN_EXTEND_32: return s390_widen_emit(buf, insn, 4, 1); 5815 5816 case S390_NEGATE: return s390_negate_emit(buf, insn); 5817 } 5818 5819 vpanic("s390_insn_unop_emit"); 5820 } 5821 5822 5823 /* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte 5824 comparisons will have been converted to 4-byte comparisons in 5825 s390_isel_cc and should not occur here. */ 5826 static UChar * 5827 s390_insn_test_emit(UChar *buf, const s390_insn *insn) 5828 { 5829 s390_opnd_RMI opnd; 5830 5831 opnd = insn->variant.test.src; 5832 5833 switch (opnd.tag) { 5834 case S390_OPND_REG: { 5835 UInt reg = hregNumber(opnd.variant.reg); 5836 5837 switch (insn->size) { 5838 case 4: 5839 return s390_emit_LTR(buf, reg, reg); 5840 5841 case 8: 5842 return s390_emit_LTGR(buf, reg, reg); 5843 5844 default: 5845 goto fail; 5846 } 5847 } 5848 5849 case S390_OPND_AMODE: { 5850 const s390_amode *am = opnd.variant.am; 5851 UChar b = hregNumber(am->b); 5852 UChar x = hregNumber(am->x); 5853 Int d = am->d; 5854 5855 switch (insn->size) { 5856 case 4: 5857 return s390_emit_LTw(buf, R0, x, b, DISP20(d)); 5858 5859 case 8: 5860 return s390_emit_LTGw(buf, R0, x, b, DISP20(d)); 5861 5862 default: 5863 goto fail; 5864 } 5865 } 5866 5867 case S390_OPND_IMMEDIATE: { 5868 ULong value = opnd.variant.imm; 5869 5870 switch (insn->size) { 5871 case 4: 5872 buf = s390_emit_load_32imm(buf, R0, value); 5873 return s390_emit_LTR(buf, R0, R0); 5874 5875 case 8: 5876 buf = s390_emit_load_64imm(buf, R0, value); 5877 return s390_emit_LTGR(buf, R0, R0); 5878 5879 default: 5880 goto fail; 5881 } 5882 } 5883 5884 default: 5885 goto fail; 5886 } 5887 5888 fail: 5889 vpanic("s390_insn_test_emit"); 5890 } 5891 5892 5893 static UChar * 5894 s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn) 5895 { 5896 UChar r1 = hregNumber(insn->variant.cc2bool.dst); 5897 s390_cc_t cond = insn->variant.cc2bool.cond; 5898 5899 /* Make the destination register be 1 or 0, depending on whether 5900 the relevant condition holds. A 64-bit value is computed. */ 5901 if (cond == S390_CC_ALWAYS) 5902 return s390_emit_LGHI(buf, r1, 1); /* r1 = 1 */ 5903 5904 buf = s390_emit_load_cc(buf, r1); /* r1 = cc */ 5905 buf = s390_emit_LGHI(buf, R0, cond); /* r0 = mask */ 5906 buf = s390_emit_SLLG(buf, r1, R0, r1, DISP20(0)); /* r1 = mask << cc */ 5907 buf = s390_emit_SRLG(buf, r1, r1, 0, DISP20(3)); /* r1 = r1 >> 3 */ 5908 buf = s390_emit_NILL(buf, r1, 1); /* r1 = r1 & 0x1 */ 5909 5910 return buf; 5911 } 5912 5913 5914 /* Only 4-byte and 8-byte operands are handled. */ 5915 static UChar * 5916 s390_insn_cas_emit(UChar *buf, const s390_insn *insn) 5917 { 5918 UChar r1, r3, b, old; 5919 Int d; 5920 s390_amode *am; 5921 5922 r1 = hregNumber(insn->variant.cas.op1); /* expected value */ 5923 r3 = hregNumber(insn->variant.cas.op3); 5924 old= hregNumber(insn->variant.cas.old_mem); 5925 am = insn->variant.cas.op2; 5926 b = hregNumber(am->b); 5927 d = am->d; 5928 5929 switch (insn->size) { 5930 case 4: 5931 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */ 5932 buf = s390_emit_LR(buf, R0, r1); 5933 if (am->tag == S390_AMODE_B12) 5934 buf = s390_emit_CS(buf, R0, r3, b, d); 5935 else 5936 buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d)); 5937 /* Now copy R0 which has the old memory value to OLD */ 5938 return s390_emit_LR(buf, old, R0); 5939 5940 case 8: 5941 /* r1 must no be overwritten. So copy it to R0 and let CS clobber it */ 5942 buf = s390_emit_LGR(buf, R0, r1); 5943 buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d)); 5944 /* Now copy R0 which has the old memory value to OLD */ 5945 return s390_emit_LGR(buf, old, R0); 5946 5947 default: 5948 goto fail; 5949 } 5950 5951 fail: 5952 vpanic("s390_insn_cas_emit"); 5953 } 5954 5955 5956 /* Only 4-byte and 8-byte comparisons are handled. 1-byte and 2-byte 5957 comparisons will have been converted to 4-byte comparisons in 5958 s390_isel_cc and should not occur here. */ 5959 static UChar * 5960 s390_insn_compare_emit(UChar *buf, const s390_insn *insn) 5961 { 5962 s390_opnd_RMI op2; 5963 HReg op1; 5964 Bool signed_comparison; 5965 5966 op1 = insn->variant.compare.src1; 5967 op2 = insn->variant.compare.src2; 5968 signed_comparison = insn->variant.compare.signed_comparison; 5969 5970 switch (op2.tag) { 5971 case S390_OPND_REG: { 5972 UInt r1 = hregNumber(op1); 5973 UInt r2 = hregNumber(op2.variant.reg); 5974 5975 switch (insn->size) { 5976 case 4: 5977 if (signed_comparison) 5978 return s390_emit_CR(buf, r1, r2); 5979 else 5980 return s390_emit_CLR(buf, r1, r2); 5981 5982 case 8: 5983 if (signed_comparison) 5984 return s390_emit_CGR(buf, r1, r2); 5985 else 5986 return s390_emit_CLGR(buf, r1, r2); 5987 5988 default: 5989 goto fail; 5990 } 5991 } 5992 5993 case S390_OPND_AMODE: { 5994 UChar r1 = hregNumber(op1); 5995 const s390_amode *am = op2.variant.am; 5996 UChar b = hregNumber(am->b); 5997 UChar x = hregNumber(am->x); 5998 Int d = am->d; 5999 6000 switch (insn->size) { 6001 case 4: 6002 switch (am->tag) { 6003 case S390_AMODE_B12: 6004 case S390_AMODE_BX12: 6005 if (signed_comparison) 6006 return s390_emit_C(buf, r1, x, b, d); 6007 else 6008 return s390_emit_CL(buf, r1, x, b, d); 6009 6010 case S390_AMODE_B20: 6011 case S390_AMODE_BX20: 6012 if (signed_comparison) 6013 return s390_emit_CY(buf, r1, x, b, DISP20(d)); 6014 else 6015 return s390_emit_CLY(buf, r1, x, b, DISP20(d)); 6016 } 6017 goto fail; 6018 6019 case 8: 6020 if (signed_comparison) 6021 return s390_emit_CG(buf, r1, x, b, DISP20(d)); 6022 else 6023 return s390_emit_CLG(buf, r1, x, b, DISP20(d)); 6024 6025 default: 6026 goto fail; 6027 } 6028 } 6029 6030 case S390_OPND_IMMEDIATE: { 6031 UChar r1 = hregNumber(op1); 6032 ULong value = op2.variant.imm; 6033 6034 switch (insn->size) { 6035 case 4: 6036 if (signed_comparison) 6037 return s390_emit_CFIw(buf, r1, value); 6038 else 6039 return s390_emit_CLFIw(buf, r1, value); 6040 6041 case 8: 6042 buf = s390_emit_load_64imm(buf, R0, value); 6043 if (signed_comparison) 6044 return s390_emit_CGR(buf, r1, R0); 6045 else 6046 return s390_emit_CLGR(buf, r1, R0); 6047 6048 default: 6049 goto fail; 6050 } 6051 } 6052 6053 default: 6054 goto fail; 6055 } 6056 6057 fail: 6058 vpanic("s390_insn_compare_emit"); 6059 } 6060 6061 6062 static UChar * 6063 s390_insn_mul_emit(UChar *buf, const s390_insn *insn) 6064 { 6065 s390_opnd_RMI op2; 6066 UChar r1; 6067 Bool signed_multiply; 6068 6069 /* The register number identifying the register pair */ 6070 r1 = hregNumber(insn->variant.mul.dst_hi); 6071 6072 op2 = insn->variant.mul.op2; 6073 signed_multiply = insn->variant.mul.signed_multiply; 6074 6075 switch (op2.tag) { 6076 case S390_OPND_REG: { 6077 UInt r2 = hregNumber(op2.variant.reg); 6078 6079 switch (insn->size) { 6080 case 1: 6081 case 2: 6082 case 4: 6083 if (signed_multiply) 6084 return s390_emit_MR(buf, r1, r2); 6085 else 6086 return s390_emit_MLR(buf, r1, r2); 6087 6088 case 8: 6089 if (signed_multiply) 6090 vpanic("s390_insn_mul_emit"); 6091 else 6092 return s390_emit_MLGR(buf, r1, r2); 6093 6094 default: 6095 goto fail; 6096 } 6097 } 6098 6099 case S390_OPND_AMODE: { 6100 const s390_amode *am = op2.variant.am; 6101 UChar b = hregNumber(am->b); 6102 UChar x = hregNumber(am->x); 6103 Int d = am->d; 6104 6105 switch (insn->size) { 6106 case 1: 6107 case 2: 6108 /* Load bytes into scratch register R0, then multiply */ 6109 buf = s390_emit_load_mem(buf, insn->size, R0, am); 6110 if (signed_multiply) 6111 return s390_emit_MR(buf, r1, R0); 6112 else 6113 return s390_emit_MLR(buf, r1, R0); 6114 6115 case 4: 6116 switch (am->tag) { 6117 case S390_AMODE_B12: 6118 case S390_AMODE_BX12: 6119 if (signed_multiply) 6120 return s390_emit_M(buf, r1, x, b, d); 6121 else 6122 return s390_emit_ML(buf, r1, x, b, DISP20(d)); 6123 6124 case S390_AMODE_B20: 6125 case S390_AMODE_BX20: 6126 if (signed_multiply) 6127 return s390_emit_MFYw(buf, r1, x, b, DISP20(d)); 6128 else 6129 return s390_emit_ML(buf, r1, x, b, DISP20(d)); 6130 } 6131 goto fail; 6132 6133 case 8: 6134 if (signed_multiply) 6135 vpanic("s390_insn_mul_emit"); 6136 else 6137 return s390_emit_MLG(buf, r1, x, b, DISP20(d)); 6138 6139 default: 6140 goto fail; 6141 } 6142 } 6143 6144 case S390_OPND_IMMEDIATE: { 6145 ULong value = op2.variant.imm; 6146 6147 switch (insn->size) { 6148 case 1: 6149 case 2: 6150 case 4: 6151 buf = s390_emit_load_32imm(buf, R0, value); 6152 if (signed_multiply) 6153 return s390_emit_MR(buf, r1, R0); 6154 else 6155 return s390_emit_MLR(buf, r1, R0); 6156 6157 case 8: 6158 buf = s390_emit_load_64imm(buf, R0, value); 6159 if (signed_multiply) 6160 vpanic("s390_insn_mul_emit"); 6161 else 6162 return s390_emit_MLGR(buf, r1, R0); 6163 6164 default: 6165 goto fail; 6166 } 6167 } 6168 6169 default: 6170 goto fail; 6171 } 6172 6173 fail: 6174 vpanic("s390_insn_mul_emit"); 6175 } 6176 6177 6178 static UChar * 6179 s390_insn_div_emit(UChar *buf, const s390_insn *insn) 6180 { 6181 s390_opnd_RMI op2; 6182 UChar r1; 6183 Bool signed_divide; 6184 6185 r1 = hregNumber(insn->variant.div.op1_hi); 6186 op2 = insn->variant.div.op2; 6187 signed_divide = insn->variant.div.signed_divide; 6188 6189 switch (op2.tag) { 6190 case S390_OPND_REG: { 6191 UInt r2 = hregNumber(op2.variant.reg); 6192 6193 switch (insn->size) { 6194 case 4: 6195 if (signed_divide) 6196 return s390_emit_DR(buf, r1, r2); 6197 else 6198 return s390_emit_DLR(buf, r1, r2); 6199 6200 case 8: 6201 if (signed_divide) 6202 vpanic("s390_insn_div_emit"); 6203 else 6204 return s390_emit_DLGR(buf, r1, r2); 6205 6206 default: 6207 goto fail; 6208 } 6209 } 6210 6211 case S390_OPND_AMODE: { 6212 const s390_amode *am = op2.variant.am; 6213 UChar b = hregNumber(am->b); 6214 UChar x = hregNumber(am->x); 6215 Int d = am->d; 6216 6217 switch (insn->size) { 6218 case 4: 6219 switch (am->tag) { 6220 case S390_AMODE_B12: 6221 case S390_AMODE_BX12: 6222 if (signed_divide) 6223 return s390_emit_D(buf, r1, x, b, d); 6224 else 6225 return s390_emit_DL(buf, r1, x, b, DISP20(d)); 6226 6227 case S390_AMODE_B20: 6228 case S390_AMODE_BX20: 6229 if (signed_divide) { 6230 buf = s390_emit_LY(buf, R0, x, b, DISP20(d)); 6231 return s390_emit_DR(buf, r1, R0); 6232 } else 6233 return s390_emit_DL(buf, r1, x, b, DISP20(d)); 6234 } 6235 goto fail; 6236 6237 case 8: 6238 if (signed_divide) 6239 vpanic("s390_insn_div_emit"); 6240 else 6241 return s390_emit_DLG(buf, r1, x, b, DISP20(d)); 6242 6243 default: 6244 goto fail; 6245 } 6246 } 6247 6248 case S390_OPND_IMMEDIATE: { 6249 ULong value = op2.variant.imm; 6250 6251 switch (insn->size) { 6252 case 4: 6253 buf = s390_emit_load_32imm(buf, R0, value); 6254 if (signed_divide) 6255 return s390_emit_DR(buf, r1, R0); 6256 else 6257 return s390_emit_DLR(buf, r1, R0); 6258 6259 case 8: 6260 buf = s390_emit_load_64imm(buf, R0, value); 6261 if (signed_divide) 6262 vpanic("s390_insn_div_emit"); 6263 else 6264 return s390_emit_DLGR(buf, r1, R0); 6265 6266 default: 6267 goto fail; 6268 } 6269 } 6270 6271 default: 6272 goto fail; 6273 } 6274 6275 fail: 6276 vpanic("s390_insn_div_emit"); 6277 } 6278 6279 6280 static UChar * 6281 s390_insn_divs_emit(UChar *buf, const s390_insn *insn) 6282 { 6283 s390_opnd_RMI op2; 6284 UChar r1; 6285 6286 r1 = hregNumber(insn->variant.divs.rem); 6287 op2 = insn->variant.divs.op2; 6288 6289 switch (op2.tag) { 6290 case S390_OPND_REG: { 6291 UInt r2 = hregNumber(op2.variant.reg); 6292 6293 return s390_emit_DSGR(buf, r1, r2); 6294 } 6295 6296 case S390_OPND_AMODE: { 6297 const s390_amode *am = op2.variant.am; 6298 UChar b = hregNumber(am->b); 6299 UChar x = hregNumber(am->x); 6300 Int d = am->d; 6301 6302 return s390_emit_DSG(buf, r1, x, b, DISP20(d)); 6303 } 6304 6305 case S390_OPND_IMMEDIATE: { 6306 ULong value = op2.variant.imm; 6307 6308 buf = s390_emit_load_64imm(buf, R0, value); 6309 return s390_emit_DSGR(buf, r1, R0); 6310 } 6311 6312 default: 6313 goto fail; 6314 } 6315 6316 fail: 6317 vpanic("s390_insn_divs_emit"); 6318 } 6319 6320 6321 static UChar * 6322 s390_insn_clz_emit(UChar *buf, const s390_insn *insn) 6323 { 6324 s390_opnd_RMI src; 6325 UChar r1, r1p1, r2, *p; 6326 6327 r1 = hregNumber(insn->variant.clz.num_bits); 6328 r1p1 = hregNumber(insn->variant.clz.clobber); 6329 6330 vassert((r1 & 0x1) == 0); 6331 vassert(r1p1 == r1 + 1); 6332 6333 p = buf; 6334 src = insn->variant.clz.src; 6335 6336 /* Get operand and move it to r2 */ 6337 switch (src.tag) { 6338 case S390_OPND_REG: 6339 r2 = hregNumber(src.variant.reg); 6340 break; 6341 6342 case S390_OPND_AMODE: { 6343 const s390_amode *am = src.variant.am; 6344 UChar b = hregNumber(am->b); 6345 UChar x = hregNumber(am->x); 6346 Int d = am->d; 6347 6348 p = s390_emit_LG(p, R0, x, b, DISP20(d)); 6349 r2 = R0; 6350 break; 6351 } 6352 6353 case S390_OPND_IMMEDIATE: { 6354 ULong value = src.variant.imm; 6355 6356 p = s390_emit_load_64imm(p, R0, value); 6357 r2 = R0; 6358 break; 6359 } 6360 6361 default: 6362 goto fail; 6363 } 6364 6365 /* Use FLOGR if you can */ 6366 if (s390_host_has_eimm) { 6367 return s390_emit_FLOGR(p, r1, r2); 6368 } 6369 6370 /* 6371 r0 = r2; 6372 r1 = 64; 6373 while (r0 != 0) { 6374 r1 -= 1; 6375 r0 >>= 1; 6376 } 6377 */ 6378 p = s390_emit_LTGR(p, R0, r2); 6379 p = s390_emit_LLILL(p, r1, 64); 6380 6381 p = s390_emit_BRC(p, S390_CC_E, (4 + 4 + 6 + 4 + 4)/ 2); /* 4 bytes */ 6382 p = s390_emit_AGHI(p, r1, (UShort)-1); /* r1 -= 1; 4 bytes */ 6383 p = s390_emit_SRLG(p, R0, R0, R0, DISP20(1)); /* r0 >>= 1; 6 bytes */ 6384 p = s390_emit_LTGR(p, R0, R0); /* set cc 4 bytes */ 6385 p = s390_emit_BRC(p, S390_CC_NE, /* 4 bytes */ 6386 (UShort)(-(4 + 6 + 4) / 2)); 6387 return p; 6388 6389 fail: 6390 vpanic("s390_insn_clz_emit"); 6391 } 6392 6393 6394 static UChar * 6395 s390_insn_branch_emit(UChar *buf, const s390_insn *insn) 6396 { 6397 s390_opnd_RMI dst; 6398 s390_cc_t cond; 6399 UInt trc; 6400 UChar *p, *ptmp = 0; /* avoid compiler warnings */ 6401 6402 cond = insn->variant.branch.cond; 6403 dst = insn->variant.branch.dst; 6404 6405 p = buf; 6406 trc = 0; 6407 6408 if (cond != S390_CC_ALWAYS) { 6409 /* So we have something like this 6410 if (cond) goto X; 6411 Y: ... 6412 We convert this into 6413 if (! cond) goto Y; // BRC insn; 4 bytes 6414 return_reg = X; 6415 return to dispatcher 6416 Y: 6417 */ 6418 ptmp = p; /* 4 bytes (a BRC insn) to be filled in here */ 6419 p += 4; 6420 } 6421 6422 /* If a non-boring, set guest-state-pointer appropriately. */ 6423 6424 switch (insn->variant.branch.kind) { 6425 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break; 6426 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break; 6427 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break; 6428 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break; 6429 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break; 6430 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break; 6431 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break; 6432 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break; 6433 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break; 6434 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break; 6435 case Ijk_Ret: trc = 0; break; 6436 case Ijk_Call: trc = 0; break; 6437 case Ijk_Boring: trc = 0; break; 6438 break; 6439 6440 default: 6441 vpanic("s390_insn_branch_emit: unknown jump kind"); 6442 } 6443 6444 /* Get the destination address into the return register */ 6445 switch (dst.tag) { 6446 case S390_OPND_REG: 6447 p = s390_emit_LGR(p, S390_REGNO_RETURN_VALUE, hregNumber(dst.variant.reg)); 6448 break; 6449 6450 case S390_OPND_AMODE: { 6451 const s390_amode *am = dst.variant.am; 6452 UChar b = hregNumber(am->b); 6453 UChar x = hregNumber(am->x); 6454 Int d = am->d; 6455 6456 p = s390_emit_LG(p, S390_REGNO_RETURN_VALUE, x, b, DISP20(d)); 6457 break; 6458 } 6459 6460 case S390_OPND_IMMEDIATE: 6461 p = s390_emit_load_64imm(p, S390_REGNO_RETURN_VALUE, dst.variant.imm); 6462 break; 6463 6464 default: 6465 goto fail; 6466 } 6467 6468 if (trc != 0) { 6469 /* Something special. Set guest-state pointer appropriately */ 6470 p = s390_emit_LGHI(p, S390_REGNO_GUEST_STATE_POINTER, trc); 6471 } else { 6472 /* Nothing special needs to be done for calls and returns. */ 6473 } 6474 6475 p = s390_emit_BCR(p, S390_CC_ALWAYS, S390_REGNO_LINK_REGISTER); 6476 6477 if (cond != S390_CC_ALWAYS) { 6478 Int delta = p - ptmp; 6479 6480 delta >>= 1; /* immediate constant is #half-words */ 6481 vassert(delta > 0 && delta < (1 << 16)); 6482 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 6483 } 6484 6485 return p; 6486 6487 fail: 6488 vpanic("s390_insn_branch_emit"); 6489 } 6490 6491 6492 static UChar * 6493 s390_insn_helper_call_emit(UChar *buf, const s390_insn *insn) 6494 { 6495 s390_cc_t cond; 6496 ULong target; 6497 UChar *ptmp = buf; 6498 6499 cond = insn->variant.helper_call.cond; 6500 target = insn->variant.helper_call.target; 6501 6502 if (cond != S390_CC_ALWAYS) { 6503 /* So we have something like this 6504 if (cond) call X; 6505 Y: ... 6506 We convert this into 6507 if (! cond) goto Y; // BRC opcode; 4 bytes 6508 call X; 6509 Y: 6510 */ 6511 /* 4 bytes (a BRC insn) to be filled in here */ 6512 buf += 4; 6513 } 6514 6515 /* Load the target address into a register, that 6516 (a) is not used for passing parameters to the helper and 6517 (b) can be clobbered by the callee 6518 r1 looks like a good choice. 6519 Also, need to arrange for the return address be put into the 6520 link-register */ 6521 buf = s390_emit_load_64imm(buf, 1, target); 6522 6523 /* Stash away the client's FPC register because the helper might change it. */ 6524 buf = s390_emit_STFPC(buf, S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_FPC_C); 6525 6526 /* Before we can call the helper, we need to save the link register, 6527 because the BASR will overwrite it. We cannot use a register for that. 6528 (a) Volatile registers will be modified by the helper. 6529 (b) For saved registers the client code assumes that they have not 6530 changed after the function returns. So we cannot use it to store 6531 the link register. 6532 In the dispatcher, before calling the client code, we have arranged for 6533 a location on the stack for this purpose. See dispatch-s390x-linux.S. */ 6534 buf = s390_emit_STG(buf, S390_REGNO_LINK_REGISTER, 0, // save LR 6535 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0); 6536 buf = s390_emit_BASR(buf, S390_REGNO_LINK_REGISTER, 1); // call helper 6537 buf = s390_emit_LG(buf, S390_REGNO_LINK_REGISTER, 0, // restore LR 6538 S390_REGNO_STACK_POINTER, S390_OFFSET_SAVED_LR, 0); 6539 buf = s390_emit_LFPC(buf, S390_REGNO_STACK_POINTER, // restore FPC 6540 S390_OFFSET_SAVED_FPC_C); 6541 6542 if (cond != S390_CC_ALWAYS) { 6543 Int delta = buf - ptmp; 6544 6545 delta >>= 1; /* immediate constant is #half-words */ 6546 vassert(delta > 0 && delta < (1 << 16)); 6547 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 6548 } 6549 6550 return buf; 6551 } 6552 6553 6554 static UChar * 6555 s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn) 6556 { 6557 HReg dst; 6558 s390_opnd_RMI src; 6559 s390_cc_t cond; 6560 UChar *p, *ptmp = 0; /* avoid compiler warnings */ 6561 6562 cond = insn->variant.cond_move.cond; 6563 dst = insn->variant.cond_move.dst; 6564 src = insn->variant.cond_move.src; 6565 6566 p = buf; 6567 6568 /* Branch (if cond fails) over move instrs */ 6569 if (cond != S390_CC_ALWAYS) { 6570 /* Don't know how many bytes to jump over yet. 6571 Make space for a BRC instruction (4 bytes) and fill in later. */ 6572 ptmp = p; /* to be filled in here */ 6573 p += 4; 6574 } 6575 6576 // cond true: move src => dst 6577 6578 switch (src.tag) { 6579 case S390_OPND_REG: 6580 p = s390_emit_LGR(p, hregNumber(dst), hregNumber(src.variant.reg)); 6581 break; 6582 6583 case S390_OPND_AMODE: 6584 p = s390_emit_load_mem(p, insn->size, hregNumber(dst), src.variant.am); 6585 break; 6586 6587 case S390_OPND_IMMEDIATE: { 6588 ULong value = src.variant.imm; 6589 UInt r = hregNumber(dst); 6590 6591 switch (insn->size) { 6592 case 1: 6593 case 2: 6594 /* Load the immediate values as a 4 byte value. That does not hurt as 6595 those extra bytes will not be looked at. Fall through .... */ 6596 case 4: 6597 p = s390_emit_load_32imm(p, r, value); 6598 break; 6599 6600 case 8: 6601 p = s390_emit_load_64imm(p, r, value); 6602 break; 6603 } 6604 break; 6605 } 6606 6607 default: 6608 goto fail; 6609 } 6610 6611 if (cond != S390_CC_ALWAYS) { 6612 Int delta = p - ptmp; 6613 6614 delta >>= 1; /* immediate constant is #half-words */ 6615 vassert(delta > 0 && delta < (1 << 16)); 6616 s390_emit_BRC(ptmp, s390_cc_invert(cond), delta); 6617 } 6618 6619 return p; 6620 6621 fail: 6622 vpanic("s390_insn_cond_move_emit"); 6623 } 6624 6625 6626 /* Little helper function to the rounding mode in the real FPC 6627 register */ 6628 static UChar * 6629 s390_set_fpc_rounding_mode(UChar *buf, s390_round_t rounding_mode) 6630 { 6631 UChar bits; 6632 6633 /* Determine BFP rounding bits */ 6634 switch (rounding_mode) { 6635 case S390_ROUND_NEAREST_EVEN: bits = 0; break; 6636 case S390_ROUND_ZERO: bits = 1; break; 6637 case S390_ROUND_POSINF: bits = 2; break; 6638 case S390_ROUND_NEGINF: bits = 3; break; 6639 default: vpanic("invalid rounding mode\n"); 6640 } 6641 6642 /* Copy FPC from guest state to R0 and OR in the new rounding mode */ 6643 buf = s390_emit_L(buf, R0, 0, S390_REGNO_GUEST_STATE_POINTER, 6644 OFFSET_s390x_fpc); // r0 = guest_fpc 6645 6646 buf = s390_emit_NILL(buf, R0, 0xFFFC); /* Clear out right-most 2 bits */ 6647 buf = s390_emit_OILL(buf, R0, bits); /* OR in the new rounding mode */ 6648 buf = s390_emit_SFPC(buf, R0, 0); /* Load FPC register from R0 */ 6649 6650 return buf; 6651 } 6652 6653 6654 static UChar * 6655 s390_insn_bfp_triop_emit(UChar *buf, const s390_insn *insn) 6656 { 6657 UInt r1 = hregNumber(insn->variant.bfp_triop.dst); 6658 UInt r2 = hregNumber(insn->variant.bfp_triop.op2); 6659 UInt r3 = hregNumber(insn->variant.bfp_triop.op3); 6660 s390_round_t rounding_mode = insn->variant.bfp_triop.rounding_mode; 6661 6662 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6663 buf = s390_set_fpc_rounding_mode(buf, rounding_mode); 6664 } 6665 6666 switch (insn->size) { 6667 case 4: 6668 switch (insn->variant.bfp_triop.tag) { 6669 case S390_BFP_MADD: buf = s390_emit_MAEBR(buf, r1, r3, r2); break; 6670 case S390_BFP_MSUB: buf = s390_emit_MSEBR(buf, r1, r3, r2); break; 6671 default: goto fail; 6672 } 6673 break; 6674 6675 case 8: 6676 switch (insn->variant.bfp_triop.tag) { 6677 case S390_BFP_MADD: buf = s390_emit_MADBR(buf, r1, r3, r2); break; 6678 case S390_BFP_MSUB: buf = s390_emit_MSDBR(buf, r1, r3, r2); break; 6679 default: goto fail; 6680 } 6681 break; 6682 6683 default: goto fail; 6684 } 6685 6686 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6687 /* Restore FPC register from guest state */ 6688 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER, 6689 OFFSET_s390x_fpc); // fpc = guest_fpc 6690 } 6691 return buf; 6692 6693 fail: 6694 vpanic("s390_insn_bfp_triop_emit"); 6695 } 6696 6697 6698 static UChar * 6699 s390_insn_bfp_binop_emit(UChar *buf, const s390_insn *insn) 6700 { 6701 UInt r1 = hregNumber(insn->variant.bfp_binop.dst); 6702 UInt r2 = hregNumber(insn->variant.bfp_binop.op2); 6703 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode; 6704 6705 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6706 buf = s390_set_fpc_rounding_mode(buf, rounding_mode); 6707 } 6708 6709 switch (insn->size) { 6710 case 4: 6711 switch (insn->variant.bfp_binop.tag) { 6712 case S390_BFP_ADD: buf = s390_emit_AEBR(buf, r1, r2); break; 6713 case S390_BFP_SUB: buf = s390_emit_SEBR(buf, r1, r2); break; 6714 case S390_BFP_MUL: buf = s390_emit_MEEBR(buf, r1, r2); break; 6715 case S390_BFP_DIV: buf = s390_emit_DEBR(buf, r1, r2); break; 6716 default: goto fail; 6717 } 6718 break; 6719 6720 case 8: 6721 switch (insn->variant.bfp_binop.tag) { 6722 case S390_BFP_ADD: buf = s390_emit_ADBR(buf, r1, r2); break; 6723 case S390_BFP_SUB: buf = s390_emit_SDBR(buf, r1, r2); break; 6724 case S390_BFP_MUL: buf = s390_emit_MDBR(buf, r1, r2); break; 6725 case S390_BFP_DIV: buf = s390_emit_DDBR(buf, r1, r2); break; 6726 default: goto fail; 6727 } 6728 break; 6729 6730 default: goto fail; 6731 } 6732 6733 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6734 /* Restore FPC register from guest state */ 6735 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER, 6736 OFFSET_s390x_fpc); 6737 } 6738 return buf; 6739 6740 fail: 6741 vpanic("s390_insn_bfp_binop_emit"); 6742 } 6743 6744 6745 static UChar * 6746 s390_insn_bfp_unop_emit(UChar *buf, const s390_insn *insn) 6747 { 6748 UInt r1 = hregNumber(insn->variant.bfp_unop.dst); 6749 UInt r2 = hregNumber(insn->variant.bfp_unop.op); 6750 s390_round_t rounding_mode = insn->variant.bfp_unop.rounding_mode; 6751 s390_round_t m3 = rounding_mode; 6752 6753 /* The "convert to fixed" instructions have a field for the rounding 6754 mode and no FPC modification is necessary. So we handle them 6755 upfront. */ 6756 switch (insn->variant.bfp_unop.tag) { 6757 case S390_BFP_F32_TO_I32: return s390_emit_CFEBR(buf, m3, r1, r2); 6758 case S390_BFP_F64_TO_I32: return s390_emit_CFDBR(buf, m3, r1, r2); 6759 case S390_BFP_F32_TO_I64: return s390_emit_CGEBR(buf, m3, r1, r2); 6760 case S390_BFP_F64_TO_I64: return s390_emit_CGDBR(buf, m3, r1, r2); 6761 default: break; 6762 } 6763 6764 /* For all other insns if a special rounding mode is requested, 6765 we need to set the FPC first and restore it later. */ 6766 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6767 buf = s390_set_fpc_rounding_mode(buf, rounding_mode); 6768 } 6769 6770 switch (insn->variant.bfp_unop.tag) { 6771 case S390_BFP_ABS: 6772 switch (insn->size) { 6773 case 4: buf = s390_emit_LPEBR(buf, r1, r2); break; 6774 case 8: buf = s390_emit_LPDBR(buf, r1, r2); break; 6775 case 16: buf = s390_emit_LPXBR(buf, r1, r2); break; 6776 default: goto fail; 6777 } 6778 break; 6779 6780 case S390_BFP_NABS: 6781 switch (insn->size) { 6782 case 4: buf = s390_emit_LNEBR(buf, r1, r2); break; 6783 case 8: buf = s390_emit_LNDBR(buf, r1, r2); break; 6784 case 16: buf = s390_emit_LNXBR(buf, r1, r2); break; 6785 default: goto fail; 6786 } 6787 break; 6788 6789 case S390_BFP_NEG: 6790 switch (insn->size) { 6791 case 4: buf = s390_emit_LCEBR(buf, r1, r2); break; 6792 case 8: buf = s390_emit_LCDBR(buf, r1, r2); break; 6793 case 16: buf = s390_emit_LCXBR(buf, r1, r2); break; 6794 default: goto fail; 6795 } 6796 break; 6797 6798 case S390_BFP_SQRT: 6799 switch (insn->size) { 6800 case 4: buf = s390_emit_SQEBR(buf, r1, r2); break; 6801 case 8: buf = s390_emit_SQDBR(buf, r1, r2); break; 6802 case 16: buf = s390_emit_SQXBR(buf, r1, r2); break; 6803 default: goto fail; 6804 } 6805 break; 6806 6807 case S390_BFP_I32_TO_F32: buf = s390_emit_CEFBR(buf, r1, r2); break; 6808 case S390_BFP_I32_TO_F64: buf = s390_emit_CDFBR(buf, r1, r2); break; 6809 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1, r2); break; 6810 case S390_BFP_I64_TO_F32: buf = s390_emit_CEGBR(buf, r1, r2); break; 6811 case S390_BFP_I64_TO_F64: buf = s390_emit_CDGBR(buf, r1, r2); break; 6812 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1, r2); break; 6813 6814 case S390_BFP_F32_TO_F64: buf = s390_emit_LDEBR(buf, r1, r2); break; 6815 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1, r2); break; 6816 case S390_BFP_F64_TO_F32: buf = s390_emit_LEDBR(buf, r1, r2); break; 6817 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1, r2); break; 6818 6819 default: goto fail; 6820 } 6821 6822 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6823 /* Restore FPC register from guest state */ 6824 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER, 6825 OFFSET_s390x_fpc); // fpc = guest_fpc 6826 } 6827 return buf; 6828 6829 fail: 6830 vpanic("s390_insn_bfp_unop_emit"); 6831 } 6832 6833 6834 static UChar * 6835 s390_insn_bfp_compare_emit(UChar *buf, const s390_insn *insn) 6836 { 6837 UInt dst = hregNumber(insn->variant.bfp_compare.dst); 6838 UInt r1 = hregNumber(insn->variant.bfp_compare.op1); 6839 UInt r2 = hregNumber(insn->variant.bfp_compare.op2); 6840 6841 switch (insn->size) { 6842 case 4: 6843 buf = s390_emit_CEBR(buf, r1, r2); 6844 break; 6845 6846 case 8: 6847 buf = s390_emit_CDBR(buf, r1, r2); 6848 break; 6849 6850 default: goto fail; 6851 } 6852 6853 return s390_emit_load_cc(buf, dst); /* Load condition code into DST */ 6854 6855 fail: 6856 vpanic("s390_insn_bfp_compare_emit"); 6857 } 6858 6859 6860 static UChar * 6861 s390_insn_bfp128_binop_emit(UChar *buf, const s390_insn *insn) 6862 { 6863 UInt r1_hi = hregNumber(insn->variant.bfp128_binop.dst_hi); 6864 UInt r1_lo = hregNumber(insn->variant.bfp128_binop.dst_lo); 6865 UInt r2_hi = hregNumber(insn->variant.bfp128_binop.op2_hi); 6866 UInt r2_lo = hregNumber(insn->variant.bfp128_binop.op2_lo); 6867 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode; 6868 6869 /* Paranoia */ 6870 vassert(insn->size == 16); 6871 vassert(r1_lo == r1_hi + 2); 6872 vassert(r2_lo == r2_hi + 2); 6873 vassert((r1_hi & 0x2) == 0); 6874 vassert((r2_hi & 0x2) == 0); 6875 6876 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6877 buf = s390_set_fpc_rounding_mode(buf, rounding_mode); 6878 } 6879 6880 switch (insn->variant.bfp128_binop.tag) { 6881 case S390_BFP_ADD: buf = s390_emit_AXBR(buf, r1_hi, r2_hi); break; 6882 case S390_BFP_SUB: buf = s390_emit_SXBR(buf, r1_hi, r2_hi); break; 6883 case S390_BFP_MUL: buf = s390_emit_MXBR(buf, r1_hi, r2_hi); break; 6884 case S390_BFP_DIV: buf = s390_emit_DXBR(buf, r1_hi, r2_hi); break; 6885 default: goto fail; 6886 } 6887 6888 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6889 /* Restore FPC register from guest state */ 6890 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER, 6891 OFFSET_s390x_fpc); // fpc = guest_fpc 6892 } 6893 return buf; 6894 6895 fail: 6896 vpanic("s390_insn_bfp128_binop_emit"); 6897 } 6898 6899 6900 static UChar * 6901 s390_insn_bfp128_compare_emit(UChar *buf, const s390_insn *insn) 6902 { 6903 UInt dst = hregNumber(insn->variant.bfp128_compare.dst); 6904 UInt r1_hi = hregNumber(insn->variant.bfp128_compare.op1_hi); 6905 UInt r1_lo = hregNumber(insn->variant.bfp128_compare.op1_lo); 6906 UInt r2_hi = hregNumber(insn->variant.bfp128_compare.op2_hi); 6907 UInt r2_lo = hregNumber(insn->variant.bfp128_compare.op2_lo); 6908 6909 /* Paranoia */ 6910 vassert(insn->size == 16); 6911 vassert(r1_lo == r1_hi + 2); 6912 vassert(r2_lo == r2_hi + 2); 6913 vassert((r1_hi & 0x2) == 0); 6914 vassert((r2_hi & 0x2) == 0); 6915 6916 buf = s390_emit_CXBR(buf, r1_hi, r2_hi); 6917 6918 /* Load condition code into DST */ 6919 return s390_emit_load_cc(buf, dst); 6920 } 6921 6922 6923 static UChar * 6924 s390_insn_bfp128_unop_emit(UChar *buf, const s390_insn *insn) 6925 { 6926 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi); 6927 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo); 6928 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi); 6929 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo); 6930 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode; 6931 6932 /* Paranoia */ 6933 vassert(insn->size == 16); 6934 vassert(r1_lo == r1_hi + 2); 6935 vassert(r2_lo == r2_hi + 2); 6936 vassert((r1_hi & 0x2) == 0); 6937 vassert((r2_hi & 0x2) == 0); 6938 6939 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6940 buf = s390_set_fpc_rounding_mode(buf, rounding_mode); 6941 } 6942 6943 switch (insn->variant.bfp128_unop.tag) { 6944 case S390_BFP_ABS: buf = s390_emit_LPXBR(buf, r1_hi, r2_hi); break; 6945 case S390_BFP_NABS: buf = s390_emit_LNXBR(buf, r1_hi, r2_hi); break; 6946 case S390_BFP_NEG: buf = s390_emit_LCXBR(buf, r1_hi, r2_hi); break; 6947 case S390_BFP_SQRT: buf = s390_emit_SQXBR(buf, r1_hi, r2_hi); break; 6948 case S390_BFP_F128_TO_F32: buf = s390_emit_LEXBR(buf, r1_hi, r2_hi); break; 6949 case S390_BFP_F128_TO_F64: buf = s390_emit_LDXBR(buf, r1_hi, r2_hi); break; 6950 default: goto fail; 6951 } 6952 6953 if (rounding_mode != S390_ROUND_NEAREST_EVEN) { 6954 /* Restore FPC register from guest state */ 6955 buf = s390_emit_LFPC(buf, S390_REGNO_GUEST_STATE_POINTER, 6956 OFFSET_s390x_fpc); // fpc = guest_fpc 6957 } 6958 return buf; 6959 6960 fail: 6961 vpanic("s390_insn_bfp128_unop_emit"); 6962 } 6963 6964 6965 /* Conversion to 128-bit BFP does not require a rounding mode */ 6966 static UChar * 6967 s390_insn_bfp128_convert_to_emit(UChar *buf, const s390_insn *insn) 6968 { 6969 UInt r1_hi = hregNumber(insn->variant.bfp128_unop.dst_hi); 6970 UInt r1_lo = hregNumber(insn->variant.bfp128_unop.dst_lo); 6971 UInt r2 = hregNumber(insn->variant.bfp128_unop.op_hi); 6972 6973 /* Paranoia */ 6974 vassert(insn->size == 16); 6975 vassert(r1_lo == r1_hi + 2); 6976 vassert((r1_hi & 0x2) == 0); 6977 6978 switch (insn->variant.bfp128_unop.tag) { 6979 case S390_BFP_I32_TO_F128: buf = s390_emit_CXFBR(buf, r1_hi, r2); break; 6980 case S390_BFP_I64_TO_F128: buf = s390_emit_CXGBR(buf, r1_hi, r2); break; 6981 case S390_BFP_F32_TO_F128: buf = s390_emit_LXEBR(buf, r1_hi, r2); break; 6982 case S390_BFP_F64_TO_F128: buf = s390_emit_LXDBR(buf, r1_hi, r2); break; 6983 default: goto fail; 6984 } 6985 6986 return buf; 6987 6988 fail: 6989 vpanic("s390_insn_bfp128_convert_to_emit"); 6990 } 6991 6992 6993 static UChar * 6994 s390_insn_bfp128_convert_from_emit(UChar *buf, const s390_insn *insn) 6995 { 6996 UInt r1 = hregNumber(insn->variant.bfp128_unop.dst_hi); 6997 UInt r2_hi = hregNumber(insn->variant.bfp128_unop.op_hi); 6998 UInt r2_lo = hregNumber(insn->variant.bfp128_unop.op_lo); 6999 s390_round_t rounding_mode = insn->variant.bfp_binop.rounding_mode; 7000 7001 /* Paranoia */ 7002 vassert(insn->size != 16); 7003 vassert(r2_lo == r2_hi + 2); 7004 vassert((r2_hi & 0x2) == 0); 7005 7006 /* The "convert to fixed" instructions have a field for the rounding 7007 mode and no FPC modification is necessary. So we handle them 7008 upfront. */ 7009 switch (insn->variant.bfp_unop.tag) { 7010 case S390_BFP_F128_TO_I32: return s390_emit_CFXBR(buf, rounding_mode, 7011 r1, r2_hi); break; 7012 case S390_BFP_F128_TO_I64: return s390_emit_CGXBR(buf, rounding_mode, 7013 r1, r2_hi); break; 7014 default: break; 7015 } 7016 7017 vpanic("s390_insn_bfp128_convert_from_emit"); 7018 } 7019 7020 7021 static UChar * 7022 s390_insn_mfence_emit(UChar *buf, const s390_insn *insn) 7023 { 7024 return s390_emit_BCR(buf, 0xF, 0x0); 7025 } 7026 7027 7028 Int 7029 emit_S390Instr(UChar *buf, Int nbuf, s390_insn *insn, Bool mode64, 7030 void *dispatch_unassisted, void *dispatch_assisted) 7031 { 7032 UChar *end; 7033 7034 switch (insn->tag) { 7035 case S390_INSN_LOAD: 7036 end = s390_insn_load_emit(buf, insn); 7037 break; 7038 7039 case S390_INSN_STORE: 7040 end = s390_insn_store_emit(buf, insn); 7041 break; 7042 7043 case S390_INSN_MOVE: 7044 end = s390_insn_move_emit(buf, insn); 7045 break; 7046 7047 case S390_INSN_COND_MOVE: 7048 end = s390_insn_cond_move_emit(buf, insn); 7049 break; 7050 7051 case S390_INSN_LOAD_IMMEDIATE: 7052 end = s390_insn_load_immediate_emit(buf, insn); 7053 break; 7054 7055 case S390_INSN_ALU: 7056 end = s390_insn_alu_emit(buf, insn); 7057 break; 7058 7059 case S390_INSN_MUL: 7060 end = s390_insn_mul_emit(buf, insn); 7061 break; 7062 7063 case S390_INSN_DIV: 7064 end = s390_insn_div_emit(buf, insn); 7065 break; 7066 7067 case S390_INSN_DIVS: 7068 end = s390_insn_divs_emit(buf, insn); 7069 break; 7070 7071 case S390_INSN_CLZ: 7072 end = s390_insn_clz_emit(buf, insn); 7073 break; 7074 7075 case S390_INSN_UNOP: 7076 end = s390_insn_unop_emit(buf, insn); 7077 break; 7078 7079 case S390_INSN_TEST: 7080 end = s390_insn_test_emit(buf, insn); 7081 break; 7082 7083 case S390_INSN_CC2BOOL: 7084 end = s390_insn_cc2bool_emit(buf, insn); 7085 break; 7086 7087 case S390_INSN_CAS: 7088 end = s390_insn_cas_emit(buf, insn); 7089 break; 7090 7091 case S390_INSN_COMPARE: 7092 end = s390_insn_compare_emit(buf, insn); 7093 break; 7094 7095 case S390_INSN_BRANCH: 7096 vassert(dispatch_unassisted == NULL); 7097 vassert(dispatch_assisted == NULL); 7098 end = s390_insn_branch_emit(buf, insn); 7099 break; 7100 7101 case S390_INSN_HELPER_CALL: 7102 end = s390_insn_helper_call_emit(buf, insn); 7103 break; 7104 7105 case S390_INSN_BFP_TRIOP: 7106 end = s390_insn_bfp_triop_emit(buf, insn); 7107 break; 7108 7109 case S390_INSN_BFP_BINOP: 7110 end = s390_insn_bfp_binop_emit(buf, insn); 7111 break; 7112 7113 case S390_INSN_BFP_UNOP: 7114 end = s390_insn_bfp_unop_emit(buf, insn); 7115 break; 7116 7117 case S390_INSN_BFP_COMPARE: 7118 end = s390_insn_bfp_compare_emit(buf, insn); 7119 break; 7120 7121 case S390_INSN_BFP128_BINOP: 7122 end = s390_insn_bfp128_binop_emit(buf, insn); 7123 break; 7124 7125 case S390_INSN_BFP128_COMPARE: 7126 end = s390_insn_bfp128_compare_emit(buf, insn); 7127 break; 7128 7129 case S390_INSN_BFP128_UNOP: 7130 end = s390_insn_bfp128_unop_emit(buf, insn); 7131 break; 7132 7133 case S390_INSN_BFP128_CONVERT_TO: 7134 end = s390_insn_bfp128_convert_to_emit(buf, insn); 7135 break; 7136 7137 case S390_INSN_BFP128_CONVERT_FROM: 7138 end = s390_insn_bfp128_convert_from_emit(buf, insn); 7139 break; 7140 7141 case S390_INSN_MFENCE: 7142 end = s390_insn_mfence_emit(buf, insn); 7143 break; 7144 7145 default: 7146 vpanic("s390_insn_emit"); 7147 } 7148 7149 vassert(end - buf <= nbuf); 7150 7151 return end - buf; 7152 } 7153 7154 7155 /*---------------------------------------------------------------*/ 7156 /*--- end host_s390_defs.c ---*/ 7157 /*---------------------------------------------------------------*/ 7158