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