1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*---------------------------------------------------------------*/ 4 /*--- begin host_s390_defs.h ---*/ 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 #ifndef __VEX_HOST_S390_DEFS_H 34 #define __VEX_HOST_S390_DEFS_H 35 36 #include "libvex_basictypes.h" /* Bool */ 37 #include "libvex.h" /* VexArchInfo */ 38 #include "main_util.h" /* needed for host_generic_regs.h */ 39 #include "host_generic_regs.h" /* HReg */ 40 41 /* --------- Registers --------- */ 42 const HChar *s390_hreg_as_string(HReg); 43 44 /* Dedicated registers */ 45 HReg s390_hreg_guest_state_pointer(void); 46 47 48 /* Given the index of a function argument, return the number of the 49 general purpose register in which it is being passed. Arguments are 50 counted 0, 1, 2, ... and they are being passed in r2, r3, r4, ... */ 51 static __inline__ unsigned 52 s390_gprno_from_arg_index(unsigned ix) 53 { 54 return ix + 2; 55 } 56 57 /* --------- Memory address expressions (amodes). --------- */ 58 59 /* These are the address modes: 60 (1) b12: base register + 12-bit unsigned offset (e.g. RS) 61 (2) b20: base register + 20-bit signed offset (e.g. RSY) 62 (3) bx12: base register + index register + 12-bit unsigned offset (e.g. RX) 63 (4) bx20: base register + index register + 20-bit signed offset (e.g. RXY) 64 fixs390: There is also pc-relative stuff.. e.g. LARL 65 */ 66 67 typedef enum { 68 S390_AMODE_B12, 69 S390_AMODE_B20, 70 S390_AMODE_BX12, 71 S390_AMODE_BX20 72 } s390_amode_t; 73 74 typedef struct { 75 s390_amode_t tag; 76 HReg b; 77 HReg x; /* hregNumber(x) == 0 for S390_AMODE_B12/B20 kinds */ 78 Int d; /* 12 bit unsigned or 20 bit signed */ 79 } s390_amode; 80 81 82 s390_amode *s390_amode_b12(Int d, HReg b); 83 s390_amode *s390_amode_b20(Int d, HReg b); 84 s390_amode *s390_amode_bx12(Int d, HReg b, HReg x); 85 s390_amode *s390_amode_bx20(Int d, HReg b, HReg x); 86 s390_amode *s390_amode_for_guest_state(Int d); 87 Bool s390_amode_is_sane(const s390_amode *); 88 89 const HChar *s390_amode_as_string(const s390_amode *); 90 91 /* ------------- 2nd (right) operand of binary operation ---------------- */ 92 93 typedef enum { 94 S390_OPND_REG, 95 S390_OPND_IMMEDIATE, 96 S390_OPND_AMODE 97 } s390_opnd_t; 98 99 100 /* Naming convention for operand locations: 101 R - GPR 102 I - immediate value 103 M - memory (any Amode may be used) 104 */ 105 106 /* An operand that is either in a GPR or is addressable via a BX20 amode */ 107 typedef struct { 108 s390_opnd_t tag; 109 union { 110 HReg reg; 111 s390_amode *am; 112 ULong imm; 113 } variant; 114 } s390_opnd_RMI; 115 116 117 /* The kind of instructions */ 118 typedef enum { 119 S390_INSN_LOAD, /* load register from memory */ 120 S390_INSN_STORE, /* store register to memory */ 121 S390_INSN_MOVE, /* from register to register */ 122 S390_INSN_COND_MOVE, /* conditonal "move" to register */ 123 S390_INSN_LOAD_IMMEDIATE, 124 S390_INSN_ALU, 125 S390_INSN_MUL, /* n-bit operands; 2n-bit result */ 126 S390_INSN_DIV, /* 2n-bit dividend; n-bit divisor; n-bit quot/rem */ 127 S390_INSN_DIVS, /* n-bit dividend; n-bit divisor; n-bit quot/rem */ 128 S390_INSN_CLZ, /* count left-most zeroes */ 129 S390_INSN_UNOP, 130 S390_INSN_TEST, /* test operand and set cc */ 131 S390_INSN_CC2BOOL,/* convert condition code to 0/1 */ 132 S390_INSN_COMPARE, 133 S390_INSN_HELPER_CALL, 134 S390_INSN_CAS, /* compare and swap */ 135 S390_INSN_CDAS, /* compare double and swap */ 136 S390_INSN_BFP_BINOP, /* Binary floating point 32-bit / 64-bit */ 137 S390_INSN_BFP_UNOP, 138 S390_INSN_BFP_TRIOP, 139 S390_INSN_BFP_COMPARE, 140 S390_INSN_BFP128_BINOP, /* Binary floating point 128-bit */ 141 S390_INSN_BFP128_UNOP, 142 S390_INSN_BFP128_COMPARE, 143 S390_INSN_BFP128_CONVERT_TO, 144 S390_INSN_BFP128_CONVERT_FROM, 145 S390_INSN_MFENCE, 146 S390_INSN_GZERO, /* Assign zero to a guest register */ 147 S390_INSN_GADD, /* Add a value to a guest register */ 148 /* The following 5 insns are mandated by translation chaining */ 149 S390_INSN_XDIRECT, /* direct transfer to guest address */ 150 S390_INSN_XINDIR, /* indirect transfer to guest address */ 151 S390_INSN_XASSISTED, /* assisted transfer to guest address */ 152 S390_INSN_EVCHECK, /* Event check */ 153 S390_INSN_PROFINC /* 64-bit profile counter increment */ 154 } s390_insn_tag; 155 156 157 /* The kind of ALU instructions */ 158 typedef enum { 159 S390_ALU_ADD, 160 S390_ALU_SUB, 161 S390_ALU_MUL, /* n-bit operands; result is lower n-bit of product */ 162 S390_ALU_AND, 163 S390_ALU_OR, 164 S390_ALU_XOR, 165 S390_ALU_LSH, 166 S390_ALU_RSH, 167 S390_ALU_RSHA /* arithmetic */ 168 } s390_alu_t; 169 170 171 /* The kind of unary integer operations */ 172 typedef enum { 173 S390_ZERO_EXTEND_8, 174 S390_ZERO_EXTEND_16, 175 S390_ZERO_EXTEND_32, 176 S390_SIGN_EXTEND_8, 177 S390_SIGN_EXTEND_16, 178 S390_SIGN_EXTEND_32, 179 S390_NEGATE 180 } s390_unop_t; 181 182 /* The kind of ternary BFP operations */ 183 typedef enum { 184 S390_BFP_MADD, 185 S390_BFP_MSUB, 186 } s390_bfp_triop_t; 187 188 /* The kind of binary BFP operations */ 189 typedef enum { 190 S390_BFP_ADD, 191 S390_BFP_SUB, 192 S390_BFP_MUL, 193 S390_BFP_DIV 194 } s390_bfp_binop_t; 195 196 197 /* The kind of unary BFP operations */ 198 typedef enum { 199 S390_BFP_ABS, 200 S390_BFP_NABS, 201 S390_BFP_NEG, 202 S390_BFP_SQRT, 203 S390_BFP_I32_TO_F32, 204 S390_BFP_I32_TO_F64, 205 S390_BFP_I32_TO_F128, 206 S390_BFP_I64_TO_F32, 207 S390_BFP_I64_TO_F64, 208 S390_BFP_I64_TO_F128, 209 S390_BFP_F32_TO_I32, 210 S390_BFP_F32_TO_I64, 211 S390_BFP_F32_TO_F64, 212 S390_BFP_F32_TO_F128, 213 S390_BFP_F64_TO_I32, 214 S390_BFP_F64_TO_I64, 215 S390_BFP_F64_TO_F32, 216 S390_BFP_F64_TO_F128, 217 S390_BFP_F128_TO_I32, 218 S390_BFP_F128_TO_I64, 219 S390_BFP_F128_TO_F32, 220 S390_BFP_F128_TO_F64 221 } s390_bfp_unop_t; 222 223 224 /* Condition code. The encoding of the enumerators matches the value of 225 the mask field in the various branch opcodes. */ 226 typedef enum { 227 S390_CC_NEVER= 0, 228 S390_CC_OVFL = 1, /* overflow */ 229 S390_CC_H = 2, /* A > B ; high */ 230 S390_CC_NLE = 3, /* not low or equal */ 231 S390_CC_L = 4, /* A < B ; low */ 232 S390_CC_NHE = 5, /* not high or equal */ 233 S390_CC_LH = 6, /* low or high */ 234 S390_CC_NE = 7, /* A != B ; not zero */ 235 S390_CC_E = 8, /* A == B ; zero */ 236 S390_CC_NLH = 9, /* not low or high */ 237 S390_CC_HE = 10, /* A >= B ; high or equal*/ 238 S390_CC_NL = 11, /* not low */ 239 S390_CC_LE = 12, /* A <= B ; low or equal */ 240 S390_CC_NH = 13, /* not high */ 241 S390_CC_NO = 14, /* not overflow */ 242 S390_CC_ALWAYS = 15 243 } s390_cc_t; 244 245 246 /* Rounding mode as it is encoded in the m3/m4 fields of certain 247 instructions (e.g. CFEBR) */ 248 typedef enum { 249 /* S390_ROUND_NEAREST_AWAY = 1, not supported */ 250 S390_ROUND_NEAREST_EVEN = 4, 251 S390_ROUND_ZERO = 5, 252 S390_ROUND_POSINF = 6, 253 S390_ROUND_NEGINF = 7 254 } s390_round_t; 255 256 257 /* Invert the condition code */ 258 static __inline__ s390_cc_t 259 s390_cc_invert(s390_cc_t cond) 260 { 261 return S390_CC_ALWAYS - cond; 262 } 263 264 265 typedef struct { 266 s390_insn_tag tag; 267 UChar size; /* size of the result in bytes */ 268 union { 269 struct { 270 HReg dst; 271 s390_amode *src; 272 } load; 273 struct { 274 s390_amode *dst; 275 HReg src; 276 } store; 277 struct { 278 HReg dst; 279 HReg src; 280 } move; 281 struct { 282 s390_cc_t cond; 283 HReg dst; 284 s390_opnd_RMI src; 285 } cond_move; 286 struct { 287 HReg dst; 288 ULong value; /* not sign extended */ 289 } load_immediate; 290 /* add, and, or, xor */ 291 struct { 292 s390_alu_t tag; 293 HReg dst; /* op1 */ 294 s390_opnd_RMI op2; 295 } alu; 296 struct { 297 Bool signed_multiply; 298 HReg dst_hi; /* r10 */ 299 HReg dst_lo; /* also op1 r11 */ 300 s390_opnd_RMI op2; 301 } mul; 302 struct { 303 Bool signed_divide; 304 HReg op1_hi; /* also remainder r10 */ 305 HReg op1_lo; /* also quotient r11 */ 306 s390_opnd_RMI op2; 307 } div; 308 struct { 309 HReg rem; /* remainder r10 */ 310 HReg op1; /* also quotient r11 */ 311 s390_opnd_RMI op2; 312 } divs; 313 struct { 314 HReg num_bits; /* number of leftmost '0' bits r10 */ 315 HReg clobber; /* unspecified r11 */ 316 s390_opnd_RMI src; 317 } clz; 318 struct { 319 s390_unop_t tag; 320 HReg dst; 321 s390_opnd_RMI src; 322 } unop; 323 struct { 324 Bool signed_comparison; 325 HReg src1; 326 s390_opnd_RMI src2; 327 } compare; 328 struct { 329 HReg dst; /* condition code in s390 encoding */ 330 HReg op1; 331 HReg op2; 332 } bfp_compare; 333 struct { 334 s390_opnd_RMI src; 335 } test; 336 /* Convert the condition code to a boolean value. */ 337 struct { 338 s390_cc_t cond; 339 HReg dst; 340 } cc2bool; 341 struct { 342 HReg op1; 343 s390_amode *op2; 344 HReg op3; 345 HReg old_mem; 346 } cas; 347 struct { 348 HReg op1_high; 349 HReg op1_low; 350 s390_amode *op2; 351 HReg op3_high; 352 HReg op3_low; 353 HReg old_mem_high; 354 HReg old_mem_low; 355 HReg scratch; 356 } cdas; 357 /* Pseudo-insn for representing a helper call. 358 TARGET is the absolute address of the helper function 359 NUM_ARGS says how many arguments are being passed. 360 All arguments have integer type and are being passed according to ABI, 361 i.e. in registers r2, r3, r4, r5, and r6, with argument #0 being 362 passed in r2 and so forth. */ 363 struct { 364 s390_cc_t cond; 365 Addr64 target; 366 UInt num_args; 367 HReg dst; /* if not INVALID_HREG, put return value here */ 368 HChar *name; /* callee's name (for debugging) */ 369 } helper_call; 370 struct { 371 s390_bfp_triop_t tag; 372 s390_round_t rounding_mode; 373 HReg dst; /* first operand */ 374 HReg op2; /* second operand */ 375 HReg op3; /* third operand */ 376 } bfp_triop; 377 struct { 378 s390_bfp_binop_t tag; 379 s390_round_t rounding_mode; 380 HReg dst; /* left operand */ 381 HReg op2; /* right operand */ 382 } bfp_binop; 383 struct { 384 s390_bfp_unop_t tag; 385 s390_round_t rounding_mode; 386 HReg dst; /* result */ 387 HReg op; /* operand */ 388 } bfp_unop; 389 struct { 390 s390_bfp_binop_t tag; 391 s390_round_t rounding_mode; 392 HReg dst_hi; /* left operand; high part */ 393 HReg dst_lo; /* left operand; low part */ 394 HReg op2_hi; /* right operand; high part */ 395 HReg op2_lo; /* right operand; low part */ 396 } bfp128_binop; 397 /* This variant is also used by the BFP128_CONVERT_TO and 398 BFP128_CONVERT_FROM insns. */ 399 struct { 400 s390_bfp_unop_t tag; 401 s390_round_t rounding_mode; 402 HReg dst_hi; /* result; high part */ 403 HReg dst_lo; /* result; low part */ 404 HReg op_hi; /* operand; high part */ 405 HReg op_lo; /* operand; low part */ 406 } bfp128_unop; 407 struct { 408 HReg dst; /* condition code in s390 encoding */ 409 HReg op1_hi; /* left operand; high part */ 410 HReg op1_lo; /* left operand; low part */ 411 HReg op2_hi; /* right operand; high part */ 412 HReg op2_lo; /* right operand; low part */ 413 } bfp128_compare; 414 struct { 415 UInt offset; 416 } gzero; 417 struct { 418 UInt offset; 419 UChar delta; 420 ULong value; /* for debugging only */ 421 } gadd; 422 423 /* The next 5 entries are generic to support translation chaining */ 424 425 /* Update the guest IA value, then exit requesting to chain 426 to it. May be conditional. */ 427 struct { 428 s390_cc_t cond; 429 Bool to_fast_entry; /* chain to the what entry point? */ 430 Addr64 dst; /* next guest address */ 431 s390_amode *guest_IA; 432 } xdirect; 433 /* Boring transfer to a guest address not known at JIT time. 434 Not chainable. May be conditional. */ 435 struct { 436 s390_cc_t cond; 437 HReg dst; 438 s390_amode *guest_IA; 439 } xindir; 440 /* Assisted transfer to a guest address, most general case. 441 Not chainable. May be conditional. */ 442 struct { 443 s390_cc_t cond; 444 IRJumpKind kind; 445 HReg dst; 446 s390_amode *guest_IA; 447 } xassisted; 448 struct { 449 /* fixs390: I don't think these are really needed 450 as the gsp and the offset are fixed no ? */ 451 s390_amode *counter; /* dispatch counter */ 452 s390_amode *fail_addr; 453 } evcheck; 454 struct { 455 /* No fields. The address of the counter to increment is 456 installed later, post-translation, by patching it in, 457 as it is not known at translation time. */ 458 } profinc; 459 460 } variant; 461 } s390_insn; 462 463 s390_insn *s390_insn_load(UChar size, HReg dst, s390_amode *src); 464 s390_insn *s390_insn_store(UChar size, s390_amode *dst, HReg src); 465 s390_insn *s390_insn_move(UChar size, HReg dst, HReg src); 466 s390_insn *s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst, 467 s390_opnd_RMI src); 468 s390_insn *s390_insn_load_immediate(UChar size, HReg dst, ULong val); 469 s390_insn *s390_insn_alu(UChar size, s390_alu_t, HReg dst, 470 s390_opnd_RMI op2); 471 s390_insn *s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo, 472 s390_opnd_RMI op2, Bool signed_multiply); 473 s390_insn *s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo, 474 s390_opnd_RMI op2, Bool signed_divide); 475 s390_insn *s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2); 476 s390_insn *s390_insn_clz(UChar size, HReg num_bits, HReg clobber, 477 s390_opnd_RMI op); 478 s390_insn *s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, 479 HReg old); 480 s390_insn *s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, 481 s390_amode *op2, HReg op3_high, HReg op3_low, 482 HReg old_high, HReg old_low, HReg scratch); 483 s390_insn *s390_insn_unop(UChar size, s390_unop_t tag, HReg dst, 484 s390_opnd_RMI opnd); 485 s390_insn *s390_insn_cc2bool(HReg dst, s390_cc_t src); 486 s390_insn *s390_insn_test(UChar size, s390_opnd_RMI src); 487 s390_insn *s390_insn_compare(UChar size, HReg dst, s390_opnd_RMI opnd, 488 Bool signed_comparison); 489 s390_insn *s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args, 490 HChar *name, HReg dst); 491 s390_insn *s390_insn_bfp_triop(UChar size, s390_bfp_triop_t, HReg dst, HReg op2, 492 HReg op3, s390_round_t); 493 s390_insn *s390_insn_bfp_binop(UChar size, s390_bfp_binop_t, HReg dst, HReg op2, 494 s390_round_t); 495 s390_insn *s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst, 496 HReg op, s390_round_t); 497 s390_insn *s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2); 498 s390_insn *s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t, HReg dst_hi, 499 HReg dst_lo, HReg op2_hi, HReg op2_lo, 500 s390_round_t); 501 s390_insn *s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t, HReg dst_hi, 502 HReg dst_lo, HReg op_hi, HReg op_lo, 503 s390_round_t); 504 s390_insn *s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi, 505 HReg op1_lo, HReg op2_hi, HReg op2_lo); 506 s390_insn *s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t, 507 HReg dst_hi, HReg dst_lo, HReg op); 508 s390_insn *s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t, 509 HReg dst, HReg op_hi, HReg op_lo, 510 s390_round_t); 511 s390_insn *s390_insn_mfence(void); 512 s390_insn *s390_insn_gzero(UChar size, UInt offset); 513 s390_insn *s390_insn_gadd(UChar size, UInt offset, UChar delta, ULong value); 514 515 /* Five for translation chaining */ 516 s390_insn *s390_insn_xdirect(s390_cc_t cond, Addr64 dst, s390_amode *guest_IA, 517 Bool to_fast_entry); 518 s390_insn *s390_insn_xindir(s390_cc_t cond, HReg dst, s390_amode *guest_IA); 519 s390_insn *s390_insn_xassisted(s390_cc_t cond, HReg dst, s390_amode *guest_IA, 520 IRJumpKind kind); 521 s390_insn *s390_insn_evcheck(s390_amode *counter, s390_amode *fail_addr); 522 s390_insn *s390_insn_profinc(void); 523 524 const HChar *s390_insn_as_string(const s390_insn *); 525 526 /*--------------------------------------------------------*/ 527 /* --- Interface exposed to VEX --- */ 528 /*--------------------------------------------------------*/ 529 530 void ppS390AMode(s390_amode *); 531 void ppS390Instr(s390_insn *, Bool mode64); 532 void ppHRegS390(HReg); 533 534 /* Some functions that insulate the register allocator from details 535 of the underlying instruction set. */ 536 void getRegUsage_S390Instr( HRegUsage *, s390_insn *, Bool ); 537 void mapRegs_S390Instr ( HRegRemap *, s390_insn *, Bool ); 538 Bool isMove_S390Instr ( s390_insn *, HReg *, HReg * ); 539 Int emit_S390Instr ( Bool *, UChar *, Int, s390_insn *, Bool, 540 void *, void *, void *, void *); 541 void getAllocableRegs_S390( Int *, HReg **, Bool ); 542 void genSpill_S390 ( HInstr **, HInstr **, HReg , Int , Bool ); 543 void genReload_S390 ( HInstr **, HInstr **, HReg , Int , Bool ); 544 s390_insn *directReload_S390 ( s390_insn *, HReg, Short ); 545 HInstrArray *iselSB_S390 ( IRSB *, VexArch, VexArchInfo *, VexAbiInfo *, 546 Int, Int, Bool, Bool, Addr64); 547 548 /* Return the number of bytes of code needed for an event check */ 549 Int evCheckSzB_S390(void); 550 551 /* Perform a chaining and unchaining of an XDirect jump. */ 552 VexInvalRange chainXDirect_S390(void *place_to_chain, 553 void *disp_cp_chain_me_EXPECTED, 554 void *place_to_jump_to); 555 556 VexInvalRange unchainXDirect_S390(void *place_to_unchain, 557 void *place_to_jump_to_EXPECTED, 558 void *disp_cp_chain_me); 559 560 /* Patch the counter location into an existing ProfInc point. */ 561 VexInvalRange patchProfInc_S390(void *code_to_patch, 562 ULong *location_of_counter); 563 564 /* KLUDGE: See detailled comment in host_s390_defs.c. */ 565 extern UInt s390_host_hwcaps; 566 567 /* Convenience macros to test installed facilities */ 568 #define s390_host_has_ldisp \ 569 (s390_host_hwcaps & (VEX_HWCAPS_S390X_LDISP)) 570 #define s390_host_has_eimm \ 571 (s390_host_hwcaps & (VEX_HWCAPS_S390X_EIMM)) 572 #define s390_host_has_gie \ 573 (s390_host_hwcaps & (VEX_HWCAPS_S390X_GIE)) 574 #define s390_host_has_dfp \ 575 (s390_host_hwcaps & (VEX_HWCAPS_S390X_DFP)) 576 #define s390_host_has_fgx \ 577 (s390_host_hwcaps & (VEX_HWCAPS_S390X_FGX)) 578 #define s390_host_has_etf2 \ 579 (s390_host_hwcaps & (VEX_HWCAPS_S390X_ETF2)) 580 #define s390_host_has_stfle \ 581 (s390_host_hwcaps & (VEX_HWCAPS_S390X_STFLE)) 582 #define s390_host_has_etf3 \ 583 (s390_host_hwcaps & (VEX_HWCAPS_S390X_ETF3)) 584 585 #endif /* ndef __VEX_HOST_S390_DEFS_H */ 586 587 /*---------------------------------------------------------------*/ 588 /*--- end host_s390_defs.h ---*/ 589 /*---------------------------------------------------------------*/ 590