1 /* 2 * S/390 translation 3 * 4 * Copyright (c) 2009 Ulrich Hecht 5 * Copyright (c) 2010 Alexander Graf 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 /* #define DEBUG_INLINE_BRANCHES */ 22 #define S390X_DEBUG_DISAS 23 /* #define S390X_DEBUG_DISAS_VERBOSE */ 24 25 #ifdef S390X_DEBUG_DISAS_VERBOSE 26 # define LOG_DISAS(...) qemu_log(__VA_ARGS__) 27 #else 28 # define LOG_DISAS(...) do { } while (0) 29 #endif 30 31 #include "qemu/osdep.h" 32 #include "cpu.h" 33 #include "s390x-internal.h" 34 #include "tcg/tcg-op.h" 35 #include "tcg/tcg-op-gvec.h" 36 #include "qemu/log.h" 37 #include "qemu/host-utils.h" 38 #include "exec/helper-proto.h" 39 #include "exec/helper-gen.h" 40 41 #include "exec/translator.h" 42 #include "exec/translation-block.h" 43 #include "exec/log.h" 44 #include "qemu/atomic128.h" 45 46 #define HELPER_H "helper.h" 47 #include "exec/helper-info.c.inc" 48 #undef HELPER_H 49 50 51 /* Information that (most) every instruction needs to manipulate. */ 52 typedef struct DisasContext DisasContext; 53 typedef struct DisasInsn DisasInsn; 54 typedef struct DisasFields DisasFields; 55 56 /* 57 * Define a structure to hold the decoded fields. We'll store each inside 58 * an array indexed by an enum. In order to conserve memory, we'll arrange 59 * for fields that do not exist at the same time to overlap, thus the "C" 60 * for compact. For checking purposes there is an "O" for original index 61 * as well that will be applied to availability bitmaps. 62 */ 63 64 enum DisasFieldIndexO { 65 FLD_O_r1, 66 FLD_O_r2, 67 FLD_O_r3, 68 FLD_O_m1, 69 FLD_O_m3, 70 FLD_O_m4, 71 FLD_O_m5, 72 FLD_O_m6, 73 FLD_O_b1, 74 FLD_O_b2, 75 FLD_O_b4, 76 FLD_O_d1, 77 FLD_O_d2, 78 FLD_O_d4, 79 FLD_O_x2, 80 FLD_O_l1, 81 FLD_O_l2, 82 FLD_O_i1, 83 FLD_O_i2, 84 FLD_O_i3, 85 FLD_O_i4, 86 FLD_O_i5, 87 FLD_O_v1, 88 FLD_O_v2, 89 FLD_O_v3, 90 FLD_O_v4, 91 }; 92 93 enum DisasFieldIndexC { 94 FLD_C_r1 = 0, 95 FLD_C_m1 = 0, 96 FLD_C_b1 = 0, 97 FLD_C_i1 = 0, 98 FLD_C_v1 = 0, 99 100 FLD_C_r2 = 1, 101 FLD_C_b2 = 1, 102 FLD_C_i2 = 1, 103 104 FLD_C_r3 = 2, 105 FLD_C_m3 = 2, 106 FLD_C_i3 = 2, 107 FLD_C_v3 = 2, 108 109 FLD_C_m4 = 3, 110 FLD_C_b4 = 3, 111 FLD_C_i4 = 3, 112 FLD_C_l1 = 3, 113 FLD_C_v4 = 3, 114 115 FLD_C_i5 = 4, 116 FLD_C_d1 = 4, 117 FLD_C_m5 = 4, 118 119 FLD_C_d2 = 5, 120 FLD_C_m6 = 5, 121 122 FLD_C_d4 = 6, 123 FLD_C_x2 = 6, 124 FLD_C_l2 = 6, 125 FLD_C_v2 = 6, 126 127 NUM_C_FIELD = 7 128 }; 129 130 struct DisasFields { 131 uint64_t raw_insn; 132 unsigned op:8; 133 unsigned op2:8; 134 unsigned presentC:16; 135 unsigned int presentO; 136 int c[NUM_C_FIELD]; 137 }; 138 139 struct DisasContext { 140 DisasContextBase base; 141 const DisasInsn *insn; 142 DisasFields fields; 143 uint64_t ex_value; 144 /* 145 * During translate_one(), pc_tmp is used to determine the instruction 146 * to be executed after base.pc_next - e.g. next sequential instruction 147 * or a branch target. 148 */ 149 uint64_t pc_tmp; 150 uint32_t ilen; 151 enum cc_op cc_op; 152 bool exit_to_mainloop; 153 }; 154 155 /* Information carried about a condition to be evaluated. */ 156 typedef struct { 157 TCGCond cond:8; 158 bool is_64; 159 union { 160 struct { TCGv_i64 a, b; } s64; 161 struct { TCGv_i32 a, b; } s32; 162 } u; 163 } DisasCompare; 164 165 #ifdef DEBUG_INLINE_BRANCHES 166 static uint64_t inline_branch_hit[CC_OP_MAX]; 167 static uint64_t inline_branch_miss[CC_OP_MAX]; 168 #endif 169 170 static void pc_to_link_info(TCGv_i64 out, DisasContext *s, uint64_t pc) 171 { 172 if (s->base.tb->flags & FLAG_MASK_32) { 173 if (s->base.tb->flags & FLAG_MASK_64) { 174 tcg_gen_movi_i64(out, pc); 175 return; 176 } 177 pc |= 0x80000000; 178 } 179 assert(!(s->base.tb->flags & FLAG_MASK_64)); 180 tcg_gen_deposit_i64(out, out, tcg_constant_i64(pc), 0, 32); 181 } 182 183 static TCGv_i64 psw_addr; 184 static TCGv_i64 psw_mask; 185 static TCGv_i64 gbea; 186 187 static TCGv_i32 cc_op; 188 static TCGv_i64 cc_src; 189 static TCGv_i64 cc_dst; 190 static TCGv_i64 cc_vr; 191 192 static char cpu_reg_names[16][4]; 193 static TCGv_i64 regs[16]; 194 195 void s390x_translate_init(void) 196 { 197 int i; 198 199 psw_addr = tcg_global_mem_new_i64(tcg_env, 200 offsetof(CPUS390XState, psw.addr), 201 "psw_addr"); 202 psw_mask = tcg_global_mem_new_i64(tcg_env, 203 offsetof(CPUS390XState, psw.mask), 204 "psw_mask"); 205 gbea = tcg_global_mem_new_i64(tcg_env, 206 offsetof(CPUS390XState, gbea), 207 "gbea"); 208 209 cc_op = tcg_global_mem_new_i32(tcg_env, offsetof(CPUS390XState, cc_op), 210 "cc_op"); 211 cc_src = tcg_global_mem_new_i64(tcg_env, offsetof(CPUS390XState, cc_src), 212 "cc_src"); 213 cc_dst = tcg_global_mem_new_i64(tcg_env, offsetof(CPUS390XState, cc_dst), 214 "cc_dst"); 215 cc_vr = tcg_global_mem_new_i64(tcg_env, offsetof(CPUS390XState, cc_vr), 216 "cc_vr"); 217 218 for (i = 0; i < 16; i++) { 219 snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i); 220 regs[i] = tcg_global_mem_new(tcg_env, 221 offsetof(CPUS390XState, regs[i]), 222 cpu_reg_names[i]); 223 } 224 } 225 226 static inline int vec_full_reg_offset(uint8_t reg) 227 { 228 g_assert(reg < 32); 229 return offsetof(CPUS390XState, vregs[reg][0]); 230 } 231 232 static inline int vec_reg_offset(uint8_t reg, uint8_t enr, MemOp es) 233 { 234 /* Convert element size (es) - e.g. MO_8 - to bytes */ 235 const uint8_t bytes = 1 << es; 236 int offs = enr * bytes; 237 238 /* 239 * vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte 240 * of the 16 byte vector, on both, little and big endian systems. 241 * 242 * Big Endian (target/possible host) 243 * B: [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15] 244 * HW: [ 0][ 1][ 2][ 3] - [ 4][ 5][ 6][ 7] 245 * W: [ 0][ 1] - [ 2][ 3] 246 * DW: [ 0] - [ 1] 247 * 248 * Little Endian (possible host) 249 * B: [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8] 250 * HW: [ 3][ 2][ 1][ 0] - [ 7][ 6][ 5][ 4] 251 * W: [ 1][ 0] - [ 3][ 2] 252 * DW: [ 0] - [ 1] 253 * 254 * For 16 byte elements, the two 8 byte halves will not form a host 255 * int128 if the host is little endian, since they're in the wrong order. 256 * Some operations (e.g. xor) do not care. For operations like addition, 257 * the two 8 byte elements have to be loaded separately. Let's force all 258 * 16 byte operations to handle it in a special way. 259 */ 260 g_assert(es <= MO_64); 261 #if !HOST_BIG_ENDIAN 262 offs ^= (8 - bytes); 263 #endif 264 return offs + vec_full_reg_offset(reg); 265 } 266 267 static inline int freg64_offset(uint8_t reg) 268 { 269 g_assert(reg < 16); 270 return vec_reg_offset(reg, 0, MO_64); 271 } 272 273 static inline int freg32_offset(uint8_t reg) 274 { 275 g_assert(reg < 16); 276 return vec_reg_offset(reg, 0, MO_32); 277 } 278 279 static TCGv_i64 load_reg(int reg) 280 { 281 TCGv_i64 r = tcg_temp_new_i64(); 282 tcg_gen_mov_i64(r, regs[reg]); 283 return r; 284 } 285 286 static TCGv_i64 load_freg(int reg) 287 { 288 TCGv_i64 r = tcg_temp_new_i64(); 289 290 tcg_gen_ld_i64(r, tcg_env, freg64_offset(reg)); 291 return r; 292 } 293 294 static TCGv_i64 load_freg32_i64(int reg) 295 { 296 TCGv_i64 r = tcg_temp_new_i64(); 297 298 tcg_gen_ld32u_i64(r, tcg_env, freg32_offset(reg)); 299 return r; 300 } 301 302 static TCGv_i128 load_freg_128(int reg) 303 { 304 TCGv_i64 h = load_freg(reg); 305 TCGv_i64 l = load_freg(reg + 2); 306 TCGv_i128 r = tcg_temp_new_i128(); 307 308 tcg_gen_concat_i64_i128(r, l, h); 309 return r; 310 } 311 312 static void store_reg(int reg, TCGv_i64 v) 313 { 314 tcg_gen_mov_i64(regs[reg], v); 315 } 316 317 static void store_freg(int reg, TCGv_i64 v) 318 { 319 tcg_gen_st_i64(v, tcg_env, freg64_offset(reg)); 320 } 321 322 static void store_reg32_i64(int reg, TCGv_i64 v) 323 { 324 /* 32 bit register writes keep the upper half */ 325 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32); 326 } 327 328 static void store_reg32h_i64(int reg, TCGv_i64 v) 329 { 330 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32); 331 } 332 333 static void store_freg32_i64(int reg, TCGv_i64 v) 334 { 335 tcg_gen_st32_i64(v, tcg_env, freg32_offset(reg)); 336 } 337 338 static void update_psw_addr(DisasContext *s) 339 { 340 /* psw.addr */ 341 tcg_gen_movi_i64(psw_addr, s->base.pc_next); 342 } 343 344 static void per_branch(DisasContext *s, TCGv_i64 dest) 345 { 346 #ifndef CONFIG_USER_ONLY 347 if (s->base.tb->flags & FLAG_MASK_PER_BRANCH) { 348 gen_helper_per_branch(tcg_env, dest, tcg_constant_i32(s->ilen)); 349 } 350 #endif 351 } 352 353 static void per_breaking_event(DisasContext *s) 354 { 355 tcg_gen_movi_i64(gbea, s->base.pc_next); 356 } 357 358 static void update_cc_op(DisasContext *s) 359 { 360 if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) { 361 tcg_gen_movi_i32(cc_op, s->cc_op); 362 } 363 } 364 365 static inline uint64_t ld_code2(CPUS390XState *env, DisasContext *s, 366 uint64_t pc) 367 { 368 return (uint64_t)translator_lduw(env, &s->base, pc); 369 } 370 371 static inline uint64_t ld_code4(CPUS390XState *env, DisasContext *s, 372 uint64_t pc) 373 { 374 return (uint64_t)(uint32_t)translator_ldl(env, &s->base, pc); 375 } 376 377 static int get_mem_index(DisasContext *s) 378 { 379 #ifdef CONFIG_USER_ONLY 380 return MMU_USER_IDX; 381 #else 382 if (!(s->base.tb->flags & FLAG_MASK_DAT)) { 383 return MMU_REAL_IDX; 384 } 385 386 switch (s->base.tb->flags & FLAG_MASK_ASC) { 387 case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT: 388 return MMU_PRIMARY_IDX; 389 case PSW_ASC_SECONDARY >> FLAG_MASK_PSW_SHIFT: 390 return MMU_SECONDARY_IDX; 391 case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT: 392 return MMU_HOME_IDX; 393 default: 394 g_assert_not_reached(); 395 } 396 #endif 397 } 398 399 static void gen_exception(int excp) 400 { 401 gen_helper_exception(tcg_env, tcg_constant_i32(excp)); 402 } 403 404 static void gen_program_exception(DisasContext *s, int code) 405 { 406 /* Remember what pgm exception this was. */ 407 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env, 408 offsetof(CPUS390XState, int_pgm_code)); 409 410 tcg_gen_st_i32(tcg_constant_i32(s->ilen), tcg_env, 411 offsetof(CPUS390XState, int_pgm_ilen)); 412 413 /* update the psw */ 414 update_psw_addr(s); 415 416 /* Save off cc. */ 417 update_cc_op(s); 418 419 /* Trigger exception. */ 420 gen_exception(EXCP_PGM); 421 } 422 423 static inline void gen_illegal_opcode(DisasContext *s) 424 { 425 gen_program_exception(s, PGM_OPERATION); 426 } 427 428 static inline void gen_data_exception(uint8_t dxc) 429 { 430 gen_helper_data_exception(tcg_env, tcg_constant_i32(dxc)); 431 } 432 433 static inline void gen_trap(DisasContext *s) 434 { 435 /* Set DXC to 0xff */ 436 gen_data_exception(0xff); 437 } 438 439 static void gen_addi_and_wrap_i64(DisasContext *s, TCGv_i64 dst, TCGv_i64 src, 440 int64_t imm) 441 { 442 tcg_gen_addi_i64(dst, src, imm); 443 if (!(s->base.tb->flags & FLAG_MASK_64)) { 444 if (s->base.tb->flags & FLAG_MASK_32) { 445 tcg_gen_andi_i64(dst, dst, 0x7fffffff); 446 } else { 447 tcg_gen_andi_i64(dst, dst, 0x00ffffff); 448 } 449 } 450 } 451 452 static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2) 453 { 454 TCGv_i64 tmp = tcg_temp_new_i64(); 455 456 /* 457 * Note that d2 is limited to 20 bits, signed. If we crop negative 458 * displacements early we create larger immediate addends. 459 */ 460 if (b2 && x2) { 461 tcg_gen_add_i64(tmp, regs[b2], regs[x2]); 462 gen_addi_and_wrap_i64(s, tmp, tmp, d2); 463 } else if (b2) { 464 gen_addi_and_wrap_i64(s, tmp, regs[b2], d2); 465 } else if (x2) { 466 gen_addi_and_wrap_i64(s, tmp, regs[x2], d2); 467 } else if (!(s->base.tb->flags & FLAG_MASK_64)) { 468 if (s->base.tb->flags & FLAG_MASK_32) { 469 tcg_gen_movi_i64(tmp, d2 & 0x7fffffff); 470 } else { 471 tcg_gen_movi_i64(tmp, d2 & 0x00ffffff); 472 } 473 } else { 474 tcg_gen_movi_i64(tmp, d2); 475 } 476 477 return tmp; 478 } 479 480 static inline bool live_cc_data(DisasContext *s) 481 { 482 return (s->cc_op != CC_OP_DYNAMIC 483 && s->cc_op != CC_OP_STATIC 484 && s->cc_op > 3); 485 } 486 487 static inline void gen_op_movi_cc(DisasContext *s, uint32_t val) 488 { 489 if (live_cc_data(s)) { 490 tcg_gen_discard_i64(cc_src); 491 tcg_gen_discard_i64(cc_dst); 492 tcg_gen_discard_i64(cc_vr); 493 } 494 s->cc_op = CC_OP_CONST0 + val; 495 } 496 497 static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst) 498 { 499 if (live_cc_data(s)) { 500 tcg_gen_discard_i64(cc_src); 501 tcg_gen_discard_i64(cc_vr); 502 } 503 tcg_gen_mov_i64(cc_dst, dst); 504 s->cc_op = op; 505 } 506 507 static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src, 508 TCGv_i64 dst) 509 { 510 if (live_cc_data(s)) { 511 tcg_gen_discard_i64(cc_vr); 512 } 513 tcg_gen_mov_i64(cc_src, src); 514 tcg_gen_mov_i64(cc_dst, dst); 515 s->cc_op = op; 516 } 517 518 static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src, 519 TCGv_i64 dst, TCGv_i64 vr) 520 { 521 tcg_gen_mov_i64(cc_src, src); 522 tcg_gen_mov_i64(cc_dst, dst); 523 tcg_gen_mov_i64(cc_vr, vr); 524 s->cc_op = op; 525 } 526 527 static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val) 528 { 529 gen_op_update1_cc_i64(s, CC_OP_NZ, val); 530 } 531 532 /* CC value is in env->cc_op */ 533 static void set_cc_static(DisasContext *s) 534 { 535 if (live_cc_data(s)) { 536 tcg_gen_discard_i64(cc_src); 537 tcg_gen_discard_i64(cc_dst); 538 tcg_gen_discard_i64(cc_vr); 539 } 540 s->cc_op = CC_OP_STATIC; 541 } 542 543 /* calculates cc into cc_op */ 544 static void gen_op_calc_cc(DisasContext *s) 545 { 546 TCGv_i32 local_cc_op = NULL; 547 TCGv_i64 dummy = NULL; 548 549 switch (s->cc_op) { 550 default: 551 dummy = tcg_constant_i64(0); 552 /* FALLTHRU */ 553 case CC_OP_ADD_64: 554 case CC_OP_SUB_64: 555 case CC_OP_ADD_32: 556 case CC_OP_SUB_32: 557 local_cc_op = tcg_constant_i32(s->cc_op); 558 break; 559 case CC_OP_CONST0: 560 case CC_OP_CONST1: 561 case CC_OP_CONST2: 562 case CC_OP_CONST3: 563 case CC_OP_STATIC: 564 case CC_OP_DYNAMIC: 565 break; 566 } 567 568 switch (s->cc_op) { 569 case CC_OP_CONST0: 570 case CC_OP_CONST1: 571 case CC_OP_CONST2: 572 case CC_OP_CONST3: 573 /* s->cc_op is the cc value */ 574 tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0); 575 break; 576 case CC_OP_STATIC: 577 /* env->cc_op already is the cc value */ 578 break; 579 case CC_OP_NZ: 580 tcg_gen_setcondi_i64(TCG_COND_NE, cc_dst, cc_dst, 0); 581 tcg_gen_extrl_i64_i32(cc_op, cc_dst); 582 break; 583 case CC_OP_ABS_64: 584 case CC_OP_NABS_64: 585 case CC_OP_ABS_32: 586 case CC_OP_NABS_32: 587 case CC_OP_LTGT0_32: 588 case CC_OP_LTGT0_64: 589 case CC_OP_COMP_32: 590 case CC_OP_COMP_64: 591 case CC_OP_NZ_F32: 592 case CC_OP_NZ_F64: 593 case CC_OP_FLOGR: 594 case CC_OP_LCBB: 595 case CC_OP_MULS_32: 596 /* 1 argument */ 597 gen_helper_calc_cc(cc_op, tcg_env, local_cc_op, dummy, cc_dst, dummy); 598 break; 599 case CC_OP_ADDU: 600 case CC_OP_ICM: 601 case CC_OP_LTGT_32: 602 case CC_OP_LTGT_64: 603 case CC_OP_LTUGTU_32: 604 case CC_OP_LTUGTU_64: 605 case CC_OP_TM_32: 606 case CC_OP_TM_64: 607 case CC_OP_SLA: 608 case CC_OP_SUBU: 609 case CC_OP_NZ_F128: 610 case CC_OP_VC: 611 case CC_OP_MULS_64: 612 /* 2 arguments */ 613 gen_helper_calc_cc(cc_op, tcg_env, local_cc_op, cc_src, cc_dst, dummy); 614 break; 615 case CC_OP_ADD_64: 616 case CC_OP_SUB_64: 617 case CC_OP_ADD_32: 618 case CC_OP_SUB_32: 619 /* 3 arguments */ 620 gen_helper_calc_cc(cc_op, tcg_env, local_cc_op, cc_src, cc_dst, cc_vr); 621 break; 622 case CC_OP_DYNAMIC: 623 /* unknown operation - assume 3 arguments and cc_op in env */ 624 gen_helper_calc_cc(cc_op, tcg_env, cc_op, cc_src, cc_dst, cc_vr); 625 break; 626 default: 627 g_assert_not_reached(); 628 } 629 630 /* We now have cc in cc_op as constant */ 631 set_cc_static(s); 632 } 633 634 static bool use_goto_tb(DisasContext *s, uint64_t dest) 635 { 636 return translator_use_goto_tb(&s->base, dest); 637 } 638 639 static void account_noninline_branch(DisasContext *s, int cc_op) 640 { 641 #ifdef DEBUG_INLINE_BRANCHES 642 inline_branch_miss[cc_op]++; 643 #endif 644 } 645 646 static void account_inline_branch(DisasContext *s, int cc_op) 647 { 648 #ifdef DEBUG_INLINE_BRANCHES 649 inline_branch_hit[cc_op]++; 650 #endif 651 } 652 653 /* Table of mask values to comparison codes, given a comparison as input. 654 For such, CC=3 should not be possible. */ 655 static const TCGCond ltgt_cond[16] = { 656 TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */ 657 TCG_COND_GT, TCG_COND_GT, /* | | GT | x */ 658 TCG_COND_LT, TCG_COND_LT, /* | LT | | x */ 659 TCG_COND_NE, TCG_COND_NE, /* | LT | GT | x */ 660 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | | x */ 661 TCG_COND_GE, TCG_COND_GE, /* EQ | | GT | x */ 662 TCG_COND_LE, TCG_COND_LE, /* EQ | LT | | x */ 663 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */ 664 }; 665 666 /* Table of mask values to comparison codes, given a logic op as input. 667 For such, only CC=0 and CC=1 should be possible. */ 668 static const TCGCond nz_cond[16] = { 669 TCG_COND_NEVER, TCG_COND_NEVER, /* | | x | x */ 670 TCG_COND_NEVER, TCG_COND_NEVER, 671 TCG_COND_NE, TCG_COND_NE, /* | NE | x | x */ 672 TCG_COND_NE, TCG_COND_NE, 673 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | x | x */ 674 TCG_COND_EQ, TCG_COND_EQ, 675 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | NE | x | x */ 676 TCG_COND_ALWAYS, TCG_COND_ALWAYS, 677 }; 678 679 /* Interpret MASK in terms of S->CC_OP, and fill in C with all the 680 details required to generate a TCG comparison. */ 681 static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask) 682 { 683 TCGCond cond; 684 enum cc_op old_cc_op = s->cc_op; 685 686 if (mask == 15 || mask == 0) { 687 c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER); 688 c->u.s32.a = cc_op; 689 c->u.s32.b = cc_op; 690 c->is_64 = false; 691 return; 692 } 693 694 /* Find the TCG condition for the mask + cc op. */ 695 switch (old_cc_op) { 696 case CC_OP_LTGT0_32: 697 case CC_OP_LTGT0_64: 698 case CC_OP_LTGT_32: 699 case CC_OP_LTGT_64: 700 cond = ltgt_cond[mask]; 701 if (cond == TCG_COND_NEVER) { 702 goto do_dynamic; 703 } 704 account_inline_branch(s, old_cc_op); 705 break; 706 707 case CC_OP_LTUGTU_32: 708 case CC_OP_LTUGTU_64: 709 cond = tcg_unsigned_cond(ltgt_cond[mask]); 710 if (cond == TCG_COND_NEVER) { 711 goto do_dynamic; 712 } 713 account_inline_branch(s, old_cc_op); 714 break; 715 716 case CC_OP_NZ: 717 cond = nz_cond[mask]; 718 if (cond == TCG_COND_NEVER) { 719 goto do_dynamic; 720 } 721 account_inline_branch(s, old_cc_op); 722 break; 723 724 case CC_OP_TM_32: 725 case CC_OP_TM_64: 726 switch (mask) { 727 case 8: 728 cond = TCG_COND_TSTEQ; 729 break; 730 case 4 | 2 | 1: 731 cond = TCG_COND_TSTNE; 732 break; 733 default: 734 goto do_dynamic; 735 } 736 account_inline_branch(s, old_cc_op); 737 break; 738 739 case CC_OP_ICM: 740 switch (mask) { 741 case 8: 742 cond = TCG_COND_TSTEQ; 743 break; 744 case 4 | 2 | 1: 745 case 4 | 2: 746 cond = TCG_COND_TSTNE; 747 break; 748 default: 749 goto do_dynamic; 750 } 751 account_inline_branch(s, old_cc_op); 752 break; 753 754 case CC_OP_FLOGR: 755 switch (mask & 0xa) { 756 case 8: /* src == 0 -> no one bit found */ 757 cond = TCG_COND_EQ; 758 break; 759 case 2: /* src != 0 -> one bit found */ 760 cond = TCG_COND_NE; 761 break; 762 default: 763 goto do_dynamic; 764 } 765 account_inline_branch(s, old_cc_op); 766 break; 767 768 case CC_OP_ADDU: 769 case CC_OP_SUBU: 770 switch (mask) { 771 case 8 | 2: /* result == 0 */ 772 cond = TCG_COND_EQ; 773 break; 774 case 4 | 1: /* result != 0 */ 775 cond = TCG_COND_NE; 776 break; 777 case 8 | 4: /* !carry (borrow) */ 778 cond = old_cc_op == CC_OP_ADDU ? TCG_COND_EQ : TCG_COND_NE; 779 break; 780 case 2 | 1: /* carry (!borrow) */ 781 cond = old_cc_op == CC_OP_ADDU ? TCG_COND_NE : TCG_COND_EQ; 782 break; 783 default: 784 goto do_dynamic; 785 } 786 account_inline_branch(s, old_cc_op); 787 break; 788 789 default: 790 do_dynamic: 791 /* Calculate cc value. */ 792 gen_op_calc_cc(s); 793 /* FALLTHRU */ 794 795 case CC_OP_STATIC: 796 /* Jump based on CC. We'll load up the real cond below; 797 the assignment here merely avoids a compiler warning. */ 798 account_noninline_branch(s, old_cc_op); 799 old_cc_op = CC_OP_STATIC; 800 cond = TCG_COND_NEVER; 801 break; 802 } 803 804 /* Load up the arguments of the comparison. */ 805 c->is_64 = true; 806 switch (old_cc_op) { 807 case CC_OP_LTGT0_32: 808 c->is_64 = false; 809 c->u.s32.a = tcg_temp_new_i32(); 810 tcg_gen_extrl_i64_i32(c->u.s32.a, cc_dst); 811 c->u.s32.b = tcg_constant_i32(0); 812 break; 813 case CC_OP_LTGT_32: 814 case CC_OP_LTUGTU_32: 815 c->is_64 = false; 816 c->u.s32.a = tcg_temp_new_i32(); 817 tcg_gen_extrl_i64_i32(c->u.s32.a, cc_src); 818 c->u.s32.b = tcg_temp_new_i32(); 819 tcg_gen_extrl_i64_i32(c->u.s32.b, cc_dst); 820 break; 821 822 case CC_OP_LTGT0_64: 823 case CC_OP_NZ: 824 case CC_OP_FLOGR: 825 c->u.s64.a = cc_dst; 826 c->u.s64.b = tcg_constant_i64(0); 827 break; 828 829 case CC_OP_LTGT_64: 830 case CC_OP_LTUGTU_64: 831 case CC_OP_TM_32: 832 case CC_OP_TM_64: 833 case CC_OP_ICM: 834 c->u.s64.a = cc_src; 835 c->u.s64.b = cc_dst; 836 break; 837 838 case CC_OP_ADDU: 839 case CC_OP_SUBU: 840 c->is_64 = true; 841 c->u.s64.b = tcg_constant_i64(0); 842 switch (mask) { 843 case 8 | 2: 844 case 4 | 1: /* result */ 845 c->u.s64.a = cc_dst; 846 break; 847 case 8 | 4: 848 case 2 | 1: /* carry */ 849 c->u.s64.a = cc_src; 850 break; 851 default: 852 g_assert_not_reached(); 853 } 854 break; 855 856 case CC_OP_STATIC: 857 c->is_64 = false; 858 c->u.s32.a = cc_op; 859 860 /* Fold half of the cases using bit 3 to invert. */ 861 switch (mask & 8 ? mask ^ 0xf : mask) { 862 case 0x1: /* cc == 3 */ 863 cond = TCG_COND_EQ; 864 c->u.s32.b = tcg_constant_i32(3); 865 break; 866 case 0x2: /* cc == 2 */ 867 cond = TCG_COND_EQ; 868 c->u.s32.b = tcg_constant_i32(2); 869 break; 870 case 0x4: /* cc == 1 */ 871 cond = TCG_COND_EQ; 872 c->u.s32.b = tcg_constant_i32(1); 873 break; 874 case 0x2 | 0x1: /* cc == 2 || cc == 3 => cc > 1 */ 875 cond = TCG_COND_GTU; 876 c->u.s32.b = tcg_constant_i32(1); 877 break; 878 case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */ 879 cond = TCG_COND_TSTNE; 880 c->u.s32.b = tcg_constant_i32(1); 881 break; 882 case 0x4 | 0x2: /* cc == 1 || cc == 2 => (cc - 1) <= 1 */ 883 cond = TCG_COND_LEU; 884 c->u.s32.a = tcg_temp_new_i32(); 885 c->u.s32.b = tcg_constant_i32(1); 886 tcg_gen_addi_i32(c->u.s32.a, cc_op, -1); 887 break; 888 case 0x4 | 0x2 | 0x1: /* cc != 0 */ 889 cond = TCG_COND_NE; 890 c->u.s32.b = tcg_constant_i32(0); 891 break; 892 default: 893 /* case 0: never, handled above. */ 894 g_assert_not_reached(); 895 } 896 if (mask & 8) { 897 cond = tcg_invert_cond(cond); 898 } 899 break; 900 901 default: 902 abort(); 903 } 904 c->cond = cond; 905 } 906 907 /* ====================================================================== */ 908 /* Define the insn format enumeration. */ 909 #define F0(N) FMT_##N, 910 #define F1(N, X1) F0(N) 911 #define F2(N, X1, X2) F0(N) 912 #define F3(N, X1, X2, X3) F0(N) 913 #define F4(N, X1, X2, X3, X4) F0(N) 914 #define F5(N, X1, X2, X3, X4, X5) F0(N) 915 #define F6(N, X1, X2, X3, X4, X5, X6) F0(N) 916 917 typedef enum { 918 #include "insn-format.h.inc" 919 } DisasFormat; 920 921 #undef F0 922 #undef F1 923 #undef F2 924 #undef F3 925 #undef F4 926 #undef F5 927 #undef F6 928 929 /* This is the way fields are to be accessed out of DisasFields. */ 930 #define have_field(S, F) have_field1((S), FLD_O_##F) 931 #define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F) 932 933 static bool have_field1(const DisasContext *s, enum DisasFieldIndexO c) 934 { 935 return (s->fields.presentO >> c) & 1; 936 } 937 938 static int get_field1(const DisasContext *s, enum DisasFieldIndexO o, 939 enum DisasFieldIndexC c) 940 { 941 assert(have_field1(s, o)); 942 return s->fields.c[c]; 943 } 944 945 /* Describe the layout of each field in each format. */ 946 typedef struct DisasField { 947 unsigned int beg:8; 948 unsigned int size:8; 949 unsigned int type:2; 950 unsigned int indexC:6; 951 enum DisasFieldIndexO indexO:8; 952 } DisasField; 953 954 typedef struct DisasFormatInfo { 955 DisasField op[NUM_C_FIELD]; 956 } DisasFormatInfo; 957 958 #define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N } 959 #define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N } 960 #define V(N, B) { B, 4, 3, FLD_C_v##N, FLD_O_v##N } 961 #define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \ 962 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N } 963 #define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \ 964 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \ 965 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N } 966 #define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \ 967 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N } 968 #define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \ 969 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \ 970 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N } 971 #define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N } 972 #define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N } 973 974 #define F0(N) { { } }, 975 #define F1(N, X1) { { X1 } }, 976 #define F2(N, X1, X2) { { X1, X2 } }, 977 #define F3(N, X1, X2, X3) { { X1, X2, X3 } }, 978 #define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } }, 979 #define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } }, 980 #define F6(N, X1, X2, X3, X4, X5, X6) { { X1, X2, X3, X4, X5, X6 } }, 981 982 static const DisasFormatInfo format_info[] = { 983 #include "insn-format.h.inc" 984 }; 985 986 #undef F0 987 #undef F1 988 #undef F2 989 #undef F3 990 #undef F4 991 #undef F5 992 #undef F6 993 #undef R 994 #undef M 995 #undef V 996 #undef BD 997 #undef BXD 998 #undef BDL 999 #undef BXDL 1000 #undef I 1001 #undef L 1002 1003 /* Generally, we'll extract operands into this structures, operate upon 1004 them, and store them back. See the "in1", "in2", "prep", "wout" sets 1005 of routines below for more details. */ 1006 typedef struct { 1007 TCGv_i64 out, out2, in1, in2; 1008 TCGv_i64 addr1; 1009 TCGv_i128 out_128, in1_128, in2_128; 1010 } DisasOps; 1011 1012 /* Instructions can place constraints on their operands, raising specification 1013 exceptions if they are violated. To make this easy to automate, each "in1", 1014 "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one 1015 of the following, or 0. To make this easy to document, we'll put the 1016 SPEC_<name> defines next to <name>. */ 1017 1018 #define SPEC_r1_even 1 1019 #define SPEC_r2_even 2 1020 #define SPEC_r3_even 4 1021 #define SPEC_r1_f128 8 1022 #define SPEC_r2_f128 16 1023 1024 /* Return values from translate_one, indicating the state of the TB. */ 1025 1026 /* We are not using a goto_tb (for whatever reason), but have updated 1027 the PC (for whatever reason), so there's no need to do it again on 1028 exiting the TB. */ 1029 #define DISAS_PC_UPDATED DISAS_TARGET_0 1030 1031 /* We have updated the PC and CC values. */ 1032 #define DISAS_PC_CC_UPDATED DISAS_TARGET_2 1033 1034 1035 /* Instruction flags */ 1036 #define IF_AFP1 0x0001 /* r1 is a fp reg for HFP/FPS instructions */ 1037 #define IF_AFP2 0x0002 /* r2 is a fp reg for HFP/FPS instructions */ 1038 #define IF_AFP3 0x0004 /* r3 is a fp reg for HFP/FPS instructions */ 1039 #define IF_BFP 0x0008 /* binary floating point instruction */ 1040 #define IF_DFP 0x0010 /* decimal floating point instruction */ 1041 #define IF_PRIV 0x0020 /* privileged instruction */ 1042 #define IF_VEC 0x0040 /* vector instruction */ 1043 #define IF_IO 0x0080 /* input/output instruction */ 1044 1045 struct DisasInsn { 1046 unsigned opc:16; 1047 unsigned flags:16; 1048 DisasFormat fmt:8; 1049 unsigned fac:8; 1050 unsigned spec:8; 1051 1052 const char *name; 1053 1054 /* Pre-process arguments before HELP_OP. */ 1055 void (*help_in1)(DisasContext *, DisasOps *); 1056 void (*help_in2)(DisasContext *, DisasOps *); 1057 void (*help_prep)(DisasContext *, DisasOps *); 1058 1059 /* 1060 * Post-process output after HELP_OP. 1061 * Note that these are not called if HELP_OP returns DISAS_NORETURN. 1062 */ 1063 void (*help_wout)(DisasContext *, DisasOps *); 1064 void (*help_cout)(DisasContext *, DisasOps *); 1065 1066 /* Implement the operation itself. */ 1067 DisasJumpType (*help_op)(DisasContext *, DisasOps *); 1068 1069 uint64_t data; 1070 }; 1071 1072 /* ====================================================================== */ 1073 /* Miscellaneous helpers, used by several operations. */ 1074 1075 static DisasJumpType help_goto_direct(DisasContext *s, uint64_t dest) 1076 { 1077 update_cc_op(s); 1078 per_breaking_event(s); 1079 per_branch(s, tcg_constant_i64(dest)); 1080 1081 if (dest == s->pc_tmp) { 1082 return DISAS_NEXT; 1083 } 1084 if (use_goto_tb(s, dest)) { 1085 tcg_gen_goto_tb(0); 1086 tcg_gen_movi_i64(psw_addr, dest); 1087 tcg_gen_exit_tb(s->base.tb, 0); 1088 return DISAS_NORETURN; 1089 } else { 1090 tcg_gen_movi_i64(psw_addr, dest); 1091 return DISAS_PC_CC_UPDATED; 1092 } 1093 } 1094 1095 static DisasJumpType help_goto_indirect(DisasContext *s, TCGv_i64 dest) 1096 { 1097 update_cc_op(s); 1098 per_breaking_event(s); 1099 tcg_gen_mov_i64(psw_addr, dest); 1100 per_branch(s, psw_addr); 1101 return DISAS_PC_CC_UPDATED; 1102 } 1103 1104 static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, 1105 bool is_imm, int imm, TCGv_i64 cdest) 1106 { 1107 uint64_t dest = s->base.pc_next + (int64_t)imm * 2; 1108 TCGLabel *lab; 1109 1110 /* Take care of the special cases first. */ 1111 if (c->cond == TCG_COND_NEVER) { 1112 return DISAS_NEXT; 1113 } 1114 if (is_imm) { 1115 /* 1116 * Do not optimize a conditional branch if PER enabled, because we 1117 * still need a conditional call to helper_per_branch. 1118 */ 1119 if (c->cond == TCG_COND_ALWAYS 1120 || (dest == s->pc_tmp && 1121 !(s->base.tb->flags & FLAG_MASK_PER_BRANCH))) { 1122 return help_goto_direct(s, dest); 1123 } 1124 } else { 1125 if (!cdest) { 1126 /* E.g. bcr %r0 -> no branch. */ 1127 return DISAS_NEXT; 1128 } 1129 if (c->cond == TCG_COND_ALWAYS) { 1130 return help_goto_indirect(s, cdest); 1131 } 1132 } 1133 1134 update_cc_op(s); 1135 1136 /* 1137 * Ensure the taken branch is fall-through of the tcg branch. 1138 * This keeps @cdest usage within the extended basic block, 1139 * which avoids an otherwise unnecessary spill to the stack. 1140 */ 1141 lab = gen_new_label(); 1142 if (c->is_64) { 1143 tcg_gen_brcond_i64(tcg_invert_cond(c->cond), 1144 c->u.s64.a, c->u.s64.b, lab); 1145 } else { 1146 tcg_gen_brcond_i32(tcg_invert_cond(c->cond), 1147 c->u.s32.a, c->u.s32.b, lab); 1148 } 1149 1150 /* Branch taken. */ 1151 per_breaking_event(s); 1152 if (is_imm) { 1153 tcg_gen_movi_i64(psw_addr, dest); 1154 } else { 1155 tcg_gen_mov_i64(psw_addr, cdest); 1156 } 1157 per_branch(s, psw_addr); 1158 1159 if (is_imm && use_goto_tb(s, dest)) { 1160 tcg_gen_goto_tb(0); 1161 tcg_gen_exit_tb(s->base.tb, 0); 1162 } else { 1163 tcg_gen_lookup_and_goto_ptr(); 1164 } 1165 1166 gen_set_label(lab); 1167 1168 /* Branch not taken. */ 1169 tcg_gen_movi_i64(psw_addr, s->pc_tmp); 1170 if (use_goto_tb(s, s->pc_tmp)) { 1171 tcg_gen_goto_tb(1); 1172 tcg_gen_exit_tb(s->base.tb, 1); 1173 return DISAS_NORETURN; 1174 } 1175 return DISAS_PC_CC_UPDATED; 1176 } 1177 1178 /* ====================================================================== */ 1179 /* The operations. These perform the bulk of the work for any insn, 1180 usually after the operands have been loaded and output initialized. */ 1181 1182 static DisasJumpType op_abs(DisasContext *s, DisasOps *o) 1183 { 1184 tcg_gen_abs_i64(o->out, o->in2); 1185 return DISAS_NEXT; 1186 } 1187 1188 static DisasJumpType op_absf32(DisasContext *s, DisasOps *o) 1189 { 1190 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull); 1191 return DISAS_NEXT; 1192 } 1193 1194 static DisasJumpType op_absf64(DisasContext *s, DisasOps *o) 1195 { 1196 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull); 1197 return DISAS_NEXT; 1198 } 1199 1200 static DisasJumpType op_absf128(DisasContext *s, DisasOps *o) 1201 { 1202 tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull); 1203 tcg_gen_mov_i64(o->out2, o->in2); 1204 return DISAS_NEXT; 1205 } 1206 1207 static DisasJumpType op_add(DisasContext *s, DisasOps *o) 1208 { 1209 tcg_gen_add_i64(o->out, o->in1, o->in2); 1210 return DISAS_NEXT; 1211 } 1212 1213 static DisasJumpType op_addu64(DisasContext *s, DisasOps *o) 1214 { 1215 tcg_gen_movi_i64(cc_src, 0); 1216 tcg_gen_add2_i64(o->out, cc_src, o->in1, cc_src, o->in2, cc_src); 1217 return DISAS_NEXT; 1218 } 1219 1220 /* Compute carry into cc_src. */ 1221 static void compute_carry(DisasContext *s) 1222 { 1223 switch (s->cc_op) { 1224 case CC_OP_ADDU: 1225 /* The carry value is already in cc_src (1,0). */ 1226 break; 1227 case CC_OP_SUBU: 1228 tcg_gen_addi_i64(cc_src, cc_src, 1); 1229 break; 1230 default: 1231 gen_op_calc_cc(s); 1232 /* fall through */ 1233 case CC_OP_STATIC: 1234 /* The carry flag is the msb of CC; compute into cc_src. */ 1235 tcg_gen_extu_i32_i64(cc_src, cc_op); 1236 tcg_gen_shri_i64(cc_src, cc_src, 1); 1237 break; 1238 } 1239 } 1240 1241 static DisasJumpType op_addc32(DisasContext *s, DisasOps *o) 1242 { 1243 compute_carry(s); 1244 tcg_gen_add_i64(o->out, o->in1, o->in2); 1245 tcg_gen_add_i64(o->out, o->out, cc_src); 1246 return DISAS_NEXT; 1247 } 1248 1249 static DisasJumpType op_addc64(DisasContext *s, DisasOps *o) 1250 { 1251 compute_carry(s); 1252 tcg_gen_addcio_i64(o->out, cc_src, o->in1, o->in2, cc_src); 1253 return DISAS_NEXT; 1254 } 1255 1256 static DisasJumpType op_asi(DisasContext *s, DisasOps *o) 1257 { 1258 bool non_atomic = !s390_has_feat(S390_FEAT_STFLE_45); 1259 1260 o->in1 = tcg_temp_new_i64(); 1261 if (non_atomic) { 1262 tcg_gen_qemu_ld_tl(o->in1, o->addr1, get_mem_index(s), s->insn->data); 1263 } else { 1264 /* Perform the atomic addition in memory. */ 1265 tcg_gen_atomic_fetch_add_i64(o->in1, o->addr1, o->in2, get_mem_index(s), 1266 s->insn->data); 1267 } 1268 1269 /* Recompute also for atomic case: needed for setting CC. */ 1270 tcg_gen_add_i64(o->out, o->in1, o->in2); 1271 1272 if (non_atomic) { 1273 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); 1274 } 1275 return DISAS_NEXT; 1276 } 1277 1278 static DisasJumpType op_asiu64(DisasContext *s, DisasOps *o) 1279 { 1280 bool non_atomic = !s390_has_feat(S390_FEAT_STFLE_45); 1281 1282 o->in1 = tcg_temp_new_i64(); 1283 if (non_atomic) { 1284 tcg_gen_qemu_ld_tl(o->in1, o->addr1, get_mem_index(s), s->insn->data); 1285 } else { 1286 /* Perform the atomic addition in memory. */ 1287 tcg_gen_atomic_fetch_add_i64(o->in1, o->addr1, o->in2, get_mem_index(s), 1288 s->insn->data); 1289 } 1290 1291 /* Recompute also for atomic case: needed for setting CC. */ 1292 tcg_gen_movi_i64(cc_src, 0); 1293 tcg_gen_add2_i64(o->out, cc_src, o->in1, cc_src, o->in2, cc_src); 1294 1295 if (non_atomic) { 1296 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); 1297 } 1298 return DISAS_NEXT; 1299 } 1300 1301 static DisasJumpType op_aeb(DisasContext *s, DisasOps *o) 1302 { 1303 gen_helper_aeb(o->out, tcg_env, o->in1, o->in2); 1304 return DISAS_NEXT; 1305 } 1306 1307 static DisasJumpType op_adb(DisasContext *s, DisasOps *o) 1308 { 1309 gen_helper_adb(o->out, tcg_env, o->in1, o->in2); 1310 return DISAS_NEXT; 1311 } 1312 1313 static DisasJumpType op_axb(DisasContext *s, DisasOps *o) 1314 { 1315 gen_helper_axb(o->out_128, tcg_env, o->in1_128, o->in2_128); 1316 return DISAS_NEXT; 1317 } 1318 1319 static DisasJumpType op_and(DisasContext *s, DisasOps *o) 1320 { 1321 tcg_gen_and_i64(o->out, o->in1, o->in2); 1322 return DISAS_NEXT; 1323 } 1324 1325 static DisasJumpType op_andi(DisasContext *s, DisasOps *o) 1326 { 1327 int shift = s->insn->data & 0xff; 1328 int size = s->insn->data >> 8; 1329 uint64_t mask = ((1ull << size) - 1) << shift; 1330 TCGv_i64 t = tcg_temp_new_i64(); 1331 1332 tcg_gen_shli_i64(t, o->in2, shift); 1333 tcg_gen_ori_i64(t, t, ~mask); 1334 tcg_gen_and_i64(o->out, o->in1, t); 1335 1336 /* Produce the CC from only the bits manipulated. */ 1337 tcg_gen_andi_i64(cc_dst, o->out, mask); 1338 set_cc_nz_u64(s, cc_dst); 1339 return DISAS_NEXT; 1340 } 1341 1342 static DisasJumpType op_andc(DisasContext *s, DisasOps *o) 1343 { 1344 tcg_gen_andc_i64(o->out, o->in1, o->in2); 1345 return DISAS_NEXT; 1346 } 1347 1348 static DisasJumpType op_orc(DisasContext *s, DisasOps *o) 1349 { 1350 tcg_gen_orc_i64(o->out, o->in1, o->in2); 1351 return DISAS_NEXT; 1352 } 1353 1354 static DisasJumpType op_nand(DisasContext *s, DisasOps *o) 1355 { 1356 tcg_gen_nand_i64(o->out, o->in1, o->in2); 1357 return DISAS_NEXT; 1358 } 1359 1360 static DisasJumpType op_nor(DisasContext *s, DisasOps *o) 1361 { 1362 tcg_gen_nor_i64(o->out, o->in1, o->in2); 1363 return DISAS_NEXT; 1364 } 1365 1366 static DisasJumpType op_nxor(DisasContext *s, DisasOps *o) 1367 { 1368 tcg_gen_eqv_i64(o->out, o->in1, o->in2); 1369 return DISAS_NEXT; 1370 } 1371 1372 static DisasJumpType op_ni(DisasContext *s, DisasOps *o) 1373 { 1374 o->in1 = tcg_temp_new_i64(); 1375 1376 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 1377 tcg_gen_qemu_ld_tl(o->in1, o->addr1, get_mem_index(s), s->insn->data); 1378 } else { 1379 /* Perform the atomic operation in memory. */ 1380 tcg_gen_atomic_fetch_and_i64(o->in1, o->addr1, o->in2, get_mem_index(s), 1381 s->insn->data); 1382 } 1383 1384 /* Recompute also for atomic case: needed for setting CC. */ 1385 tcg_gen_and_i64(o->out, o->in1, o->in2); 1386 1387 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 1388 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); 1389 } 1390 return DISAS_NEXT; 1391 } 1392 1393 static DisasJumpType op_bas(DisasContext *s, DisasOps *o) 1394 { 1395 pc_to_link_info(o->out, s, s->pc_tmp); 1396 if (o->in2) { 1397 return help_goto_indirect(s, o->in2); 1398 } else { 1399 return DISAS_NEXT; 1400 } 1401 } 1402 1403 static void save_link_info(DisasContext *s, DisasOps *o) 1404 { 1405 TCGv_i64 t; 1406 1407 if (s->base.tb->flags & (FLAG_MASK_32 | FLAG_MASK_64)) { 1408 pc_to_link_info(o->out, s, s->pc_tmp); 1409 return; 1410 } 1411 gen_op_calc_cc(s); 1412 tcg_gen_andi_i64(o->out, o->out, 0xffffffff00000000ull); 1413 tcg_gen_ori_i64(o->out, o->out, ((s->ilen / 2) << 30) | s->pc_tmp); 1414 t = tcg_temp_new_i64(); 1415 tcg_gen_shri_i64(t, psw_mask, 16); 1416 tcg_gen_andi_i64(t, t, 0x0f000000); 1417 tcg_gen_or_i64(o->out, o->out, t); 1418 tcg_gen_extu_i32_i64(t, cc_op); 1419 tcg_gen_shli_i64(t, t, 28); 1420 tcg_gen_or_i64(o->out, o->out, t); 1421 } 1422 1423 static DisasJumpType op_bal(DisasContext *s, DisasOps *o) 1424 { 1425 save_link_info(s, o); 1426 if (o->in2) { 1427 return help_goto_indirect(s, o->in2); 1428 } else { 1429 return DISAS_NEXT; 1430 } 1431 } 1432 1433 /* 1434 * Disassemble the target of a branch. The results are returned in a form 1435 * suitable for passing into help_branch(): 1436 * 1437 * - bool IS_IMM reflects whether the target is fixed or computed. Non-EXECUTEd 1438 * branches, whose DisasContext *S contains the relative immediate field RI, 1439 * are considered fixed. All the other branches are considered computed. 1440 * - int IMM is the value of RI. 1441 * - TCGv_i64 CDEST is the address of the computed target. 1442 */ 1443 #define disas_jdest(s, ri, is_imm, imm, cdest) do { \ 1444 if (have_field(s, ri)) { \ 1445 if (unlikely(s->ex_value)) { \ 1446 cdest = tcg_temp_new_i64(); \ 1447 tcg_gen_ld_i64(cdest, tcg_env, offsetof(CPUS390XState, ex_target));\ 1448 tcg_gen_addi_i64(cdest, cdest, (int64_t)get_field(s, ri) * 2); \ 1449 is_imm = false; \ 1450 } else { \ 1451 is_imm = true; \ 1452 } \ 1453 } else { \ 1454 is_imm = false; \ 1455 } \ 1456 imm = is_imm ? get_field(s, ri) : 0; \ 1457 } while (false) 1458 1459 static DisasJumpType op_basi(DisasContext *s, DisasOps *o) 1460 { 1461 DisasCompare c; 1462 bool is_imm; 1463 int imm; 1464 1465 pc_to_link_info(o->out, s, s->pc_tmp); 1466 1467 disas_jdest(s, i2, is_imm, imm, o->in2); 1468 disas_jcc(s, &c, 0xf); 1469 return help_branch(s, &c, is_imm, imm, o->in2); 1470 } 1471 1472 static DisasJumpType op_bc(DisasContext *s, DisasOps *o) 1473 { 1474 int m1 = get_field(s, m1); 1475 DisasCompare c; 1476 bool is_imm; 1477 int imm; 1478 1479 /* BCR with R2 = 0 causes no branching */ 1480 if (have_field(s, r2) && get_field(s, r2) == 0) { 1481 if (m1 == 14) { 1482 /* Perform serialization */ 1483 /* FIXME: check for fast-BCR-serialization facility */ 1484 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 1485 } 1486 if (m1 == 15) { 1487 /* Perform serialization */ 1488 /* FIXME: perform checkpoint-synchronisation */ 1489 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 1490 } 1491 return DISAS_NEXT; 1492 } 1493 1494 disas_jdest(s, i2, is_imm, imm, o->in2); 1495 disas_jcc(s, &c, m1); 1496 return help_branch(s, &c, is_imm, imm, o->in2); 1497 } 1498 1499 static DisasJumpType op_bct32(DisasContext *s, DisasOps *o) 1500 { 1501 int r1 = get_field(s, r1); 1502 DisasCompare c; 1503 bool is_imm; 1504 TCGv_i64 t; 1505 int imm; 1506 1507 c.cond = TCG_COND_NE; 1508 c.is_64 = false; 1509 1510 t = tcg_temp_new_i64(); 1511 tcg_gen_subi_i64(t, regs[r1], 1); 1512 store_reg32_i64(r1, t); 1513 c.u.s32.a = tcg_temp_new_i32(); 1514 c.u.s32.b = tcg_constant_i32(0); 1515 tcg_gen_extrl_i64_i32(c.u.s32.a, t); 1516 1517 disas_jdest(s, i2, is_imm, imm, o->in2); 1518 return help_branch(s, &c, is_imm, imm, o->in2); 1519 } 1520 1521 static DisasJumpType op_bcth(DisasContext *s, DisasOps *o) 1522 { 1523 int r1 = get_field(s, r1); 1524 int imm = get_field(s, i2); 1525 DisasCompare c; 1526 TCGv_i64 t; 1527 1528 c.cond = TCG_COND_NE; 1529 c.is_64 = false; 1530 1531 t = tcg_temp_new_i64(); 1532 tcg_gen_shri_i64(t, regs[r1], 32); 1533 tcg_gen_subi_i64(t, t, 1); 1534 store_reg32h_i64(r1, t); 1535 c.u.s32.a = tcg_temp_new_i32(); 1536 c.u.s32.b = tcg_constant_i32(0); 1537 tcg_gen_extrl_i64_i32(c.u.s32.a, t); 1538 1539 return help_branch(s, &c, 1, imm, o->in2); 1540 } 1541 1542 static DisasJumpType op_bct64(DisasContext *s, DisasOps *o) 1543 { 1544 int r1 = get_field(s, r1); 1545 DisasCompare c; 1546 bool is_imm; 1547 int imm; 1548 1549 c.cond = TCG_COND_NE; 1550 c.is_64 = true; 1551 1552 tcg_gen_subi_i64(regs[r1], regs[r1], 1); 1553 c.u.s64.a = regs[r1]; 1554 c.u.s64.b = tcg_constant_i64(0); 1555 1556 disas_jdest(s, i2, is_imm, imm, o->in2); 1557 return help_branch(s, &c, is_imm, imm, o->in2); 1558 } 1559 1560 static DisasJumpType op_bx32(DisasContext *s, DisasOps *o) 1561 { 1562 int r1 = get_field(s, r1); 1563 int r3 = get_field(s, r3); 1564 DisasCompare c; 1565 bool is_imm; 1566 TCGv_i64 t; 1567 int imm; 1568 1569 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT); 1570 c.is_64 = false; 1571 1572 t = tcg_temp_new_i64(); 1573 tcg_gen_add_i64(t, regs[r1], regs[r3]); 1574 c.u.s32.a = tcg_temp_new_i32(); 1575 c.u.s32.b = tcg_temp_new_i32(); 1576 tcg_gen_extrl_i64_i32(c.u.s32.a, t); 1577 tcg_gen_extrl_i64_i32(c.u.s32.b, regs[r3 | 1]); 1578 store_reg32_i64(r1, t); 1579 1580 disas_jdest(s, i2, is_imm, imm, o->in2); 1581 return help_branch(s, &c, is_imm, imm, o->in2); 1582 } 1583 1584 static DisasJumpType op_bx64(DisasContext *s, DisasOps *o) 1585 { 1586 int r1 = get_field(s, r1); 1587 int r3 = get_field(s, r3); 1588 DisasCompare c; 1589 bool is_imm; 1590 int imm; 1591 1592 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT); 1593 c.is_64 = true; 1594 1595 if (r1 == (r3 | 1)) { 1596 c.u.s64.b = load_reg(r3 | 1); 1597 } else { 1598 c.u.s64.b = regs[r3 | 1]; 1599 } 1600 1601 tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]); 1602 c.u.s64.a = regs[r1]; 1603 1604 disas_jdest(s, i2, is_imm, imm, o->in2); 1605 return help_branch(s, &c, is_imm, imm, o->in2); 1606 } 1607 1608 static DisasJumpType op_cj(DisasContext *s, DisasOps *o) 1609 { 1610 int imm, m3 = get_field(s, m3); 1611 bool is_imm; 1612 DisasCompare c; 1613 1614 c.cond = ltgt_cond[m3]; 1615 if (s->insn->data) { 1616 c.cond = tcg_unsigned_cond(c.cond); 1617 } 1618 c.is_64 = true; 1619 c.u.s64.a = o->in1; 1620 c.u.s64.b = o->in2; 1621 1622 o->out = NULL; 1623 disas_jdest(s, i4, is_imm, imm, o->out); 1624 if (!is_imm && !o->out) { 1625 imm = 0; 1626 o->out = get_address(s, 0, get_field(s, b4), 1627 get_field(s, d4)); 1628 } 1629 1630 return help_branch(s, &c, is_imm, imm, o->out); 1631 } 1632 1633 static DisasJumpType op_ceb(DisasContext *s, DisasOps *o) 1634 { 1635 gen_helper_ceb(cc_op, tcg_env, o->in1, o->in2); 1636 set_cc_static(s); 1637 return DISAS_NEXT; 1638 } 1639 1640 static DisasJumpType op_cdb(DisasContext *s, DisasOps *o) 1641 { 1642 gen_helper_cdb(cc_op, tcg_env, o->in1, o->in2); 1643 set_cc_static(s); 1644 return DISAS_NEXT; 1645 } 1646 1647 static DisasJumpType op_cxb(DisasContext *s, DisasOps *o) 1648 { 1649 gen_helper_cxb(cc_op, tcg_env, o->in1_128, o->in2_128); 1650 set_cc_static(s); 1651 return DISAS_NEXT; 1652 } 1653 1654 static TCGv_i32 fpinst_extract_m34(DisasContext *s, bool m3_with_fpe, 1655 bool m4_with_fpe) 1656 { 1657 const bool fpe = s390_has_feat(S390_FEAT_FLOATING_POINT_EXT); 1658 uint8_t m3 = get_field(s, m3); 1659 uint8_t m4 = get_field(s, m4); 1660 1661 /* m3 field was introduced with FPE */ 1662 if (!fpe && m3_with_fpe) { 1663 m3 = 0; 1664 } 1665 /* m4 field was introduced with FPE */ 1666 if (!fpe && m4_with_fpe) { 1667 m4 = 0; 1668 } 1669 1670 /* Check for valid rounding modes. Mode 3 was introduced later. */ 1671 if (m3 == 2 || m3 > 7 || (!fpe && m3 == 3)) { 1672 gen_program_exception(s, PGM_SPECIFICATION); 1673 return NULL; 1674 } 1675 1676 return tcg_constant_i32(deposit32(m3, 4, 4, m4)); 1677 } 1678 1679 static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o) 1680 { 1681 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1682 1683 if (!m34) { 1684 return DISAS_NORETURN; 1685 } 1686 gen_helper_cfeb(o->out, tcg_env, o->in2, m34); 1687 set_cc_static(s); 1688 return DISAS_NEXT; 1689 } 1690 1691 static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o) 1692 { 1693 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1694 1695 if (!m34) { 1696 return DISAS_NORETURN; 1697 } 1698 gen_helper_cfdb(o->out, tcg_env, o->in2, m34); 1699 set_cc_static(s); 1700 return DISAS_NEXT; 1701 } 1702 1703 static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o) 1704 { 1705 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1706 1707 if (!m34) { 1708 return DISAS_NORETURN; 1709 } 1710 gen_helper_cfxb(o->out, tcg_env, o->in2_128, m34); 1711 set_cc_static(s); 1712 return DISAS_NEXT; 1713 } 1714 1715 static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o) 1716 { 1717 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1718 1719 if (!m34) { 1720 return DISAS_NORETURN; 1721 } 1722 gen_helper_cgeb(o->out, tcg_env, o->in2, m34); 1723 set_cc_static(s); 1724 return DISAS_NEXT; 1725 } 1726 1727 static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o) 1728 { 1729 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1730 1731 if (!m34) { 1732 return DISAS_NORETURN; 1733 } 1734 gen_helper_cgdb(o->out, tcg_env, o->in2, m34); 1735 set_cc_static(s); 1736 return DISAS_NEXT; 1737 } 1738 1739 static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o) 1740 { 1741 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 1742 1743 if (!m34) { 1744 return DISAS_NORETURN; 1745 } 1746 gen_helper_cgxb(o->out, tcg_env, o->in2_128, m34); 1747 set_cc_static(s); 1748 return DISAS_NEXT; 1749 } 1750 1751 static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o) 1752 { 1753 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1754 1755 if (!m34) { 1756 return DISAS_NORETURN; 1757 } 1758 gen_helper_clfeb(o->out, tcg_env, o->in2, m34); 1759 set_cc_static(s); 1760 return DISAS_NEXT; 1761 } 1762 1763 static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o) 1764 { 1765 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1766 1767 if (!m34) { 1768 return DISAS_NORETURN; 1769 } 1770 gen_helper_clfdb(o->out, tcg_env, o->in2, m34); 1771 set_cc_static(s); 1772 return DISAS_NEXT; 1773 } 1774 1775 static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o) 1776 { 1777 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1778 1779 if (!m34) { 1780 return DISAS_NORETURN; 1781 } 1782 gen_helper_clfxb(o->out, tcg_env, o->in2_128, m34); 1783 set_cc_static(s); 1784 return DISAS_NEXT; 1785 } 1786 1787 static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o) 1788 { 1789 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1790 1791 if (!m34) { 1792 return DISAS_NORETURN; 1793 } 1794 gen_helper_clgeb(o->out, tcg_env, o->in2, m34); 1795 set_cc_static(s); 1796 return DISAS_NEXT; 1797 } 1798 1799 static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o) 1800 { 1801 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1802 1803 if (!m34) { 1804 return DISAS_NORETURN; 1805 } 1806 gen_helper_clgdb(o->out, tcg_env, o->in2, m34); 1807 set_cc_static(s); 1808 return DISAS_NEXT; 1809 } 1810 1811 static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o) 1812 { 1813 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1814 1815 if (!m34) { 1816 return DISAS_NORETURN; 1817 } 1818 gen_helper_clgxb(o->out, tcg_env, o->in2_128, m34); 1819 set_cc_static(s); 1820 return DISAS_NEXT; 1821 } 1822 1823 static DisasJumpType op_cegb(DisasContext *s, DisasOps *o) 1824 { 1825 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 1826 1827 if (!m34) { 1828 return DISAS_NORETURN; 1829 } 1830 gen_helper_cegb(o->out, tcg_env, o->in2, m34); 1831 return DISAS_NEXT; 1832 } 1833 1834 static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o) 1835 { 1836 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 1837 1838 if (!m34) { 1839 return DISAS_NORETURN; 1840 } 1841 gen_helper_cdgb(o->out, tcg_env, o->in2, m34); 1842 return DISAS_NEXT; 1843 } 1844 1845 static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o) 1846 { 1847 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 1848 1849 if (!m34) { 1850 return DISAS_NORETURN; 1851 } 1852 gen_helper_cxgb(o->out_128, tcg_env, o->in2, m34); 1853 return DISAS_NEXT; 1854 } 1855 1856 static DisasJumpType op_celgb(DisasContext *s, DisasOps *o) 1857 { 1858 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1859 1860 if (!m34) { 1861 return DISAS_NORETURN; 1862 } 1863 gen_helper_celgb(o->out, tcg_env, o->in2, m34); 1864 return DISAS_NEXT; 1865 } 1866 1867 static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o) 1868 { 1869 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1870 1871 if (!m34) { 1872 return DISAS_NORETURN; 1873 } 1874 gen_helper_cdlgb(o->out, tcg_env, o->in2, m34); 1875 return DISAS_NEXT; 1876 } 1877 1878 static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o) 1879 { 1880 TCGv_i32 m34 = fpinst_extract_m34(s, false, false); 1881 1882 if (!m34) { 1883 return DISAS_NORETURN; 1884 } 1885 gen_helper_cxlgb(o->out_128, tcg_env, o->in2, m34); 1886 return DISAS_NEXT; 1887 } 1888 1889 static DisasJumpType op_cksm(DisasContext *s, DisasOps *o) 1890 { 1891 int r2 = get_field(s, r2); 1892 TCGv_i128 pair = tcg_temp_new_i128(); 1893 TCGv_i64 len = tcg_temp_new_i64(); 1894 1895 gen_helper_cksm(pair, tcg_env, o->in1, o->in2, regs[r2 + 1]); 1896 set_cc_static(s); 1897 tcg_gen_extr_i128_i64(o->out, len, pair); 1898 1899 tcg_gen_add_i64(regs[r2], regs[r2], len); 1900 tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len); 1901 1902 return DISAS_NEXT; 1903 } 1904 1905 static DisasJumpType op_clc(DisasContext *s, DisasOps *o) 1906 { 1907 int l = get_field(s, l1); 1908 TCGv_i64 src; 1909 TCGv_i32 vl; 1910 MemOp mop; 1911 1912 switch (l + 1) { 1913 case 1: 1914 case 2: 1915 case 4: 1916 case 8: 1917 mop = ctz32(l + 1) | MO_TE; 1918 /* Do not update cc_src yet: loading cc_dst may cause an exception. */ 1919 src = tcg_temp_new_i64(); 1920 tcg_gen_qemu_ld_tl(src, o->addr1, get_mem_index(s), mop); 1921 tcg_gen_qemu_ld_tl(cc_dst, o->in2, get_mem_index(s), mop); 1922 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, src, cc_dst); 1923 return DISAS_NEXT; 1924 default: 1925 vl = tcg_constant_i32(l); 1926 gen_helper_clc(cc_op, tcg_env, vl, o->addr1, o->in2); 1927 set_cc_static(s); 1928 return DISAS_NEXT; 1929 } 1930 } 1931 1932 static DisasJumpType op_clcl(DisasContext *s, DisasOps *o) 1933 { 1934 int r1 = get_field(s, r1); 1935 int r2 = get_field(s, r2); 1936 TCGv_i32 t1, t2; 1937 1938 /* r1 and r2 must be even. */ 1939 if (r1 & 1 || r2 & 1) { 1940 gen_program_exception(s, PGM_SPECIFICATION); 1941 return DISAS_NORETURN; 1942 } 1943 1944 t1 = tcg_constant_i32(r1); 1945 t2 = tcg_constant_i32(r2); 1946 gen_helper_clcl(cc_op, tcg_env, t1, t2); 1947 set_cc_static(s); 1948 return DISAS_NEXT; 1949 } 1950 1951 static DisasJumpType op_clcle(DisasContext *s, DisasOps *o) 1952 { 1953 int r1 = get_field(s, r1); 1954 int r3 = get_field(s, r3); 1955 TCGv_i32 t1, t3; 1956 1957 /* r1 and r3 must be even. */ 1958 if (r1 & 1 || r3 & 1) { 1959 gen_program_exception(s, PGM_SPECIFICATION); 1960 return DISAS_NORETURN; 1961 } 1962 1963 t1 = tcg_constant_i32(r1); 1964 t3 = tcg_constant_i32(r3); 1965 gen_helper_clcle(cc_op, tcg_env, t1, o->in2, t3); 1966 set_cc_static(s); 1967 return DISAS_NEXT; 1968 } 1969 1970 static DisasJumpType op_clclu(DisasContext *s, DisasOps *o) 1971 { 1972 int r1 = get_field(s, r1); 1973 int r3 = get_field(s, r3); 1974 TCGv_i32 t1, t3; 1975 1976 /* r1 and r3 must be even. */ 1977 if (r1 & 1 || r3 & 1) { 1978 gen_program_exception(s, PGM_SPECIFICATION); 1979 return DISAS_NORETURN; 1980 } 1981 1982 t1 = tcg_constant_i32(r1); 1983 t3 = tcg_constant_i32(r3); 1984 gen_helper_clclu(cc_op, tcg_env, t1, o->in2, t3); 1985 set_cc_static(s); 1986 return DISAS_NEXT; 1987 } 1988 1989 static DisasJumpType op_clm(DisasContext *s, DisasOps *o) 1990 { 1991 TCGv_i32 m3 = tcg_constant_i32(get_field(s, m3)); 1992 TCGv_i32 t1 = tcg_temp_new_i32(); 1993 1994 tcg_gen_extrl_i64_i32(t1, o->in1); 1995 gen_helper_clm(cc_op, tcg_env, t1, m3, o->in2); 1996 set_cc_static(s); 1997 return DISAS_NEXT; 1998 } 1999 2000 static DisasJumpType op_clst(DisasContext *s, DisasOps *o) 2001 { 2002 TCGv_i128 pair = tcg_temp_new_i128(); 2003 2004 gen_helper_clst(pair, tcg_env, regs[0], o->in1, o->in2); 2005 tcg_gen_extr_i128_i64(o->in2, o->in1, pair); 2006 2007 set_cc_static(s); 2008 return DISAS_NEXT; 2009 } 2010 2011 static DisasJumpType op_cps(DisasContext *s, DisasOps *o) 2012 { 2013 TCGv_i64 t = tcg_temp_new_i64(); 2014 tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull); 2015 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull); 2016 tcg_gen_or_i64(o->out, o->out, t); 2017 return DISAS_NEXT; 2018 } 2019 2020 static DisasJumpType op_cs(DisasContext *s, DisasOps *o) 2021 { 2022 int d2 = get_field(s, d2); 2023 int b2 = get_field(s, b2); 2024 TCGv_i64 addr, cc; 2025 2026 /* Note that in1 = R3 (new value) and 2027 in2 = (zero-extended) R1 (expected value). */ 2028 2029 addr = get_address(s, 0, b2, d2); 2030 tcg_gen_atomic_cmpxchg_i64(o->out, addr, o->in2, o->in1, 2031 get_mem_index(s), s->insn->data | MO_ALIGN); 2032 2033 /* Are the memory and expected values (un)equal? Note that this setcond 2034 produces the output CC value, thus the NE sense of the test. */ 2035 cc = tcg_temp_new_i64(); 2036 tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out); 2037 tcg_gen_extrl_i64_i32(cc_op, cc); 2038 set_cc_static(s); 2039 2040 return DISAS_NEXT; 2041 } 2042 2043 static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o) 2044 { 2045 int r1 = get_field(s, r1); 2046 2047 o->out_128 = tcg_temp_new_i128(); 2048 tcg_gen_concat_i64_i128(o->out_128, regs[r1 + 1], regs[r1]); 2049 2050 /* Note out (R1:R1+1) = expected value and in2 (R3:R3+1) = new value. */ 2051 tcg_gen_atomic_cmpxchg_i128(o->out_128, o->addr1, o->out_128, o->in2_128, 2052 get_mem_index(s), MO_BE | MO_128 | MO_ALIGN); 2053 2054 /* 2055 * Extract result into cc_dst:cc_src, compare vs the expected value 2056 * in the as yet unmodified input registers, then update CC_OP. 2057 */ 2058 tcg_gen_extr_i128_i64(cc_src, cc_dst, o->out_128); 2059 tcg_gen_xor_i64(cc_dst, cc_dst, regs[r1]); 2060 tcg_gen_xor_i64(cc_src, cc_src, regs[r1 + 1]); 2061 tcg_gen_or_i64(cc_dst, cc_dst, cc_src); 2062 set_cc_nz_u64(s, cc_dst); 2063 2064 return DISAS_NEXT; 2065 } 2066 2067 static DisasJumpType op_csst(DisasContext *s, DisasOps *o) 2068 { 2069 int r3 = get_field(s, r3); 2070 TCGv_i32 t_r3 = tcg_constant_i32(r3); 2071 2072 if (tb_cflags(s->base.tb) & CF_PARALLEL) { 2073 gen_helper_csst_parallel(cc_op, tcg_env, t_r3, o->addr1, o->in2); 2074 } else { 2075 gen_helper_csst(cc_op, tcg_env, t_r3, o->addr1, o->in2); 2076 } 2077 2078 set_cc_static(s); 2079 return DISAS_NEXT; 2080 } 2081 2082 #ifndef CONFIG_USER_ONLY 2083 static DisasJumpType op_csp(DisasContext *s, DisasOps *o) 2084 { 2085 MemOp mop = s->insn->data; 2086 TCGv_i64 addr, old, cc; 2087 TCGLabel *lab = gen_new_label(); 2088 2089 /* Note that in1 = R1 (zero-extended expected value), 2090 out = R1 (original reg), out2 = R1+1 (new value). */ 2091 2092 addr = tcg_temp_new_i64(); 2093 old = tcg_temp_new_i64(); 2094 tcg_gen_andi_i64(addr, o->in2, -1ULL << (mop & MO_SIZE)); 2095 tcg_gen_atomic_cmpxchg_i64(old, addr, o->in1, o->out2, 2096 get_mem_index(s), mop | MO_ALIGN); 2097 2098 /* Are the memory and expected values (un)equal? */ 2099 cc = tcg_temp_new_i64(); 2100 tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in1, old); 2101 tcg_gen_extrl_i64_i32(cc_op, cc); 2102 2103 /* Write back the output now, so that it happens before the 2104 following branch, so that we don't need local temps. */ 2105 if ((mop & MO_SIZE) == MO_32) { 2106 tcg_gen_deposit_i64(o->out, o->out, old, 0, 32); 2107 } else { 2108 tcg_gen_mov_i64(o->out, old); 2109 } 2110 2111 /* If the comparison was equal, and the LSB of R2 was set, 2112 then we need to flush the TLB (for all cpus). */ 2113 tcg_gen_xori_i64(cc, cc, 1); 2114 tcg_gen_and_i64(cc, cc, o->in2); 2115 tcg_gen_brcondi_i64(TCG_COND_EQ, cc, 0, lab); 2116 2117 gen_helper_purge(tcg_env); 2118 gen_set_label(lab); 2119 2120 return DISAS_NEXT; 2121 } 2122 #endif 2123 2124 static DisasJumpType op_cvb(DisasContext *s, DisasOps *o) 2125 { 2126 TCGv_i64 t = tcg_temp_new_i64(); 2127 tcg_gen_qemu_ld_i64(t, o->addr1, get_mem_index(s), MO_TEUQ); 2128 gen_helper_cvb(tcg_env, tcg_constant_i32(get_field(s, r1)), t); 2129 return DISAS_NEXT; 2130 } 2131 2132 static DisasJumpType op_cvbg(DisasContext *s, DisasOps *o) 2133 { 2134 TCGv_i128 t = tcg_temp_new_i128(); 2135 tcg_gen_qemu_ld_i128(t, o->addr1, get_mem_index(s), MO_TE | MO_128); 2136 gen_helper_cvbg(o->out, tcg_env, t); 2137 return DISAS_NEXT; 2138 } 2139 2140 static DisasJumpType op_cvd(DisasContext *s, DisasOps *o) 2141 { 2142 TCGv_i64 t1 = tcg_temp_new_i64(); 2143 TCGv_i32 t2 = tcg_temp_new_i32(); 2144 tcg_gen_extrl_i64_i32(t2, o->in1); 2145 gen_helper_cvd(t1, t2); 2146 tcg_gen_qemu_st_i64(t1, o->in2, get_mem_index(s), MO_TEUQ); 2147 return DISAS_NEXT; 2148 } 2149 2150 static DisasJumpType op_cvdg(DisasContext *s, DisasOps *o) 2151 { 2152 TCGv_i128 t = tcg_temp_new_i128(); 2153 gen_helper_cvdg(t, o->in1); 2154 tcg_gen_qemu_st_i128(t, o->in2, get_mem_index(s), MO_TE | MO_128); 2155 return DISAS_NEXT; 2156 } 2157 2158 static DisasJumpType op_ct(DisasContext *s, DisasOps *o) 2159 { 2160 int m3 = get_field(s, m3); 2161 TCGLabel *lab = gen_new_label(); 2162 TCGCond c; 2163 2164 c = tcg_invert_cond(ltgt_cond[m3]); 2165 if (s->insn->data) { 2166 c = tcg_unsigned_cond(c); 2167 } 2168 tcg_gen_brcond_i64(c, o->in1, o->in2, lab); 2169 2170 /* Trap. */ 2171 gen_trap(s); 2172 2173 gen_set_label(lab); 2174 return DISAS_NEXT; 2175 } 2176 2177 static DisasJumpType op_cuXX(DisasContext *s, DisasOps *o) 2178 { 2179 int m3 = get_field(s, m3); 2180 int r1 = get_field(s, r1); 2181 int r2 = get_field(s, r2); 2182 TCGv_i32 tr1, tr2, chk; 2183 2184 /* R1 and R2 must both be even. */ 2185 if ((r1 | r2) & 1) { 2186 gen_program_exception(s, PGM_SPECIFICATION); 2187 return DISAS_NORETURN; 2188 } 2189 if (!s390_has_feat(S390_FEAT_ETF3_ENH)) { 2190 m3 = 0; 2191 } 2192 2193 tr1 = tcg_constant_i32(r1); 2194 tr2 = tcg_constant_i32(r2); 2195 chk = tcg_constant_i32(m3); 2196 2197 switch (s->insn->data) { 2198 case 12: 2199 gen_helper_cu12(cc_op, tcg_env, tr1, tr2, chk); 2200 break; 2201 case 14: 2202 gen_helper_cu14(cc_op, tcg_env, tr1, tr2, chk); 2203 break; 2204 case 21: 2205 gen_helper_cu21(cc_op, tcg_env, tr1, tr2, chk); 2206 break; 2207 case 24: 2208 gen_helper_cu24(cc_op, tcg_env, tr1, tr2, chk); 2209 break; 2210 case 41: 2211 gen_helper_cu41(cc_op, tcg_env, tr1, tr2, chk); 2212 break; 2213 case 42: 2214 gen_helper_cu42(cc_op, tcg_env, tr1, tr2, chk); 2215 break; 2216 default: 2217 g_assert_not_reached(); 2218 } 2219 2220 set_cc_static(s); 2221 return DISAS_NEXT; 2222 } 2223 2224 #ifndef CONFIG_USER_ONLY 2225 static DisasJumpType op_diag(DisasContext *s, DisasOps *o) 2226 { 2227 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 2228 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 2229 TCGv_i32 func_code = tcg_constant_i32(get_field(s, i2)); 2230 2231 gen_helper_diag(tcg_env, r1, r3, func_code); 2232 return DISAS_NEXT; 2233 } 2234 #endif 2235 2236 static DisasJumpType op_divs32(DisasContext *s, DisasOps *o) 2237 { 2238 gen_helper_divs32(o->out, tcg_env, o->in1, o->in2); 2239 tcg_gen_extr32_i64(o->out2, o->out, o->out); 2240 return DISAS_NEXT; 2241 } 2242 2243 static DisasJumpType op_divu32(DisasContext *s, DisasOps *o) 2244 { 2245 gen_helper_divu32(o->out, tcg_env, o->in1, o->in2); 2246 tcg_gen_extr32_i64(o->out2, o->out, o->out); 2247 return DISAS_NEXT; 2248 } 2249 2250 static DisasJumpType op_divs64(DisasContext *s, DisasOps *o) 2251 { 2252 TCGv_i128 t = tcg_temp_new_i128(); 2253 2254 gen_helper_divs64(t, tcg_env, o->in1, o->in2); 2255 tcg_gen_extr_i128_i64(o->out2, o->out, t); 2256 return DISAS_NEXT; 2257 } 2258 2259 static DisasJumpType op_divu64(DisasContext *s, DisasOps *o) 2260 { 2261 TCGv_i128 t = tcg_temp_new_i128(); 2262 2263 gen_helper_divu64(t, tcg_env, o->out, o->out2, o->in2); 2264 tcg_gen_extr_i128_i64(o->out2, o->out, t); 2265 return DISAS_NEXT; 2266 } 2267 2268 static DisasJumpType op_deb(DisasContext *s, DisasOps *o) 2269 { 2270 gen_helper_deb(o->out, tcg_env, o->in1, o->in2); 2271 return DISAS_NEXT; 2272 } 2273 2274 static DisasJumpType op_ddb(DisasContext *s, DisasOps *o) 2275 { 2276 gen_helper_ddb(o->out, tcg_env, o->in1, o->in2); 2277 return DISAS_NEXT; 2278 } 2279 2280 static DisasJumpType op_dxb(DisasContext *s, DisasOps *o) 2281 { 2282 gen_helper_dxb(o->out_128, tcg_env, o->in1_128, o->in2_128); 2283 return DISAS_NEXT; 2284 } 2285 2286 static DisasJumpType op_ear(DisasContext *s, DisasOps *o) 2287 { 2288 int r2 = get_field(s, r2); 2289 tcg_gen_ld32u_i64(o->out, tcg_env, offsetof(CPUS390XState, aregs[r2])); 2290 return DISAS_NEXT; 2291 } 2292 2293 static DisasJumpType op_ecag(DisasContext *s, DisasOps *o) 2294 { 2295 /* No cache information provided. */ 2296 tcg_gen_movi_i64(o->out, -1); 2297 return DISAS_NEXT; 2298 } 2299 2300 static DisasJumpType op_efpc(DisasContext *s, DisasOps *o) 2301 { 2302 tcg_gen_ld32u_i64(o->out, tcg_env, offsetof(CPUS390XState, fpc)); 2303 return DISAS_NEXT; 2304 } 2305 2306 static DisasJumpType op_epsw(DisasContext *s, DisasOps *o) 2307 { 2308 int r1 = get_field(s, r1); 2309 int r2 = get_field(s, r2); 2310 TCGv_i64 t = tcg_temp_new_i64(); 2311 TCGv_i64 t_cc = tcg_temp_new_i64(); 2312 2313 /* Note the "subsequently" in the PoO, which implies a defined result 2314 if r1 == r2. Thus we cannot defer these writes to an output hook. */ 2315 gen_op_calc_cc(s); 2316 tcg_gen_extu_i32_i64(t_cc, cc_op); 2317 tcg_gen_shri_i64(t, psw_mask, 32); 2318 tcg_gen_deposit_i64(t, t, t_cc, 12, 2); 2319 store_reg32_i64(r1, t); 2320 if (r2 != 0) { 2321 store_reg32_i64(r2, psw_mask); 2322 } 2323 return DISAS_NEXT; 2324 } 2325 2326 static DisasJumpType op_ex(DisasContext *s, DisasOps *o) 2327 { 2328 int r1 = get_field(s, r1); 2329 TCGv_i32 ilen; 2330 TCGv_i64 v1; 2331 2332 /* Nested EXECUTE is not allowed. */ 2333 if (unlikely(s->ex_value)) { 2334 gen_program_exception(s, PGM_EXECUTE); 2335 return DISAS_NORETURN; 2336 } 2337 2338 update_psw_addr(s); 2339 update_cc_op(s); 2340 2341 if (r1 == 0) { 2342 v1 = tcg_constant_i64(0); 2343 } else { 2344 v1 = regs[r1]; 2345 } 2346 2347 ilen = tcg_constant_i32(s->ilen); 2348 gen_helper_ex(tcg_env, ilen, v1, o->in2); 2349 2350 return DISAS_PC_CC_UPDATED; 2351 } 2352 2353 static DisasJumpType op_fieb(DisasContext *s, DisasOps *o) 2354 { 2355 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 2356 2357 if (!m34) { 2358 return DISAS_NORETURN; 2359 } 2360 gen_helper_fieb(o->out, tcg_env, o->in2, m34); 2361 return DISAS_NEXT; 2362 } 2363 2364 static DisasJumpType op_fidb(DisasContext *s, DisasOps *o) 2365 { 2366 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 2367 2368 if (!m34) { 2369 return DISAS_NORETURN; 2370 } 2371 gen_helper_fidb(o->out, tcg_env, o->in2, m34); 2372 return DISAS_NEXT; 2373 } 2374 2375 static DisasJumpType op_fixb(DisasContext *s, DisasOps *o) 2376 { 2377 TCGv_i32 m34 = fpinst_extract_m34(s, false, true); 2378 2379 if (!m34) { 2380 return DISAS_NORETURN; 2381 } 2382 gen_helper_fixb(o->out_128, tcg_env, o->in2_128, m34); 2383 return DISAS_NEXT; 2384 } 2385 2386 static DisasJumpType op_flogr(DisasContext *s, DisasOps *o) 2387 { 2388 /* We'll use the original input for cc computation, since we get to 2389 compare that against 0, which ought to be better than comparing 2390 the real output against 64. It also lets cc_dst be a convenient 2391 temporary during our computation. */ 2392 gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2); 2393 2394 /* R1 = IN ? CLZ(IN) : 64. */ 2395 tcg_gen_clzi_i64(o->out, o->in2, 64); 2396 2397 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this 2398 value by 64, which is undefined. But since the shift is 64 iff the 2399 input is zero, we still get the correct result after and'ing. */ 2400 tcg_gen_movi_i64(o->out2, 0x8000000000000000ull); 2401 tcg_gen_shr_i64(o->out2, o->out2, o->out); 2402 tcg_gen_andc_i64(o->out2, cc_dst, o->out2); 2403 return DISAS_NEXT; 2404 } 2405 2406 static DisasJumpType op_icm(DisasContext *s, DisasOps *o) 2407 { 2408 int m3 = get_field(s, m3); 2409 int pos, len, base = s->insn->data; 2410 TCGv_i64 tmp = tcg_temp_new_i64(); 2411 uint64_t ccm; 2412 2413 switch (m3) { 2414 case 0xf: 2415 /* Effectively a 32-bit load. */ 2416 tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_TEUL); 2417 len = 32; 2418 goto one_insert; 2419 2420 case 0xc: 2421 case 0x6: 2422 case 0x3: 2423 /* Effectively a 16-bit load. */ 2424 tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_TEUW); 2425 len = 16; 2426 goto one_insert; 2427 2428 case 0x8: 2429 case 0x4: 2430 case 0x2: 2431 case 0x1: 2432 /* Effectively an 8-bit load. */ 2433 tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); 2434 len = 8; 2435 goto one_insert; 2436 2437 one_insert: 2438 pos = base + ctz32(m3) * 8; 2439 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len); 2440 ccm = ((1ull << len) - 1) << pos; 2441 break; 2442 2443 case 0: 2444 /* Recognize access exceptions for the first byte. */ 2445 tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); 2446 gen_op_movi_cc(s, 0); 2447 return DISAS_NEXT; 2448 2449 default: 2450 /* This is going to be a sequence of loads and inserts. */ 2451 pos = base + 32 - 8; 2452 ccm = 0; 2453 while (m3) { 2454 if (m3 & 0x8) { 2455 tcg_gen_qemu_ld_i64(tmp, o->in2, get_mem_index(s), MO_UB); 2456 tcg_gen_addi_i64(o->in2, o->in2, 1); 2457 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8); 2458 ccm |= 0xffull << pos; 2459 } 2460 m3 = (m3 << 1) & 0xf; 2461 pos -= 8; 2462 } 2463 break; 2464 } 2465 2466 tcg_gen_movi_i64(tmp, ccm); 2467 gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out); 2468 return DISAS_NEXT; 2469 } 2470 2471 static DisasJumpType op_insi(DisasContext *s, DisasOps *o) 2472 { 2473 int shift = s->insn->data & 0xff; 2474 int size = s->insn->data >> 8; 2475 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size); 2476 return DISAS_NEXT; 2477 } 2478 2479 static DisasJumpType op_ipm(DisasContext *s, DisasOps *o) 2480 { 2481 TCGv_i64 t1, t2; 2482 2483 gen_op_calc_cc(s); 2484 t1 = tcg_temp_new_i64(); 2485 tcg_gen_extract_i64(t1, psw_mask, 40, 4); 2486 t2 = tcg_temp_new_i64(); 2487 tcg_gen_extu_i32_i64(t2, cc_op); 2488 tcg_gen_deposit_i64(t1, t1, t2, 4, 60); 2489 tcg_gen_deposit_i64(o->out, o->out, t1, 24, 8); 2490 return DISAS_NEXT; 2491 } 2492 2493 #ifndef CONFIG_USER_ONLY 2494 static DisasJumpType op_idte(DisasContext *s, DisasOps *o) 2495 { 2496 TCGv_i32 m4; 2497 2498 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { 2499 m4 = tcg_constant_i32(get_field(s, m4)); 2500 } else { 2501 m4 = tcg_constant_i32(0); 2502 } 2503 gen_helper_idte(tcg_env, o->in1, o->in2, m4); 2504 return DISAS_NEXT; 2505 } 2506 2507 static DisasJumpType op_ipte(DisasContext *s, DisasOps *o) 2508 { 2509 TCGv_i32 m4; 2510 2511 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) { 2512 m4 = tcg_constant_i32(get_field(s, m4)); 2513 } else { 2514 m4 = tcg_constant_i32(0); 2515 } 2516 gen_helper_ipte(tcg_env, o->in1, o->in2, m4); 2517 return DISAS_NEXT; 2518 } 2519 2520 static DisasJumpType op_iske(DisasContext *s, DisasOps *o) 2521 { 2522 gen_helper_iske(o->out, tcg_env, o->in2); 2523 return DISAS_NEXT; 2524 } 2525 #endif 2526 2527 static DisasJumpType op_msa(DisasContext *s, DisasOps *o) 2528 { 2529 int r1 = have_field(s, r1) ? get_field(s, r1) : 0; 2530 int r2 = have_field(s, r2) ? get_field(s, r2) : 0; 2531 int r3 = have_field(s, r3) ? get_field(s, r3) : 0; 2532 TCGv_i32 t_r1, t_r2, t_r3, type; 2533 2534 switch (s->insn->data) { 2535 case S390_FEAT_TYPE_KMA: 2536 if (r3 == r1 || r3 == r2) { 2537 gen_program_exception(s, PGM_SPECIFICATION); 2538 return DISAS_NORETURN; 2539 } 2540 /* FALL THROUGH */ 2541 case S390_FEAT_TYPE_KMCTR: 2542 if (r3 & 1 || !r3) { 2543 gen_program_exception(s, PGM_SPECIFICATION); 2544 return DISAS_NORETURN; 2545 } 2546 /* FALL THROUGH */ 2547 case S390_FEAT_TYPE_PPNO: 2548 case S390_FEAT_TYPE_KMF: 2549 case S390_FEAT_TYPE_KMC: 2550 case S390_FEAT_TYPE_KMO: 2551 case S390_FEAT_TYPE_KM: 2552 if (r1 & 1 || !r1) { 2553 gen_program_exception(s, PGM_SPECIFICATION); 2554 return DISAS_NORETURN; 2555 } 2556 /* FALL THROUGH */ 2557 case S390_FEAT_TYPE_KMAC: 2558 case S390_FEAT_TYPE_KIMD: 2559 case S390_FEAT_TYPE_KLMD: 2560 if (r2 & 1 || !r2) { 2561 gen_program_exception(s, PGM_SPECIFICATION); 2562 return DISAS_NORETURN; 2563 } 2564 /* FALL THROUGH */ 2565 case S390_FEAT_TYPE_PCKMO: 2566 case S390_FEAT_TYPE_PCC: 2567 break; 2568 default: 2569 g_assert_not_reached(); 2570 }; 2571 2572 t_r1 = tcg_constant_i32(r1); 2573 t_r2 = tcg_constant_i32(r2); 2574 t_r3 = tcg_constant_i32(r3); 2575 type = tcg_constant_i32(s->insn->data); 2576 gen_helper_msa(cc_op, tcg_env, t_r1, t_r2, t_r3, type); 2577 set_cc_static(s); 2578 return DISAS_NEXT; 2579 } 2580 2581 static DisasJumpType op_keb(DisasContext *s, DisasOps *o) 2582 { 2583 gen_helper_keb(cc_op, tcg_env, o->in1, o->in2); 2584 set_cc_static(s); 2585 return DISAS_NEXT; 2586 } 2587 2588 static DisasJumpType op_kdb(DisasContext *s, DisasOps *o) 2589 { 2590 gen_helper_kdb(cc_op, tcg_env, o->in1, o->in2); 2591 set_cc_static(s); 2592 return DISAS_NEXT; 2593 } 2594 2595 static DisasJumpType op_kxb(DisasContext *s, DisasOps *o) 2596 { 2597 gen_helper_kxb(cc_op, tcg_env, o->in1_128, o->in2_128); 2598 set_cc_static(s); 2599 return DISAS_NEXT; 2600 } 2601 2602 static DisasJumpType help_laa(DisasContext *s, DisasOps *o, bool addu64) 2603 { 2604 /* The real output is indeed the original value in memory; 2605 recompute the addition for the computation of CC. */ 2606 tcg_gen_atomic_fetch_add_i64(o->in2, o->in2, o->in1, get_mem_index(s), 2607 s->insn->data | MO_ALIGN); 2608 /* However, we need to recompute the addition for setting CC. */ 2609 if (addu64) { 2610 tcg_gen_movi_i64(cc_src, 0); 2611 tcg_gen_add2_i64(o->out, cc_src, o->in1, cc_src, o->in2, cc_src); 2612 } else { 2613 tcg_gen_add_i64(o->out, o->in1, o->in2); 2614 } 2615 return DISAS_NEXT; 2616 } 2617 2618 static DisasJumpType op_laa(DisasContext *s, DisasOps *o) 2619 { 2620 return help_laa(s, o, false); 2621 } 2622 2623 static DisasJumpType op_laa_addu64(DisasContext *s, DisasOps *o) 2624 { 2625 return help_laa(s, o, true); 2626 } 2627 2628 static DisasJumpType op_lan(DisasContext *s, DisasOps *o) 2629 { 2630 /* The real output is indeed the original value in memory; 2631 recompute the addition for the computation of CC. */ 2632 tcg_gen_atomic_fetch_and_i64(o->in2, o->in2, o->in1, get_mem_index(s), 2633 s->insn->data | MO_ALIGN); 2634 /* However, we need to recompute the operation for setting CC. */ 2635 tcg_gen_and_i64(o->out, o->in1, o->in2); 2636 return DISAS_NEXT; 2637 } 2638 2639 static DisasJumpType op_lao(DisasContext *s, DisasOps *o) 2640 { 2641 /* The real output is indeed the original value in memory; 2642 recompute the addition for the computation of CC. */ 2643 tcg_gen_atomic_fetch_or_i64(o->in2, o->in2, o->in1, get_mem_index(s), 2644 s->insn->data | MO_ALIGN); 2645 /* However, we need to recompute the operation for setting CC. */ 2646 tcg_gen_or_i64(o->out, o->in1, o->in2); 2647 return DISAS_NEXT; 2648 } 2649 2650 static DisasJumpType op_lax(DisasContext *s, DisasOps *o) 2651 { 2652 /* The real output is indeed the original value in memory; 2653 recompute the addition for the computation of CC. */ 2654 tcg_gen_atomic_fetch_xor_i64(o->in2, o->in2, o->in1, get_mem_index(s), 2655 s->insn->data | MO_ALIGN); 2656 /* However, we need to recompute the operation for setting CC. */ 2657 tcg_gen_xor_i64(o->out, o->in1, o->in2); 2658 return DISAS_NEXT; 2659 } 2660 2661 static DisasJumpType op_ldeb(DisasContext *s, DisasOps *o) 2662 { 2663 gen_helper_ldeb(o->out, tcg_env, o->in2); 2664 return DISAS_NEXT; 2665 } 2666 2667 static DisasJumpType op_ledb(DisasContext *s, DisasOps *o) 2668 { 2669 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 2670 2671 if (!m34) { 2672 return DISAS_NORETURN; 2673 } 2674 gen_helper_ledb(o->out, tcg_env, o->in2, m34); 2675 return DISAS_NEXT; 2676 } 2677 2678 static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o) 2679 { 2680 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 2681 2682 if (!m34) { 2683 return DISAS_NORETURN; 2684 } 2685 gen_helper_ldxb(o->out, tcg_env, o->in2_128, m34); 2686 return DISAS_NEXT; 2687 } 2688 2689 static DisasJumpType op_lexb(DisasContext *s, DisasOps *o) 2690 { 2691 TCGv_i32 m34 = fpinst_extract_m34(s, true, true); 2692 2693 if (!m34) { 2694 return DISAS_NORETURN; 2695 } 2696 gen_helper_lexb(o->out, tcg_env, o->in2_128, m34); 2697 return DISAS_NEXT; 2698 } 2699 2700 static DisasJumpType op_lxdb(DisasContext *s, DisasOps *o) 2701 { 2702 gen_helper_lxdb(o->out_128, tcg_env, o->in2); 2703 return DISAS_NEXT; 2704 } 2705 2706 static DisasJumpType op_lxeb(DisasContext *s, DisasOps *o) 2707 { 2708 gen_helper_lxeb(o->out_128, tcg_env, o->in2); 2709 return DISAS_NEXT; 2710 } 2711 2712 static DisasJumpType op_lde(DisasContext *s, DisasOps *o) 2713 { 2714 tcg_gen_shli_i64(o->out, o->in2, 32); 2715 return DISAS_NEXT; 2716 } 2717 2718 static DisasJumpType op_llgt(DisasContext *s, DisasOps *o) 2719 { 2720 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); 2721 return DISAS_NEXT; 2722 } 2723 2724 static DisasJumpType op_ld8s(DisasContext *s, DisasOps *o) 2725 { 2726 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_SB); 2727 return DISAS_NEXT; 2728 } 2729 2730 static DisasJumpType op_ld8u(DisasContext *s, DisasOps *o) 2731 { 2732 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_UB); 2733 return DISAS_NEXT; 2734 } 2735 2736 static DisasJumpType op_ld16s(DisasContext *s, DisasOps *o) 2737 { 2738 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TESW); 2739 return DISAS_NEXT; 2740 } 2741 2742 static DisasJumpType op_ld16u(DisasContext *s, DisasOps *o) 2743 { 2744 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUW); 2745 return DISAS_NEXT; 2746 } 2747 2748 static DisasJumpType op_ld32s(DisasContext *s, DisasOps *o) 2749 { 2750 tcg_gen_qemu_ld_tl(o->out, o->in2, get_mem_index(s), 2751 MO_TESL | s->insn->data); 2752 return DISAS_NEXT; 2753 } 2754 2755 static DisasJumpType op_ld32u(DisasContext *s, DisasOps *o) 2756 { 2757 tcg_gen_qemu_ld_tl(o->out, o->in2, get_mem_index(s), 2758 MO_TEUL | s->insn->data); 2759 return DISAS_NEXT; 2760 } 2761 2762 static DisasJumpType op_ld64(DisasContext *s, DisasOps *o) 2763 { 2764 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), 2765 MO_TEUQ | s->insn->data); 2766 return DISAS_NEXT; 2767 } 2768 2769 static DisasJumpType op_lat(DisasContext *s, DisasOps *o) 2770 { 2771 TCGLabel *lab = gen_new_label(); 2772 store_reg32_i64(get_field(s, r1), o->in2); 2773 /* The value is stored even in case of trap. */ 2774 tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); 2775 gen_trap(s); 2776 gen_set_label(lab); 2777 return DISAS_NEXT; 2778 } 2779 2780 static DisasJumpType op_lgat(DisasContext *s, DisasOps *o) 2781 { 2782 TCGLabel *lab = gen_new_label(); 2783 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUQ); 2784 /* The value is stored even in case of trap. */ 2785 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); 2786 gen_trap(s); 2787 gen_set_label(lab); 2788 return DISAS_NEXT; 2789 } 2790 2791 static DisasJumpType op_lfhat(DisasContext *s, DisasOps *o) 2792 { 2793 TCGLabel *lab = gen_new_label(); 2794 store_reg32h_i64(get_field(s, r1), o->in2); 2795 /* The value is stored even in case of trap. */ 2796 tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); 2797 gen_trap(s); 2798 gen_set_label(lab); 2799 return DISAS_NEXT; 2800 } 2801 2802 static DisasJumpType op_llgfat(DisasContext *s, DisasOps *o) 2803 { 2804 TCGLabel *lab = gen_new_label(); 2805 2806 tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s), MO_TEUL); 2807 /* The value is stored even in case of trap. */ 2808 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); 2809 gen_trap(s); 2810 gen_set_label(lab); 2811 return DISAS_NEXT; 2812 } 2813 2814 static DisasJumpType op_llgtat(DisasContext *s, DisasOps *o) 2815 { 2816 TCGLabel *lab = gen_new_label(); 2817 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); 2818 /* The value is stored even in case of trap. */ 2819 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); 2820 gen_trap(s); 2821 gen_set_label(lab); 2822 return DISAS_NEXT; 2823 } 2824 2825 static DisasJumpType op_loc(DisasContext *s, DisasOps *o) 2826 { 2827 DisasCompare c; 2828 2829 if (have_field(s, m3)) { 2830 /* LOAD * ON CONDITION */ 2831 disas_jcc(s, &c, get_field(s, m3)); 2832 } else { 2833 /* SELECT */ 2834 disas_jcc(s, &c, get_field(s, m4)); 2835 } 2836 2837 if (c.is_64) { 2838 tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b, 2839 o->in2, o->in1); 2840 } else { 2841 TCGv_i32 t32 = tcg_temp_new_i32(); 2842 TCGv_i64 t, z; 2843 2844 tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b); 2845 2846 t = tcg_temp_new_i64(); 2847 tcg_gen_extu_i32_i64(t, t32); 2848 2849 z = tcg_constant_i64(0); 2850 tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1); 2851 } 2852 2853 return DISAS_NEXT; 2854 } 2855 2856 #ifndef CONFIG_USER_ONLY 2857 static DisasJumpType op_lctl(DisasContext *s, DisasOps *o) 2858 { 2859 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 2860 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 2861 2862 gen_helper_lctl(tcg_env, r1, o->in2, r3); 2863 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ 2864 s->exit_to_mainloop = true; 2865 return DISAS_TOO_MANY; 2866 } 2867 2868 static DisasJumpType op_lctlg(DisasContext *s, DisasOps *o) 2869 { 2870 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 2871 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 2872 2873 gen_helper_lctlg(tcg_env, r1, o->in2, r3); 2874 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ 2875 s->exit_to_mainloop = true; 2876 return DISAS_TOO_MANY; 2877 } 2878 2879 static DisasJumpType op_lra(DisasContext *s, DisasOps *o) 2880 { 2881 gen_helper_lra(o->out, tcg_env, o->out, o->in2); 2882 set_cc_static(s); 2883 return DISAS_NEXT; 2884 } 2885 2886 static DisasJumpType op_lpp(DisasContext *s, DisasOps *o) 2887 { 2888 tcg_gen_st_i64(o->in2, tcg_env, offsetof(CPUS390XState, pp)); 2889 return DISAS_NEXT; 2890 } 2891 2892 static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o) 2893 { 2894 TCGv_i64 mask, addr; 2895 2896 per_breaking_event(s); 2897 2898 /* 2899 * Convert the short PSW into the normal PSW, similar to what 2900 * s390_cpu_load_normal() does. 2901 */ 2902 mask = tcg_temp_new_i64(); 2903 addr = tcg_temp_new_i64(); 2904 tcg_gen_qemu_ld_i64(mask, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN_8); 2905 tcg_gen_andi_i64(addr, mask, PSW_MASK_SHORT_ADDR); 2906 tcg_gen_andi_i64(mask, mask, PSW_MASK_SHORT_CTRL); 2907 tcg_gen_xori_i64(mask, mask, PSW_MASK_SHORTPSW); 2908 gen_helper_load_psw(tcg_env, mask, addr); 2909 return DISAS_NORETURN; 2910 } 2911 2912 static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o) 2913 { 2914 TCGv_i64 t1, t2; 2915 2916 per_breaking_event(s); 2917 2918 t1 = tcg_temp_new_i64(); 2919 t2 = tcg_temp_new_i64(); 2920 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), 2921 MO_TEUQ | MO_ALIGN_8); 2922 tcg_gen_addi_i64(o->in2, o->in2, 8); 2923 tcg_gen_qemu_ld_i64(t2, o->in2, get_mem_index(s), MO_TEUQ); 2924 gen_helper_load_psw(tcg_env, t1, t2); 2925 return DISAS_NORETURN; 2926 } 2927 #endif 2928 2929 static DisasJumpType op_lam(DisasContext *s, DisasOps *o) 2930 { 2931 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 2932 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 2933 2934 gen_helper_lam(tcg_env, r1, o->in2, r3); 2935 return DISAS_NEXT; 2936 } 2937 2938 static DisasJumpType op_lm32(DisasContext *s, DisasOps *o) 2939 { 2940 int r1 = get_field(s, r1); 2941 int r3 = get_field(s, r3); 2942 TCGv_i64 t1, t2; 2943 2944 /* Only one register to read. */ 2945 t1 = tcg_temp_new_i64(); 2946 if (unlikely(r1 == r3)) { 2947 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 2948 store_reg32_i64(r1, t1); 2949 return DISAS_NEXT; 2950 } 2951 2952 /* First load the values of the first and last registers to trigger 2953 possible page faults. */ 2954 t2 = tcg_temp_new_i64(); 2955 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 2956 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15)); 2957 tcg_gen_qemu_ld_i64(t2, t2, get_mem_index(s), MO_TEUL); 2958 store_reg32_i64(r1, t1); 2959 store_reg32_i64(r3, t2); 2960 2961 /* Only two registers to read. */ 2962 if (((r1 + 1) & 15) == r3) { 2963 return DISAS_NEXT; 2964 } 2965 2966 /* Then load the remaining registers. Page fault can't occur. */ 2967 r3 = (r3 - 1) & 15; 2968 tcg_gen_movi_i64(t2, 4); 2969 while (r1 != r3) { 2970 r1 = (r1 + 1) & 15; 2971 tcg_gen_add_i64(o->in2, o->in2, t2); 2972 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 2973 store_reg32_i64(r1, t1); 2974 } 2975 return DISAS_NEXT; 2976 } 2977 2978 static DisasJumpType op_lmh(DisasContext *s, DisasOps *o) 2979 { 2980 int r1 = get_field(s, r1); 2981 int r3 = get_field(s, r3); 2982 TCGv_i64 t1, t2; 2983 2984 /* Only one register to read. */ 2985 t1 = tcg_temp_new_i64(); 2986 if (unlikely(r1 == r3)) { 2987 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 2988 store_reg32h_i64(r1, t1); 2989 return DISAS_NEXT; 2990 } 2991 2992 /* First load the values of the first and last registers to trigger 2993 possible page faults. */ 2994 t2 = tcg_temp_new_i64(); 2995 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 2996 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15)); 2997 tcg_gen_qemu_ld_i64(t2, t2, get_mem_index(s), MO_TEUL); 2998 store_reg32h_i64(r1, t1); 2999 store_reg32h_i64(r3, t2); 3000 3001 /* Only two registers to read. */ 3002 if (((r1 + 1) & 15) == r3) { 3003 return DISAS_NEXT; 3004 } 3005 3006 /* Then load the remaining registers. Page fault can't occur. */ 3007 r3 = (r3 - 1) & 15; 3008 tcg_gen_movi_i64(t2, 4); 3009 while (r1 != r3) { 3010 r1 = (r1 + 1) & 15; 3011 tcg_gen_add_i64(o->in2, o->in2, t2); 3012 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUL); 3013 store_reg32h_i64(r1, t1); 3014 } 3015 return DISAS_NEXT; 3016 } 3017 3018 static DisasJumpType op_lm64(DisasContext *s, DisasOps *o) 3019 { 3020 int r1 = get_field(s, r1); 3021 int r3 = get_field(s, r3); 3022 TCGv_i64 t1, t2; 3023 3024 /* Only one register to read. */ 3025 if (unlikely(r1 == r3)) { 3026 tcg_gen_qemu_ld_i64(regs[r1], o->in2, get_mem_index(s), MO_TEUQ); 3027 return DISAS_NEXT; 3028 } 3029 3030 /* First load the values of the first and last registers to trigger 3031 possible page faults. */ 3032 t1 = tcg_temp_new_i64(); 3033 t2 = tcg_temp_new_i64(); 3034 tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), MO_TEUQ); 3035 tcg_gen_addi_i64(t2, o->in2, 8 * ((r3 - r1) & 15)); 3036 tcg_gen_qemu_ld_i64(regs[r3], t2, get_mem_index(s), MO_TEUQ); 3037 tcg_gen_mov_i64(regs[r1], t1); 3038 3039 /* Only two registers to read. */ 3040 if (((r1 + 1) & 15) == r3) { 3041 return DISAS_NEXT; 3042 } 3043 3044 /* Then load the remaining registers. Page fault can't occur. */ 3045 r3 = (r3 - 1) & 15; 3046 tcg_gen_movi_i64(t1, 8); 3047 while (r1 != r3) { 3048 r1 = (r1 + 1) & 15; 3049 tcg_gen_add_i64(o->in2, o->in2, t1); 3050 tcg_gen_qemu_ld_i64(regs[r1], o->in2, get_mem_index(s), MO_TEUQ); 3051 } 3052 return DISAS_NEXT; 3053 } 3054 3055 static DisasJumpType op_lpd(DisasContext *s, DisasOps *o) 3056 { 3057 TCGv_i64 a1, a2; 3058 MemOp mop = s->insn->data; 3059 3060 /* In a parallel context, stop the world and single step. */ 3061 if (tb_cflags(s->base.tb) & CF_PARALLEL) { 3062 update_psw_addr(s); 3063 update_cc_op(s); 3064 gen_exception(EXCP_ATOMIC); 3065 return DISAS_NORETURN; 3066 } 3067 3068 /* In a serial context, perform the two loads ... */ 3069 a1 = get_address(s, 0, get_field(s, b1), get_field(s, d1)); 3070 a2 = get_address(s, 0, get_field(s, b2), get_field(s, d2)); 3071 tcg_gen_qemu_ld_i64(o->out, a1, get_mem_index(s), mop | MO_ALIGN); 3072 tcg_gen_qemu_ld_i64(o->out2, a2, get_mem_index(s), mop | MO_ALIGN); 3073 3074 /* ... and indicate that we performed them while interlocked. */ 3075 gen_op_movi_cc(s, 0); 3076 return DISAS_NEXT; 3077 } 3078 3079 static DisasJumpType op_lpq(DisasContext *s, DisasOps *o) 3080 { 3081 o->out_128 = tcg_temp_new_i128(); 3082 tcg_gen_qemu_ld_i128(o->out_128, o->in2, get_mem_index(s), 3083 MO_TE | MO_128 | MO_ALIGN); 3084 return DISAS_NEXT; 3085 } 3086 3087 #ifndef CONFIG_USER_ONLY 3088 static DisasJumpType op_lura(DisasContext *s, DisasOps *o) 3089 { 3090 tcg_gen_qemu_ld_tl(o->out, o->in2, MMU_REAL_IDX, s->insn->data); 3091 return DISAS_NEXT; 3092 } 3093 #endif 3094 3095 static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o) 3096 { 3097 tcg_gen_andi_i64(o->out, o->in2, -256); 3098 return DISAS_NEXT; 3099 } 3100 3101 static DisasJumpType op_lcbb(DisasContext *s, DisasOps *o) 3102 { 3103 const int64_t block_size = (1ull << (get_field(s, m3) + 6)); 3104 3105 if (get_field(s, m3) > 6) { 3106 gen_program_exception(s, PGM_SPECIFICATION); 3107 return DISAS_NORETURN; 3108 } 3109 3110 tcg_gen_ori_i64(o->addr1, o->addr1, -block_size); 3111 tcg_gen_neg_i64(o->addr1, o->addr1); 3112 tcg_gen_movi_i64(o->out, 16); 3113 tcg_gen_umin_i64(o->out, o->out, o->addr1); 3114 gen_op_update1_cc_i64(s, CC_OP_LCBB, o->out); 3115 return DISAS_NEXT; 3116 } 3117 3118 static DisasJumpType op_mc(DisasContext *s, DisasOps *o) 3119 { 3120 const uint8_t monitor_class = get_field(s, i2); 3121 3122 if (monitor_class & 0xf0) { 3123 gen_program_exception(s, PGM_SPECIFICATION); 3124 return DISAS_NORETURN; 3125 } 3126 3127 #if !defined(CONFIG_USER_ONLY) 3128 gen_helper_monitor_call(tcg_env, o->addr1, 3129 tcg_constant_i32(monitor_class)); 3130 #endif 3131 /* Defaults to a NOP. */ 3132 return DISAS_NEXT; 3133 } 3134 3135 static DisasJumpType op_mov2(DisasContext *s, DisasOps *o) 3136 { 3137 o->out = o->in2; 3138 o->in2 = NULL; 3139 return DISAS_NEXT; 3140 } 3141 3142 static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o) 3143 { 3144 int b2 = get_field(s, b2); 3145 TCGv ar1 = tcg_temp_new_i64(); 3146 int r1 = get_field(s, r1); 3147 3148 o->out = o->in2; 3149 o->in2 = NULL; 3150 3151 switch (s->base.tb->flags & FLAG_MASK_ASC) { 3152 case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT: 3153 tcg_gen_movi_i64(ar1, 0); 3154 break; 3155 case PSW_ASC_ACCREG >> FLAG_MASK_PSW_SHIFT: 3156 tcg_gen_movi_i64(ar1, 1); 3157 break; 3158 case PSW_ASC_SECONDARY >> FLAG_MASK_PSW_SHIFT: 3159 if (b2) { 3160 tcg_gen_ld32u_i64(ar1, tcg_env, offsetof(CPUS390XState, aregs[b2])); 3161 } else { 3162 tcg_gen_movi_i64(ar1, 0); 3163 } 3164 break; 3165 case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT: 3166 tcg_gen_movi_i64(ar1, 2); 3167 break; 3168 } 3169 3170 tcg_gen_st32_i64(ar1, tcg_env, offsetof(CPUS390XState, aregs[r1])); 3171 return DISAS_NEXT; 3172 } 3173 3174 static DisasJumpType op_movx(DisasContext *s, DisasOps *o) 3175 { 3176 o->out = o->in1; 3177 o->out2 = o->in2; 3178 o->in1 = NULL; 3179 o->in2 = NULL; 3180 return DISAS_NEXT; 3181 } 3182 3183 static DisasJumpType op_mvc(DisasContext *s, DisasOps *o) 3184 { 3185 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3186 3187 gen_helper_mvc(tcg_env, l, o->addr1, o->in2); 3188 return DISAS_NEXT; 3189 } 3190 3191 static DisasJumpType op_mvcrl(DisasContext *s, DisasOps *o) 3192 { 3193 gen_helper_mvcrl(tcg_env, regs[0], o->addr1, o->in2); 3194 return DISAS_NEXT; 3195 } 3196 3197 static DisasJumpType op_mvcin(DisasContext *s, DisasOps *o) 3198 { 3199 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3200 3201 gen_helper_mvcin(tcg_env, l, o->addr1, o->in2); 3202 return DISAS_NEXT; 3203 } 3204 3205 static DisasJumpType op_mvcl(DisasContext *s, DisasOps *o) 3206 { 3207 int r1 = get_field(s, r1); 3208 int r2 = get_field(s, r2); 3209 TCGv_i32 t1, t2; 3210 3211 /* r1 and r2 must be even. */ 3212 if (r1 & 1 || r2 & 1) { 3213 gen_program_exception(s, PGM_SPECIFICATION); 3214 return DISAS_NORETURN; 3215 } 3216 3217 t1 = tcg_constant_i32(r1); 3218 t2 = tcg_constant_i32(r2); 3219 gen_helper_mvcl(cc_op, tcg_env, t1, t2); 3220 set_cc_static(s); 3221 return DISAS_NEXT; 3222 } 3223 3224 static DisasJumpType op_mvcle(DisasContext *s, DisasOps *o) 3225 { 3226 int r1 = get_field(s, r1); 3227 int r3 = get_field(s, r3); 3228 TCGv_i32 t1, t3; 3229 3230 /* r1 and r3 must be even. */ 3231 if (r1 & 1 || r3 & 1) { 3232 gen_program_exception(s, PGM_SPECIFICATION); 3233 return DISAS_NORETURN; 3234 } 3235 3236 t1 = tcg_constant_i32(r1); 3237 t3 = tcg_constant_i32(r3); 3238 gen_helper_mvcle(cc_op, tcg_env, t1, o->in2, t3); 3239 set_cc_static(s); 3240 return DISAS_NEXT; 3241 } 3242 3243 static DisasJumpType op_mvclu(DisasContext *s, DisasOps *o) 3244 { 3245 int r1 = get_field(s, r1); 3246 int r3 = get_field(s, r3); 3247 TCGv_i32 t1, t3; 3248 3249 /* r1 and r3 must be even. */ 3250 if (r1 & 1 || r3 & 1) { 3251 gen_program_exception(s, PGM_SPECIFICATION); 3252 return DISAS_NORETURN; 3253 } 3254 3255 t1 = tcg_constant_i32(r1); 3256 t3 = tcg_constant_i32(r3); 3257 gen_helper_mvclu(cc_op, tcg_env, t1, o->in2, t3); 3258 set_cc_static(s); 3259 return DISAS_NEXT; 3260 } 3261 3262 static DisasJumpType op_mvcos(DisasContext *s, DisasOps *o) 3263 { 3264 int r3 = get_field(s, r3); 3265 gen_helper_mvcos(cc_op, tcg_env, o->addr1, o->in2, regs[r3]); 3266 set_cc_static(s); 3267 return DISAS_NEXT; 3268 } 3269 3270 #ifndef CONFIG_USER_ONLY 3271 static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o) 3272 { 3273 int r1 = get_field(s, l1); 3274 int r3 = get_field(s, r3); 3275 gen_helper_mvcp(cc_op, tcg_env, regs[r1], o->addr1, o->in2, regs[r3]); 3276 set_cc_static(s); 3277 return DISAS_NEXT; 3278 } 3279 3280 static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o) 3281 { 3282 int r1 = get_field(s, l1); 3283 int r3 = get_field(s, r3); 3284 gen_helper_mvcs(cc_op, tcg_env, regs[r1], o->addr1, o->in2, regs[r3]); 3285 set_cc_static(s); 3286 return DISAS_NEXT; 3287 } 3288 #endif 3289 3290 static DisasJumpType op_mvn(DisasContext *s, DisasOps *o) 3291 { 3292 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3293 3294 gen_helper_mvn(tcg_env, l, o->addr1, o->in2); 3295 return DISAS_NEXT; 3296 } 3297 3298 static DisasJumpType op_mvo(DisasContext *s, DisasOps *o) 3299 { 3300 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3301 3302 gen_helper_mvo(tcg_env, l, o->addr1, o->in2); 3303 return DISAS_NEXT; 3304 } 3305 3306 static DisasJumpType op_mvpg(DisasContext *s, DisasOps *o) 3307 { 3308 TCGv_i32 t1 = tcg_constant_i32(get_field(s, r1)); 3309 TCGv_i32 t2 = tcg_constant_i32(get_field(s, r2)); 3310 3311 gen_helper_mvpg(cc_op, tcg_env, regs[0], t1, t2); 3312 set_cc_static(s); 3313 return DISAS_NEXT; 3314 } 3315 3316 static DisasJumpType op_mvst(DisasContext *s, DisasOps *o) 3317 { 3318 TCGv_i32 t1 = tcg_constant_i32(get_field(s, r1)); 3319 TCGv_i32 t2 = tcg_constant_i32(get_field(s, r2)); 3320 3321 gen_helper_mvst(cc_op, tcg_env, t1, t2); 3322 set_cc_static(s); 3323 return DISAS_NEXT; 3324 } 3325 3326 static DisasJumpType op_mvz(DisasContext *s, DisasOps *o) 3327 { 3328 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3329 3330 gen_helper_mvz(tcg_env, l, o->addr1, o->in2); 3331 return DISAS_NEXT; 3332 } 3333 3334 static DisasJumpType op_mul(DisasContext *s, DisasOps *o) 3335 { 3336 tcg_gen_mul_i64(o->out, o->in1, o->in2); 3337 return DISAS_NEXT; 3338 } 3339 3340 static DisasJumpType op_mul128(DisasContext *s, DisasOps *o) 3341 { 3342 tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2); 3343 return DISAS_NEXT; 3344 } 3345 3346 static DisasJumpType op_muls128(DisasContext *s, DisasOps *o) 3347 { 3348 tcg_gen_muls2_i64(o->out2, o->out, o->in1, o->in2); 3349 return DISAS_NEXT; 3350 } 3351 3352 static DisasJumpType op_meeb(DisasContext *s, DisasOps *o) 3353 { 3354 gen_helper_meeb(o->out, tcg_env, o->in1, o->in2); 3355 return DISAS_NEXT; 3356 } 3357 3358 static DisasJumpType op_mdeb(DisasContext *s, DisasOps *o) 3359 { 3360 gen_helper_mdeb(o->out, tcg_env, o->in1, o->in2); 3361 return DISAS_NEXT; 3362 } 3363 3364 static DisasJumpType op_mdb(DisasContext *s, DisasOps *o) 3365 { 3366 gen_helper_mdb(o->out, tcg_env, o->in1, o->in2); 3367 return DISAS_NEXT; 3368 } 3369 3370 static DisasJumpType op_mxb(DisasContext *s, DisasOps *o) 3371 { 3372 gen_helper_mxb(o->out_128, tcg_env, o->in1_128, o->in2_128); 3373 return DISAS_NEXT; 3374 } 3375 3376 static DisasJumpType op_mxdb(DisasContext *s, DisasOps *o) 3377 { 3378 gen_helper_mxdb(o->out_128, tcg_env, o->in1, o->in2); 3379 return DISAS_NEXT; 3380 } 3381 3382 static DisasJumpType op_maeb(DisasContext *s, DisasOps *o) 3383 { 3384 TCGv_i64 r3 = load_freg32_i64(get_field(s, r3)); 3385 gen_helper_maeb(o->out, tcg_env, o->in1, o->in2, r3); 3386 return DISAS_NEXT; 3387 } 3388 3389 static DisasJumpType op_madb(DisasContext *s, DisasOps *o) 3390 { 3391 TCGv_i64 r3 = load_freg(get_field(s, r3)); 3392 gen_helper_madb(o->out, tcg_env, o->in1, o->in2, r3); 3393 return DISAS_NEXT; 3394 } 3395 3396 static DisasJumpType op_mseb(DisasContext *s, DisasOps *o) 3397 { 3398 TCGv_i64 r3 = load_freg32_i64(get_field(s, r3)); 3399 gen_helper_mseb(o->out, tcg_env, o->in1, o->in2, r3); 3400 return DISAS_NEXT; 3401 } 3402 3403 static DisasJumpType op_msdb(DisasContext *s, DisasOps *o) 3404 { 3405 TCGv_i64 r3 = load_freg(get_field(s, r3)); 3406 gen_helper_msdb(o->out, tcg_env, o->in1, o->in2, r3); 3407 return DISAS_NEXT; 3408 } 3409 3410 static DisasJumpType op_nabs(DisasContext *s, DisasOps *o) 3411 { 3412 TCGv_i64 z = tcg_constant_i64(0); 3413 TCGv_i64 n = tcg_temp_new_i64(); 3414 3415 tcg_gen_neg_i64(n, o->in2); 3416 tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2); 3417 return DISAS_NEXT; 3418 } 3419 3420 static DisasJumpType op_nabsf32(DisasContext *s, DisasOps *o) 3421 { 3422 tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull); 3423 return DISAS_NEXT; 3424 } 3425 3426 static DisasJumpType op_nabsf64(DisasContext *s, DisasOps *o) 3427 { 3428 tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull); 3429 return DISAS_NEXT; 3430 } 3431 3432 static DisasJumpType op_nabsf128(DisasContext *s, DisasOps *o) 3433 { 3434 tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull); 3435 tcg_gen_mov_i64(o->out2, o->in2); 3436 return DISAS_NEXT; 3437 } 3438 3439 static DisasJumpType op_nc(DisasContext *s, DisasOps *o) 3440 { 3441 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3442 3443 gen_helper_nc(cc_op, tcg_env, l, o->addr1, o->in2); 3444 set_cc_static(s); 3445 return DISAS_NEXT; 3446 } 3447 3448 static DisasJumpType op_neg(DisasContext *s, DisasOps *o) 3449 { 3450 tcg_gen_neg_i64(o->out, o->in2); 3451 return DISAS_NEXT; 3452 } 3453 3454 static DisasJumpType op_negf32(DisasContext *s, DisasOps *o) 3455 { 3456 tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull); 3457 return DISAS_NEXT; 3458 } 3459 3460 static DisasJumpType op_negf64(DisasContext *s, DisasOps *o) 3461 { 3462 tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull); 3463 return DISAS_NEXT; 3464 } 3465 3466 static DisasJumpType op_negf128(DisasContext *s, DisasOps *o) 3467 { 3468 tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull); 3469 tcg_gen_mov_i64(o->out2, o->in2); 3470 return DISAS_NEXT; 3471 } 3472 3473 static DisasJumpType op_oc(DisasContext *s, DisasOps *o) 3474 { 3475 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3476 3477 gen_helper_oc(cc_op, tcg_env, l, o->addr1, o->in2); 3478 set_cc_static(s); 3479 return DISAS_NEXT; 3480 } 3481 3482 static DisasJumpType op_or(DisasContext *s, DisasOps *o) 3483 { 3484 tcg_gen_or_i64(o->out, o->in1, o->in2); 3485 return DISAS_NEXT; 3486 } 3487 3488 static DisasJumpType op_ori(DisasContext *s, DisasOps *o) 3489 { 3490 int shift = s->insn->data & 0xff; 3491 int size = s->insn->data >> 8; 3492 uint64_t mask = ((1ull << size) - 1) << shift; 3493 TCGv_i64 t = tcg_temp_new_i64(); 3494 3495 tcg_gen_shli_i64(t, o->in2, shift); 3496 tcg_gen_or_i64(o->out, o->in1, t); 3497 3498 /* Produce the CC from only the bits manipulated. */ 3499 tcg_gen_andi_i64(cc_dst, o->out, mask); 3500 set_cc_nz_u64(s, cc_dst); 3501 return DISAS_NEXT; 3502 } 3503 3504 static DisasJumpType op_oi(DisasContext *s, DisasOps *o) 3505 { 3506 o->in1 = tcg_temp_new_i64(); 3507 3508 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 3509 tcg_gen_qemu_ld_tl(o->in1, o->addr1, get_mem_index(s), s->insn->data); 3510 } else { 3511 /* Perform the atomic operation in memory. */ 3512 tcg_gen_atomic_fetch_or_i64(o->in1, o->addr1, o->in2, get_mem_index(s), 3513 s->insn->data); 3514 } 3515 3516 /* Recompute also for atomic case: needed for setting CC. */ 3517 tcg_gen_or_i64(o->out, o->in1, o->in2); 3518 3519 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 3520 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); 3521 } 3522 return DISAS_NEXT; 3523 } 3524 3525 static DisasJumpType op_pack(DisasContext *s, DisasOps *o) 3526 { 3527 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 3528 3529 gen_helper_pack(tcg_env, l, o->addr1, o->in2); 3530 return DISAS_NEXT; 3531 } 3532 3533 static DisasJumpType op_pka(DisasContext *s, DisasOps *o) 3534 { 3535 int l2 = get_field(s, l2) + 1; 3536 TCGv_i32 l; 3537 3538 /* The length must not exceed 32 bytes. */ 3539 if (l2 > 32) { 3540 gen_program_exception(s, PGM_SPECIFICATION); 3541 return DISAS_NORETURN; 3542 } 3543 l = tcg_constant_i32(l2); 3544 gen_helper_pka(tcg_env, o->addr1, o->in2, l); 3545 return DISAS_NEXT; 3546 } 3547 3548 static DisasJumpType op_pku(DisasContext *s, DisasOps *o) 3549 { 3550 int l2 = get_field(s, l2) + 1; 3551 TCGv_i32 l; 3552 3553 /* The length must be even and should not exceed 64 bytes. */ 3554 if ((l2 & 1) || (l2 > 64)) { 3555 gen_program_exception(s, PGM_SPECIFICATION); 3556 return DISAS_NORETURN; 3557 } 3558 l = tcg_constant_i32(l2); 3559 gen_helper_pku(tcg_env, o->addr1, o->in2, l); 3560 return DISAS_NEXT; 3561 } 3562 3563 static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o) 3564 { 3565 const uint8_t m3 = get_field(s, m3); 3566 3567 if ((m3 & 8) && s390_has_feat(S390_FEAT_MISC_INSTRUCTION_EXT3)) { 3568 tcg_gen_ctpop_i64(o->out, o->in2); 3569 } else { 3570 gen_helper_popcnt(o->out, o->in2); 3571 } 3572 return DISAS_NEXT; 3573 } 3574 3575 #ifndef CONFIG_USER_ONLY 3576 static DisasJumpType op_ptlb(DisasContext *s, DisasOps *o) 3577 { 3578 gen_helper_ptlb(tcg_env); 3579 return DISAS_NEXT; 3580 } 3581 #endif 3582 3583 static DisasJumpType op_risbg(DisasContext *s, DisasOps *o) 3584 { 3585 int i3 = get_field(s, i3); 3586 int i4 = get_field(s, i4); 3587 int i5 = get_field(s, i5); 3588 int do_zero = i4 & 0x80; 3589 uint64_t mask, imask, pmask; 3590 int pos, len, rot; 3591 3592 /* Adjust the arguments for the specific insn. */ 3593 switch (s->fields.op2) { 3594 case 0x55: /* risbg */ 3595 case 0x59: /* risbgn */ 3596 i3 &= 63; 3597 i4 &= 63; 3598 pmask = ~0; 3599 break; 3600 case 0x5d: /* risbhg */ 3601 i3 &= 31; 3602 i4 &= 31; 3603 pmask = 0xffffffff00000000ull; 3604 break; 3605 case 0x51: /* risblg */ 3606 i3 = (i3 & 31) + 32; 3607 i4 = (i4 & 31) + 32; 3608 pmask = 0x00000000ffffffffull; 3609 break; 3610 default: 3611 g_assert_not_reached(); 3612 } 3613 3614 /* MASK is the set of bits to be inserted from R2. */ 3615 if (i3 <= i4) { 3616 /* [0...i3---i4...63] */ 3617 mask = (-1ull >> i3) & (-1ull << (63 - i4)); 3618 } else { 3619 /* [0---i4...i3---63] */ 3620 mask = (-1ull >> i3) | (-1ull << (63 - i4)); 3621 } 3622 /* For RISBLG/RISBHG, the wrapping is limited to the high/low doubleword. */ 3623 mask &= pmask; 3624 3625 /* IMASK is the set of bits to be kept from R1. In the case of the high/low 3626 insns, we need to keep the other half of the register. */ 3627 imask = ~mask | ~pmask; 3628 if (do_zero) { 3629 imask = ~pmask; 3630 } 3631 3632 len = i4 - i3 + 1; 3633 pos = 63 - i4; 3634 rot = i5 & 63; 3635 3636 /* In some cases we can implement this with extract. */ 3637 if (imask == 0 && pos == 0 && len > 0 && len <= rot) { 3638 tcg_gen_extract_i64(o->out, o->in2, 64 - rot, len); 3639 return DISAS_NEXT; 3640 } 3641 3642 /* In some cases we can implement this with deposit. */ 3643 if (len > 0 && (imask == 0 || ~mask == imask)) { 3644 /* Note that we rotate the bits to be inserted to the lsb, not to 3645 the position as described in the PoO. */ 3646 rot = (rot - pos) & 63; 3647 } else { 3648 pos = -1; 3649 } 3650 3651 /* Rotate the input as necessary. */ 3652 tcg_gen_rotli_i64(o->in2, o->in2, rot); 3653 3654 /* Insert the selected bits into the output. */ 3655 if (pos >= 0) { 3656 if (imask == 0) { 3657 tcg_gen_deposit_z_i64(o->out, o->in2, pos, len); 3658 } else { 3659 tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len); 3660 } 3661 } else if (imask == 0) { 3662 tcg_gen_andi_i64(o->out, o->in2, mask); 3663 } else { 3664 tcg_gen_andi_i64(o->in2, o->in2, mask); 3665 tcg_gen_andi_i64(o->out, o->out, imask); 3666 tcg_gen_or_i64(o->out, o->out, o->in2); 3667 } 3668 return DISAS_NEXT; 3669 } 3670 3671 static DisasJumpType op_rosbg(DisasContext *s, DisasOps *o) 3672 { 3673 int i3 = get_field(s, i3); 3674 int i4 = get_field(s, i4); 3675 int i5 = get_field(s, i5); 3676 TCGv_i64 orig_out; 3677 uint64_t mask; 3678 3679 /* If this is a test-only form, arrange to discard the result. */ 3680 if (i3 & 0x80) { 3681 tcg_debug_assert(o->out != NULL); 3682 orig_out = o->out; 3683 o->out = tcg_temp_new_i64(); 3684 tcg_gen_mov_i64(o->out, orig_out); 3685 } 3686 3687 i3 &= 63; 3688 i4 &= 63; 3689 i5 &= 63; 3690 3691 /* MASK is the set of bits to be operated on from R2. 3692 Take care for I3/I4 wraparound. */ 3693 mask = ~0ull >> i3; 3694 if (i3 <= i4) { 3695 mask ^= ~0ull >> i4 >> 1; 3696 } else { 3697 mask |= ~(~0ull >> i4 >> 1); 3698 } 3699 3700 /* Rotate the input as necessary. */ 3701 tcg_gen_rotli_i64(o->in2, o->in2, i5); 3702 3703 /* Operate. */ 3704 switch (s->fields.op2) { 3705 case 0x54: /* AND */ 3706 tcg_gen_ori_i64(o->in2, o->in2, ~mask); 3707 tcg_gen_and_i64(o->out, o->out, o->in2); 3708 break; 3709 case 0x56: /* OR */ 3710 tcg_gen_andi_i64(o->in2, o->in2, mask); 3711 tcg_gen_or_i64(o->out, o->out, o->in2); 3712 break; 3713 case 0x57: /* XOR */ 3714 tcg_gen_andi_i64(o->in2, o->in2, mask); 3715 tcg_gen_xor_i64(o->out, o->out, o->in2); 3716 break; 3717 default: 3718 abort(); 3719 } 3720 3721 /* Set the CC. */ 3722 tcg_gen_andi_i64(cc_dst, o->out, mask); 3723 set_cc_nz_u64(s, cc_dst); 3724 return DISAS_NEXT; 3725 } 3726 3727 static DisasJumpType op_rev16(DisasContext *s, DisasOps *o) 3728 { 3729 tcg_gen_bswap16_i64(o->out, o->in2, TCG_BSWAP_IZ | TCG_BSWAP_OZ); 3730 return DISAS_NEXT; 3731 } 3732 3733 static DisasJumpType op_rev32(DisasContext *s, DisasOps *o) 3734 { 3735 tcg_gen_bswap32_i64(o->out, o->in2, TCG_BSWAP_IZ | TCG_BSWAP_OZ); 3736 return DISAS_NEXT; 3737 } 3738 3739 static DisasJumpType op_rev64(DisasContext *s, DisasOps *o) 3740 { 3741 tcg_gen_bswap64_i64(o->out, o->in2); 3742 return DISAS_NEXT; 3743 } 3744 3745 static DisasJumpType op_rll32(DisasContext *s, DisasOps *o) 3746 { 3747 TCGv_i32 t1 = tcg_temp_new_i32(); 3748 TCGv_i32 t2 = tcg_temp_new_i32(); 3749 TCGv_i32 to = tcg_temp_new_i32(); 3750 tcg_gen_extrl_i64_i32(t1, o->in1); 3751 tcg_gen_extrl_i64_i32(t2, o->in2); 3752 tcg_gen_rotl_i32(to, t1, t2); 3753 tcg_gen_extu_i32_i64(o->out, to); 3754 return DISAS_NEXT; 3755 } 3756 3757 static DisasJumpType op_rll64(DisasContext *s, DisasOps *o) 3758 { 3759 tcg_gen_rotl_i64(o->out, o->in1, o->in2); 3760 return DISAS_NEXT; 3761 } 3762 3763 #ifndef CONFIG_USER_ONLY 3764 static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o) 3765 { 3766 gen_helper_rrbe(cc_op, tcg_env, o->in2); 3767 set_cc_static(s); 3768 return DISAS_NEXT; 3769 } 3770 3771 static DisasJumpType op_sacf(DisasContext *s, DisasOps *o) 3772 { 3773 gen_helper_sacf(tcg_env, o->in2); 3774 /* Addressing mode has changed, so end the block. */ 3775 return DISAS_TOO_MANY; 3776 } 3777 #endif 3778 3779 static DisasJumpType op_sam(DisasContext *s, DisasOps *o) 3780 { 3781 int sam = s->insn->data; 3782 TCGv_i64 tsam; 3783 uint64_t mask; 3784 3785 switch (sam) { 3786 case 0: 3787 mask = 0xffffff; 3788 break; 3789 case 1: 3790 mask = 0x7fffffff; 3791 break; 3792 default: 3793 mask = -1; 3794 break; 3795 } 3796 3797 /* Bizarre but true, we check the address of the current insn for the 3798 specification exception, not the next to be executed. Thus the PoO 3799 documents that Bad Things Happen two bytes before the end. */ 3800 if (s->base.pc_next & ~mask) { 3801 gen_program_exception(s, PGM_SPECIFICATION); 3802 return DISAS_NORETURN; 3803 } 3804 s->pc_tmp &= mask; 3805 3806 tsam = tcg_constant_i64(sam); 3807 tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2); 3808 3809 /* Always exit the TB, since we (may have) changed execution mode. */ 3810 return DISAS_TOO_MANY; 3811 } 3812 3813 static DisasJumpType op_sar(DisasContext *s, DisasOps *o) 3814 { 3815 int r1 = get_field(s, r1); 3816 tcg_gen_st32_i64(o->in2, tcg_env, offsetof(CPUS390XState, aregs[r1])); 3817 return DISAS_NEXT; 3818 } 3819 3820 static DisasJumpType op_seb(DisasContext *s, DisasOps *o) 3821 { 3822 gen_helper_seb(o->out, tcg_env, o->in1, o->in2); 3823 return DISAS_NEXT; 3824 } 3825 3826 static DisasJumpType op_sdb(DisasContext *s, DisasOps *o) 3827 { 3828 gen_helper_sdb(o->out, tcg_env, o->in1, o->in2); 3829 return DISAS_NEXT; 3830 } 3831 3832 static DisasJumpType op_sxb(DisasContext *s, DisasOps *o) 3833 { 3834 gen_helper_sxb(o->out_128, tcg_env, o->in1_128, o->in2_128); 3835 return DISAS_NEXT; 3836 } 3837 3838 static DisasJumpType op_sqeb(DisasContext *s, DisasOps *o) 3839 { 3840 gen_helper_sqeb(o->out, tcg_env, o->in2); 3841 return DISAS_NEXT; 3842 } 3843 3844 static DisasJumpType op_sqdb(DisasContext *s, DisasOps *o) 3845 { 3846 gen_helper_sqdb(o->out, tcg_env, o->in2); 3847 return DISAS_NEXT; 3848 } 3849 3850 static DisasJumpType op_sqxb(DisasContext *s, DisasOps *o) 3851 { 3852 gen_helper_sqxb(o->out_128, tcg_env, o->in2_128); 3853 return DISAS_NEXT; 3854 } 3855 3856 #ifndef CONFIG_USER_ONLY 3857 static DisasJumpType op_servc(DisasContext *s, DisasOps *o) 3858 { 3859 gen_helper_servc(cc_op, tcg_env, o->in2, o->in1); 3860 set_cc_static(s); 3861 return DISAS_NEXT; 3862 } 3863 3864 static DisasJumpType op_sigp(DisasContext *s, DisasOps *o) 3865 { 3866 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 3867 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 3868 3869 gen_helper_sigp(cc_op, tcg_env, o->in2, r1, r3); 3870 set_cc_static(s); 3871 return DISAS_NEXT; 3872 } 3873 #endif 3874 3875 static DisasJumpType op_soc(DisasContext *s, DisasOps *o) 3876 { 3877 DisasCompare c; 3878 TCGv_i64 a, h; 3879 TCGLabel *lab; 3880 int r1; 3881 3882 disas_jcc(s, &c, get_field(s, m3)); 3883 3884 /* We want to store when the condition is fulfilled, so branch 3885 out when it's not */ 3886 c.cond = tcg_invert_cond(c.cond); 3887 3888 lab = gen_new_label(); 3889 if (c.is_64) { 3890 tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab); 3891 } else { 3892 tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab); 3893 } 3894 3895 r1 = get_field(s, r1); 3896 a = get_address(s, 0, get_field(s, b2), get_field(s, d2)); 3897 switch (s->insn->data) { 3898 case 1: /* STOCG */ 3899 tcg_gen_qemu_st_i64(regs[r1], a, get_mem_index(s), MO_TEUQ); 3900 break; 3901 case 0: /* STOC */ 3902 tcg_gen_qemu_st_i64(regs[r1], a, get_mem_index(s), MO_TEUL); 3903 break; 3904 case 2: /* STOCFH */ 3905 h = tcg_temp_new_i64(); 3906 tcg_gen_shri_i64(h, regs[r1], 32); 3907 tcg_gen_qemu_st_i64(h, a, get_mem_index(s), MO_TEUL); 3908 break; 3909 default: 3910 g_assert_not_reached(); 3911 } 3912 3913 gen_set_label(lab); 3914 return DISAS_NEXT; 3915 } 3916 3917 static DisasJumpType op_sla(DisasContext *s, DisasOps *o) 3918 { 3919 TCGv_i64 t; 3920 uint64_t sign = 1ull << s->insn->data; 3921 if (s->insn->data == 31) { 3922 t = tcg_temp_new_i64(); 3923 tcg_gen_shli_i64(t, o->in1, 32); 3924 } else { 3925 t = o->in1; 3926 } 3927 gen_op_update2_cc_i64(s, CC_OP_SLA, t, o->in2); 3928 tcg_gen_shl_i64(o->out, o->in1, o->in2); 3929 /* The arithmetic left shift is curious in that it does not affect 3930 the sign bit. Copy that over from the source unchanged. */ 3931 tcg_gen_andi_i64(o->out, o->out, ~sign); 3932 tcg_gen_andi_i64(o->in1, o->in1, sign); 3933 tcg_gen_or_i64(o->out, o->out, o->in1); 3934 return DISAS_NEXT; 3935 } 3936 3937 static DisasJumpType op_sll(DisasContext *s, DisasOps *o) 3938 { 3939 tcg_gen_shl_i64(o->out, o->in1, o->in2); 3940 return DISAS_NEXT; 3941 } 3942 3943 static DisasJumpType op_sra(DisasContext *s, DisasOps *o) 3944 { 3945 tcg_gen_sar_i64(o->out, o->in1, o->in2); 3946 return DISAS_NEXT; 3947 } 3948 3949 static DisasJumpType op_srl(DisasContext *s, DisasOps *o) 3950 { 3951 tcg_gen_shr_i64(o->out, o->in1, o->in2); 3952 return DISAS_NEXT; 3953 } 3954 3955 static DisasJumpType op_sfpc(DisasContext *s, DisasOps *o) 3956 { 3957 gen_helper_sfpc(tcg_env, o->in2); 3958 return DISAS_NEXT; 3959 } 3960 3961 static DisasJumpType op_sfas(DisasContext *s, DisasOps *o) 3962 { 3963 gen_helper_sfas(tcg_env, o->in2); 3964 return DISAS_NEXT; 3965 } 3966 3967 static DisasJumpType op_srnm(DisasContext *s, DisasOps *o) 3968 { 3969 /* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */ 3970 tcg_gen_andi_i64(o->addr1, o->addr1, 0x3ull); 3971 gen_helper_srnm(tcg_env, o->addr1); 3972 return DISAS_NEXT; 3973 } 3974 3975 static DisasJumpType op_srnmb(DisasContext *s, DisasOps *o) 3976 { 3977 /* Bits 0-55 are are ignored. */ 3978 tcg_gen_andi_i64(o->addr1, o->addr1, 0xffull); 3979 gen_helper_srnm(tcg_env, o->addr1); 3980 return DISAS_NEXT; 3981 } 3982 3983 static DisasJumpType op_srnmt(DisasContext *s, DisasOps *o) 3984 { 3985 TCGv_i64 tmp = tcg_temp_new_i64(); 3986 3987 /* Bits other than 61-63 are ignored. */ 3988 tcg_gen_andi_i64(o->addr1, o->addr1, 0x7ull); 3989 3990 /* No need to call a helper, we don't implement dfp */ 3991 tcg_gen_ld32u_i64(tmp, tcg_env, offsetof(CPUS390XState, fpc)); 3992 tcg_gen_deposit_i64(tmp, tmp, o->addr1, 4, 3); 3993 tcg_gen_st32_i64(tmp, tcg_env, offsetof(CPUS390XState, fpc)); 3994 return DISAS_NEXT; 3995 } 3996 3997 static DisasJumpType op_spm(DisasContext *s, DisasOps *o) 3998 { 3999 tcg_gen_extrl_i64_i32(cc_op, o->in1); 4000 tcg_gen_extract_i32(cc_op, cc_op, 28, 2); 4001 set_cc_static(s); 4002 4003 tcg_gen_shri_i64(o->in1, o->in1, 24); 4004 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in1, PSW_SHIFT_MASK_PM, 4); 4005 return DISAS_NEXT; 4006 } 4007 4008 static DisasJumpType op_ectg(DisasContext *s, DisasOps *o) 4009 { 4010 int b1 = get_field(s, b1); 4011 int d1 = get_field(s, d1); 4012 int b2 = get_field(s, b2); 4013 int d2 = get_field(s, d2); 4014 int r3 = get_field(s, r3); 4015 TCGv_i64 tmp = tcg_temp_new_i64(); 4016 4017 /* fetch all operands first */ 4018 o->in1 = tcg_temp_new_i64(); 4019 tcg_gen_addi_i64(o->in1, regs[b1], d1); 4020 o->in2 = tcg_temp_new_i64(); 4021 tcg_gen_addi_i64(o->in2, regs[b2], d2); 4022 o->addr1 = tcg_temp_new_i64(); 4023 gen_addi_and_wrap_i64(s, o->addr1, regs[r3], 0); 4024 4025 /* load the third operand into r3 before modifying anything */ 4026 tcg_gen_qemu_ld_i64(regs[r3], o->addr1, get_mem_index(s), MO_TEUQ); 4027 4028 /* subtract CPU timer from first operand and store in GR0 */ 4029 gen_helper_stpt(tmp, tcg_env); 4030 tcg_gen_sub_i64(regs[0], o->in1, tmp); 4031 4032 /* store second operand in GR1 */ 4033 tcg_gen_mov_i64(regs[1], o->in2); 4034 return DISAS_NEXT; 4035 } 4036 4037 #ifndef CONFIG_USER_ONLY 4038 static DisasJumpType op_spka(DisasContext *s, DisasOps *o) 4039 { 4040 tcg_gen_shri_i64(o->in2, o->in2, 4); 4041 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4); 4042 return DISAS_NEXT; 4043 } 4044 4045 static DisasJumpType op_sske(DisasContext *s, DisasOps *o) 4046 { 4047 gen_helper_sske(tcg_env, o->in1, o->in2); 4048 return DISAS_NEXT; 4049 } 4050 4051 static void gen_check_psw_mask(DisasContext *s) 4052 { 4053 TCGv_i64 reserved = tcg_temp_new_i64(); 4054 TCGLabel *ok = gen_new_label(); 4055 4056 tcg_gen_andi_i64(reserved, psw_mask, PSW_MASK_RESERVED); 4057 tcg_gen_brcondi_i64(TCG_COND_EQ, reserved, 0, ok); 4058 gen_program_exception(s, PGM_SPECIFICATION); 4059 gen_set_label(ok); 4060 } 4061 4062 static DisasJumpType op_ssm(DisasContext *s, DisasOps *o) 4063 { 4064 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8); 4065 4066 gen_check_psw_mask(s); 4067 4068 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ 4069 s->exit_to_mainloop = true; 4070 return DISAS_TOO_MANY; 4071 } 4072 4073 static DisasJumpType op_stap(DisasContext *s, DisasOps *o) 4074 { 4075 tcg_gen_ld32u_i64(o->out, tcg_env, offsetof(CPUS390XState, core_id)); 4076 return DISAS_NEXT; 4077 } 4078 #endif 4079 4080 static DisasJumpType op_stck(DisasContext *s, DisasOps *o) 4081 { 4082 gen_helper_stck(o->out, tcg_env); 4083 /* ??? We don't implement clock states. */ 4084 gen_op_movi_cc(s, 0); 4085 return DISAS_NEXT; 4086 } 4087 4088 static DisasJumpType op_stcke(DisasContext *s, DisasOps *o) 4089 { 4090 TCGv_i64 c1 = tcg_temp_new_i64(); 4091 TCGv_i64 c2 = tcg_temp_new_i64(); 4092 TCGv_i64 todpr = tcg_temp_new_i64(); 4093 gen_helper_stck(c1, tcg_env); 4094 /* 16 bit value store in an uint32_t (only valid bits set) */ 4095 tcg_gen_ld32u_i64(todpr, tcg_env, offsetof(CPUS390XState, todpr)); 4096 /* Shift the 64-bit value into its place as a zero-extended 4097 104-bit value. Note that "bit positions 64-103 are always 4098 non-zero so that they compare differently to STCK"; we set 4099 the least significant bit to 1. */ 4100 tcg_gen_shli_i64(c2, c1, 56); 4101 tcg_gen_shri_i64(c1, c1, 8); 4102 tcg_gen_ori_i64(c2, c2, 0x10000); 4103 tcg_gen_or_i64(c2, c2, todpr); 4104 tcg_gen_qemu_st_i64(c1, o->in2, get_mem_index(s), MO_TEUQ); 4105 tcg_gen_addi_i64(o->in2, o->in2, 8); 4106 tcg_gen_qemu_st_i64(c2, o->in2, get_mem_index(s), MO_TEUQ); 4107 /* ??? We don't implement clock states. */ 4108 gen_op_movi_cc(s, 0); 4109 return DISAS_NEXT; 4110 } 4111 4112 #ifndef CONFIG_USER_ONLY 4113 static DisasJumpType op_sck(DisasContext *s, DisasOps *o) 4114 { 4115 gen_helper_sck(cc_op, tcg_env, o->in2); 4116 set_cc_static(s); 4117 return DISAS_NEXT; 4118 } 4119 4120 static DisasJumpType op_sckc(DisasContext *s, DisasOps *o) 4121 { 4122 gen_helper_sckc(tcg_env, o->in2); 4123 return DISAS_NEXT; 4124 } 4125 4126 static DisasJumpType op_sckpf(DisasContext *s, DisasOps *o) 4127 { 4128 gen_helper_sckpf(tcg_env, regs[0]); 4129 return DISAS_NEXT; 4130 } 4131 4132 static DisasJumpType op_stckc(DisasContext *s, DisasOps *o) 4133 { 4134 gen_helper_stckc(o->out, tcg_env); 4135 return DISAS_NEXT; 4136 } 4137 4138 static DisasJumpType op_stctg(DisasContext *s, DisasOps *o) 4139 { 4140 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4141 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 4142 4143 gen_helper_stctg(tcg_env, r1, o->in2, r3); 4144 return DISAS_NEXT; 4145 } 4146 4147 static DisasJumpType op_stctl(DisasContext *s, DisasOps *o) 4148 { 4149 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4150 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 4151 4152 gen_helper_stctl(tcg_env, r1, o->in2, r3); 4153 return DISAS_NEXT; 4154 } 4155 4156 static DisasJumpType op_stidp(DisasContext *s, DisasOps *o) 4157 { 4158 tcg_gen_ld_i64(o->out, tcg_env, offsetof(CPUS390XState, cpuid)); 4159 return DISAS_NEXT; 4160 } 4161 4162 static DisasJumpType op_spt(DisasContext *s, DisasOps *o) 4163 { 4164 gen_helper_spt(tcg_env, o->in2); 4165 return DISAS_NEXT; 4166 } 4167 4168 static DisasJumpType op_stfl(DisasContext *s, DisasOps *o) 4169 { 4170 gen_helper_stfl(tcg_env); 4171 return DISAS_NEXT; 4172 } 4173 4174 static DisasJumpType op_stpt(DisasContext *s, DisasOps *o) 4175 { 4176 gen_helper_stpt(o->out, tcg_env); 4177 return DISAS_NEXT; 4178 } 4179 4180 static DisasJumpType op_stsi(DisasContext *s, DisasOps *o) 4181 { 4182 gen_helper_stsi(cc_op, tcg_env, o->in2, regs[0], regs[1]); 4183 set_cc_static(s); 4184 return DISAS_NEXT; 4185 } 4186 4187 static DisasJumpType op_spx(DisasContext *s, DisasOps *o) 4188 { 4189 gen_helper_spx(tcg_env, o->in2); 4190 return DISAS_NEXT; 4191 } 4192 4193 static DisasJumpType op_xsch(DisasContext *s, DisasOps *o) 4194 { 4195 gen_helper_xsch(tcg_env, regs[1]); 4196 set_cc_static(s); 4197 return DISAS_NEXT; 4198 } 4199 4200 static DisasJumpType op_csch(DisasContext *s, DisasOps *o) 4201 { 4202 gen_helper_csch(tcg_env, regs[1]); 4203 set_cc_static(s); 4204 return DISAS_NEXT; 4205 } 4206 4207 static DisasJumpType op_hsch(DisasContext *s, DisasOps *o) 4208 { 4209 gen_helper_hsch(tcg_env, regs[1]); 4210 set_cc_static(s); 4211 return DISAS_NEXT; 4212 } 4213 4214 static DisasJumpType op_msch(DisasContext *s, DisasOps *o) 4215 { 4216 gen_helper_msch(tcg_env, regs[1], o->in2); 4217 set_cc_static(s); 4218 return DISAS_NEXT; 4219 } 4220 4221 static DisasJumpType op_rchp(DisasContext *s, DisasOps *o) 4222 { 4223 gen_helper_rchp(tcg_env, regs[1]); 4224 set_cc_static(s); 4225 return DISAS_NEXT; 4226 } 4227 4228 static DisasJumpType op_rsch(DisasContext *s, DisasOps *o) 4229 { 4230 gen_helper_rsch(tcg_env, regs[1]); 4231 set_cc_static(s); 4232 return DISAS_NEXT; 4233 } 4234 4235 static DisasJumpType op_sal(DisasContext *s, DisasOps *o) 4236 { 4237 gen_helper_sal(tcg_env, regs[1]); 4238 return DISAS_NEXT; 4239 } 4240 4241 static DisasJumpType op_schm(DisasContext *s, DisasOps *o) 4242 { 4243 gen_helper_schm(tcg_env, regs[1], regs[2], o->in2); 4244 return DISAS_NEXT; 4245 } 4246 4247 static DisasJumpType op_siga(DisasContext *s, DisasOps *o) 4248 { 4249 /* From KVM code: Not provided, set CC = 3 for subchannel not operational */ 4250 gen_op_movi_cc(s, 3); 4251 return DISAS_NEXT; 4252 } 4253 4254 static DisasJumpType op_stcps(DisasContext *s, DisasOps *o) 4255 { 4256 /* The instruction is suppressed if not provided. */ 4257 return DISAS_NEXT; 4258 } 4259 4260 static DisasJumpType op_ssch(DisasContext *s, DisasOps *o) 4261 { 4262 gen_helper_ssch(tcg_env, regs[1], o->in2); 4263 set_cc_static(s); 4264 return DISAS_NEXT; 4265 } 4266 4267 static DisasJumpType op_stsch(DisasContext *s, DisasOps *o) 4268 { 4269 gen_helper_stsch(tcg_env, regs[1], o->in2); 4270 set_cc_static(s); 4271 return DISAS_NEXT; 4272 } 4273 4274 static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o) 4275 { 4276 gen_helper_stcrw(tcg_env, o->in2); 4277 set_cc_static(s); 4278 return DISAS_NEXT; 4279 } 4280 4281 static DisasJumpType op_tpi(DisasContext *s, DisasOps *o) 4282 { 4283 gen_helper_tpi(cc_op, tcg_env, o->addr1); 4284 set_cc_static(s); 4285 return DISAS_NEXT; 4286 } 4287 4288 static DisasJumpType op_tsch(DisasContext *s, DisasOps *o) 4289 { 4290 gen_helper_tsch(tcg_env, regs[1], o->in2); 4291 set_cc_static(s); 4292 return DISAS_NEXT; 4293 } 4294 4295 static DisasJumpType op_chsc(DisasContext *s, DisasOps *o) 4296 { 4297 gen_helper_chsc(tcg_env, o->in2); 4298 set_cc_static(s); 4299 return DISAS_NEXT; 4300 } 4301 4302 static DisasJumpType op_stpx(DisasContext *s, DisasOps *o) 4303 { 4304 tcg_gen_ld_i64(o->out, tcg_env, offsetof(CPUS390XState, psa)); 4305 tcg_gen_andi_i64(o->out, o->out, 0x7fffe000); 4306 return DISAS_NEXT; 4307 } 4308 4309 static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o) 4310 { 4311 uint64_t i2 = get_field(s, i2); 4312 TCGv_i64 t; 4313 4314 /* It is important to do what the instruction name says: STORE THEN. 4315 If we let the output hook perform the store then if we fault and 4316 restart, we'll have the wrong SYSTEM MASK in place. */ 4317 t = tcg_temp_new_i64(); 4318 tcg_gen_shri_i64(t, psw_mask, 56); 4319 tcg_gen_qemu_st_i64(t, o->addr1, get_mem_index(s), MO_UB); 4320 4321 if (s->fields.op == 0xac) { 4322 tcg_gen_andi_i64(psw_mask, psw_mask, 4323 (i2 << 56) | 0x00ffffffffffffffull); 4324 } else { 4325 tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56); 4326 } 4327 4328 gen_check_psw_mask(s); 4329 4330 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ 4331 s->exit_to_mainloop = true; 4332 return DISAS_TOO_MANY; 4333 } 4334 4335 static DisasJumpType op_stura(DisasContext *s, DisasOps *o) 4336 { 4337 tcg_gen_qemu_st_tl(o->in1, o->in2, MMU_REAL_IDX, s->insn->data); 4338 4339 if (s->base.tb->flags & FLAG_MASK_PER_STORE_REAL) { 4340 update_cc_op(s); 4341 update_psw_addr(s); 4342 gen_helper_per_store_real(tcg_env, tcg_constant_i32(s->ilen)); 4343 return DISAS_NORETURN; 4344 } 4345 return DISAS_NEXT; 4346 } 4347 #endif 4348 4349 static DisasJumpType op_stfle(DisasContext *s, DisasOps *o) 4350 { 4351 gen_helper_stfle(cc_op, tcg_env, o->in2); 4352 set_cc_static(s); 4353 return DISAS_NEXT; 4354 } 4355 4356 static DisasJumpType op_st8(DisasContext *s, DisasOps *o) 4357 { 4358 tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s), MO_UB); 4359 return DISAS_NEXT; 4360 } 4361 4362 static DisasJumpType op_st16(DisasContext *s, DisasOps *o) 4363 { 4364 tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s), MO_TEUW); 4365 return DISAS_NEXT; 4366 } 4367 4368 static DisasJumpType op_st32(DisasContext *s, DisasOps *o) 4369 { 4370 tcg_gen_qemu_st_tl(o->in1, o->in2, get_mem_index(s), 4371 MO_TEUL | s->insn->data); 4372 return DISAS_NEXT; 4373 } 4374 4375 static DisasJumpType op_st64(DisasContext *s, DisasOps *o) 4376 { 4377 tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s), 4378 MO_TEUQ | s->insn->data); 4379 return DISAS_NEXT; 4380 } 4381 4382 static DisasJumpType op_stam(DisasContext *s, DisasOps *o) 4383 { 4384 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4385 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 4386 4387 gen_helper_stam(tcg_env, r1, o->in2, r3); 4388 return DISAS_NEXT; 4389 } 4390 4391 static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) 4392 { 4393 int m3 = get_field(s, m3); 4394 int pos, base = s->insn->data; 4395 TCGv_i64 tmp = tcg_temp_new_i64(); 4396 4397 pos = base + ctz32(m3) * 8; 4398 switch (m3) { 4399 case 0xf: 4400 /* Effectively a 32-bit store. */ 4401 tcg_gen_shri_i64(tmp, o->in1, pos); 4402 tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_TEUL); 4403 break; 4404 4405 case 0xc: 4406 case 0x6: 4407 case 0x3: 4408 /* Effectively a 16-bit store. */ 4409 tcg_gen_shri_i64(tmp, o->in1, pos); 4410 tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_TEUW); 4411 break; 4412 4413 case 0x8: 4414 case 0x4: 4415 case 0x2: 4416 case 0x1: 4417 /* Effectively an 8-bit store. */ 4418 tcg_gen_shri_i64(tmp, o->in1, pos); 4419 tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_UB); 4420 break; 4421 4422 default: 4423 /* This is going to be a sequence of shifts and stores. */ 4424 pos = base + 32 - 8; 4425 while (m3) { 4426 if (m3 & 0x8) { 4427 tcg_gen_shri_i64(tmp, o->in1, pos); 4428 tcg_gen_qemu_st_i64(tmp, o->in2, get_mem_index(s), MO_UB); 4429 tcg_gen_addi_i64(o->in2, o->in2, 1); 4430 } 4431 m3 = (m3 << 1) & 0xf; 4432 pos -= 8; 4433 } 4434 break; 4435 } 4436 return DISAS_NEXT; 4437 } 4438 4439 static DisasJumpType op_stm(DisasContext *s, DisasOps *o) 4440 { 4441 int r1 = get_field(s, r1); 4442 int r3 = get_field(s, r3); 4443 int size = s->insn->data; 4444 TCGv_i64 tsize = tcg_constant_i64(size); 4445 4446 while (1) { 4447 tcg_gen_qemu_st_i64(regs[r1], o->in2, get_mem_index(s), 4448 size == 8 ? MO_TEUQ : MO_TEUL); 4449 if (r1 == r3) { 4450 break; 4451 } 4452 tcg_gen_add_i64(o->in2, o->in2, tsize); 4453 r1 = (r1 + 1) & 15; 4454 } 4455 4456 return DISAS_NEXT; 4457 } 4458 4459 static DisasJumpType op_stmh(DisasContext *s, DisasOps *o) 4460 { 4461 int r1 = get_field(s, r1); 4462 int r3 = get_field(s, r3); 4463 TCGv_i64 t = tcg_temp_new_i64(); 4464 TCGv_i64 t4 = tcg_constant_i64(4); 4465 TCGv_i64 t32 = tcg_constant_i64(32); 4466 4467 while (1) { 4468 tcg_gen_shl_i64(t, regs[r1], t32); 4469 tcg_gen_qemu_st_i64(t, o->in2, get_mem_index(s), MO_TEUL); 4470 if (r1 == r3) { 4471 break; 4472 } 4473 tcg_gen_add_i64(o->in2, o->in2, t4); 4474 r1 = (r1 + 1) & 15; 4475 } 4476 return DISAS_NEXT; 4477 } 4478 4479 static DisasJumpType op_stpq(DisasContext *s, DisasOps *o) 4480 { 4481 TCGv_i128 t16 = tcg_temp_new_i128(); 4482 4483 tcg_gen_concat_i64_i128(t16, o->out2, o->out); 4484 tcg_gen_qemu_st_i128(t16, o->in2, get_mem_index(s), 4485 MO_TE | MO_128 | MO_ALIGN); 4486 return DISAS_NEXT; 4487 } 4488 4489 static DisasJumpType op_srst(DisasContext *s, DisasOps *o) 4490 { 4491 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4492 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4493 4494 gen_helper_srst(tcg_env, r1, r2); 4495 set_cc_static(s); 4496 return DISAS_NEXT; 4497 } 4498 4499 static DisasJumpType op_srstu(DisasContext *s, DisasOps *o) 4500 { 4501 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4502 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4503 4504 gen_helper_srstu(tcg_env, r1, r2); 4505 set_cc_static(s); 4506 return DISAS_NEXT; 4507 } 4508 4509 static DisasJumpType op_sub(DisasContext *s, DisasOps *o) 4510 { 4511 tcg_gen_sub_i64(o->out, o->in1, o->in2); 4512 return DISAS_NEXT; 4513 } 4514 4515 static DisasJumpType op_subu64(DisasContext *s, DisasOps *o) 4516 { 4517 tcg_gen_movi_i64(cc_src, 0); 4518 tcg_gen_sub2_i64(o->out, cc_src, o->in1, cc_src, o->in2, cc_src); 4519 return DISAS_NEXT; 4520 } 4521 4522 /* Compute borrow (0, -1) into cc_src. */ 4523 static void compute_borrow(DisasContext *s) 4524 { 4525 switch (s->cc_op) { 4526 case CC_OP_SUBU: 4527 /* The borrow value is already in cc_src (0,-1). */ 4528 break; 4529 default: 4530 gen_op_calc_cc(s); 4531 /* fall through */ 4532 case CC_OP_STATIC: 4533 /* The carry flag is the msb of CC; compute into cc_src. */ 4534 tcg_gen_extu_i32_i64(cc_src, cc_op); 4535 tcg_gen_shri_i64(cc_src, cc_src, 1); 4536 /* fall through */ 4537 case CC_OP_ADDU: 4538 /* Convert carry (1,0) to borrow (0,-1). */ 4539 tcg_gen_subi_i64(cc_src, cc_src, 1); 4540 break; 4541 } 4542 } 4543 4544 static DisasJumpType op_subb32(DisasContext *s, DisasOps *o) 4545 { 4546 compute_borrow(s); 4547 4548 /* Borrow is {0, -1}, so add to subtract. */ 4549 tcg_gen_add_i64(o->out, o->in1, cc_src); 4550 tcg_gen_sub_i64(o->out, o->out, o->in2); 4551 return DISAS_NEXT; 4552 } 4553 4554 static DisasJumpType op_subb64(DisasContext *s, DisasOps *o) 4555 { 4556 compute_borrow(s); 4557 4558 /* 4559 * Borrow is {0, -1}, so add to subtract; replicate the 4560 * borrow input to produce 128-bit -1 for the addition. 4561 */ 4562 TCGv_i64 zero = tcg_constant_i64(0); 4563 tcg_gen_add2_i64(o->out, cc_src, o->in1, zero, cc_src, cc_src); 4564 tcg_gen_sub2_i64(o->out, cc_src, o->out, cc_src, o->in2, zero); 4565 4566 return DISAS_NEXT; 4567 } 4568 4569 static DisasJumpType op_svc(DisasContext *s, DisasOps *o) 4570 { 4571 TCGv_i32 t; 4572 4573 update_psw_addr(s); 4574 update_cc_op(s); 4575 4576 t = tcg_constant_i32(get_field(s, i1) & 0xff); 4577 tcg_gen_st_i32(t, tcg_env, offsetof(CPUS390XState, int_svc_code)); 4578 4579 t = tcg_constant_i32(s->ilen); 4580 tcg_gen_st_i32(t, tcg_env, offsetof(CPUS390XState, int_svc_ilen)); 4581 4582 gen_exception(EXCP_SVC); 4583 return DISAS_NORETURN; 4584 } 4585 4586 static DisasJumpType op_tam(DisasContext *s, DisasOps *o) 4587 { 4588 int cc = 0; 4589 4590 cc |= (s->base.tb->flags & FLAG_MASK_64) ? 2 : 0; 4591 cc |= (s->base.tb->flags & FLAG_MASK_32) ? 1 : 0; 4592 gen_op_movi_cc(s, cc); 4593 return DISAS_NEXT; 4594 } 4595 4596 static DisasJumpType op_tceb(DisasContext *s, DisasOps *o) 4597 { 4598 gen_helper_tceb(cc_op, tcg_env, o->in1, o->in2); 4599 set_cc_static(s); 4600 return DISAS_NEXT; 4601 } 4602 4603 static DisasJumpType op_tcdb(DisasContext *s, DisasOps *o) 4604 { 4605 gen_helper_tcdb(cc_op, tcg_env, o->in1, o->in2); 4606 set_cc_static(s); 4607 return DISAS_NEXT; 4608 } 4609 4610 static DisasJumpType op_tcxb(DisasContext *s, DisasOps *o) 4611 { 4612 gen_helper_tcxb(cc_op, tcg_env, o->in1_128, o->in2); 4613 set_cc_static(s); 4614 return DISAS_NEXT; 4615 } 4616 4617 #ifndef CONFIG_USER_ONLY 4618 4619 static DisasJumpType op_testblock(DisasContext *s, DisasOps *o) 4620 { 4621 gen_helper_testblock(cc_op, tcg_env, o->in2); 4622 set_cc_static(s); 4623 return DISAS_NEXT; 4624 } 4625 4626 static DisasJumpType op_tprot(DisasContext *s, DisasOps *o) 4627 { 4628 gen_helper_tprot(cc_op, tcg_env, o->addr1, o->in2); 4629 set_cc_static(s); 4630 return DISAS_NEXT; 4631 } 4632 4633 #endif 4634 4635 static DisasJumpType op_tp(DisasContext *s, DisasOps *o) 4636 { 4637 TCGv_i32 l1 = tcg_constant_i32(get_field(s, l1) + 1); 4638 4639 gen_helper_tp(cc_op, tcg_env, o->addr1, l1); 4640 set_cc_static(s); 4641 return DISAS_NEXT; 4642 } 4643 4644 static DisasJumpType op_tr(DisasContext *s, DisasOps *o) 4645 { 4646 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 4647 4648 gen_helper_tr(tcg_env, l, o->addr1, o->in2); 4649 set_cc_static(s); 4650 return DISAS_NEXT; 4651 } 4652 4653 static DisasJumpType op_tre(DisasContext *s, DisasOps *o) 4654 { 4655 TCGv_i128 pair = tcg_temp_new_i128(); 4656 4657 gen_helper_tre(pair, tcg_env, o->out, o->out2, o->in2); 4658 tcg_gen_extr_i128_i64(o->out2, o->out, pair); 4659 set_cc_static(s); 4660 return DISAS_NEXT; 4661 } 4662 4663 static DisasJumpType op_trt(DisasContext *s, DisasOps *o) 4664 { 4665 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 4666 4667 gen_helper_trt(cc_op, tcg_env, l, o->addr1, o->in2); 4668 set_cc_static(s); 4669 return DISAS_NEXT; 4670 } 4671 4672 static DisasJumpType op_trtr(DisasContext *s, DisasOps *o) 4673 { 4674 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 4675 4676 gen_helper_trtr(cc_op, tcg_env, l, o->addr1, o->in2); 4677 set_cc_static(s); 4678 return DISAS_NEXT; 4679 } 4680 4681 static DisasJumpType op_trXX(DisasContext *s, DisasOps *o) 4682 { 4683 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4684 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4685 TCGv_i32 sizes = tcg_constant_i32(s->insn->opc & 3); 4686 TCGv_i32 tst = tcg_temp_new_i32(); 4687 int m3 = get_field(s, m3); 4688 4689 if (!s390_has_feat(S390_FEAT_ETF2_ENH)) { 4690 m3 = 0; 4691 } 4692 if (m3 & 1) { 4693 tcg_gen_movi_i32(tst, -1); 4694 } else { 4695 tcg_gen_extrl_i64_i32(tst, regs[0]); 4696 if (s->insn->opc & 3) { 4697 tcg_gen_ext8u_i32(tst, tst); 4698 } else { 4699 tcg_gen_ext16u_i32(tst, tst); 4700 } 4701 } 4702 gen_helper_trXX(cc_op, tcg_env, r1, r2, tst, sizes); 4703 4704 set_cc_static(s); 4705 return DISAS_NEXT; 4706 } 4707 4708 static DisasJumpType op_ts(DisasContext *s, DisasOps *o) 4709 { 4710 TCGv_i32 ff = tcg_constant_i32(0xff); 4711 TCGv_i32 t1 = tcg_temp_new_i32(); 4712 4713 tcg_gen_atomic_xchg_i32(t1, o->in2, ff, get_mem_index(s), MO_UB); 4714 tcg_gen_extract_i32(cc_op, t1, 7, 1); 4715 set_cc_static(s); 4716 return DISAS_NEXT; 4717 } 4718 4719 static DisasJumpType op_unpk(DisasContext *s, DisasOps *o) 4720 { 4721 TCGv_i32 l = tcg_constant_i32(get_field(s, l1)); 4722 4723 gen_helper_unpk(tcg_env, l, o->addr1, o->in2); 4724 return DISAS_NEXT; 4725 } 4726 4727 static DisasJumpType op_unpka(DisasContext *s, DisasOps *o) 4728 { 4729 int l1 = get_field(s, l1) + 1; 4730 TCGv_i32 l; 4731 4732 /* The length must not exceed 32 bytes. */ 4733 if (l1 > 32) { 4734 gen_program_exception(s, PGM_SPECIFICATION); 4735 return DISAS_NORETURN; 4736 } 4737 l = tcg_constant_i32(l1); 4738 gen_helper_unpka(cc_op, tcg_env, o->addr1, l, o->in2); 4739 set_cc_static(s); 4740 return DISAS_NEXT; 4741 } 4742 4743 static DisasJumpType op_unpku(DisasContext *s, DisasOps *o) 4744 { 4745 int l1 = get_field(s, l1) + 1; 4746 TCGv_i32 l; 4747 4748 /* The length must be even and should not exceed 64 bytes. */ 4749 if ((l1 & 1) || (l1 > 64)) { 4750 gen_program_exception(s, PGM_SPECIFICATION); 4751 return DISAS_NORETURN; 4752 } 4753 l = tcg_constant_i32(l1); 4754 gen_helper_unpku(cc_op, tcg_env, o->addr1, l, o->in2); 4755 set_cc_static(s); 4756 return DISAS_NEXT; 4757 } 4758 4759 4760 static DisasJumpType op_xc(DisasContext *s, DisasOps *o) 4761 { 4762 int d1 = get_field(s, d1); 4763 int d2 = get_field(s, d2); 4764 int b1 = get_field(s, b1); 4765 int b2 = get_field(s, b2); 4766 int l = get_field(s, l1); 4767 TCGv_i32 t32; 4768 4769 o->addr1 = get_address(s, 0, b1, d1); 4770 4771 /* If the addresses are identical, this is a store/memset of zero. */ 4772 if (b1 == b2 && d1 == d2 && (l + 1) <= 32) { 4773 o->in2 = tcg_constant_i64(0); 4774 4775 l++; 4776 while (l >= 8) { 4777 tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UQ); 4778 l -= 8; 4779 if (l > 0) { 4780 tcg_gen_addi_i64(o->addr1, o->addr1, 8); 4781 } 4782 } 4783 if (l >= 4) { 4784 tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UL); 4785 l -= 4; 4786 if (l > 0) { 4787 tcg_gen_addi_i64(o->addr1, o->addr1, 4); 4788 } 4789 } 4790 if (l >= 2) { 4791 tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UW); 4792 l -= 2; 4793 if (l > 0) { 4794 tcg_gen_addi_i64(o->addr1, o->addr1, 2); 4795 } 4796 } 4797 if (l) { 4798 tcg_gen_qemu_st_i64(o->in2, o->addr1, get_mem_index(s), MO_UB); 4799 } 4800 gen_op_movi_cc(s, 0); 4801 return DISAS_NEXT; 4802 } 4803 4804 /* But in general we'll defer to a helper. */ 4805 o->in2 = get_address(s, 0, b2, d2); 4806 t32 = tcg_constant_i32(l); 4807 gen_helper_xc(cc_op, tcg_env, t32, o->addr1, o->in2); 4808 set_cc_static(s); 4809 return DISAS_NEXT; 4810 } 4811 4812 static DisasJumpType op_xor(DisasContext *s, DisasOps *o) 4813 { 4814 tcg_gen_xor_i64(o->out, o->in1, o->in2); 4815 return DISAS_NEXT; 4816 } 4817 4818 static DisasJumpType op_xori(DisasContext *s, DisasOps *o) 4819 { 4820 int shift = s->insn->data & 0xff; 4821 int size = s->insn->data >> 8; 4822 uint64_t mask = ((1ull << size) - 1) << shift; 4823 TCGv_i64 t = tcg_temp_new_i64(); 4824 4825 tcg_gen_shli_i64(t, o->in2, shift); 4826 tcg_gen_xor_i64(o->out, o->in1, t); 4827 4828 /* Produce the CC from only the bits manipulated. */ 4829 tcg_gen_andi_i64(cc_dst, o->out, mask); 4830 set_cc_nz_u64(s, cc_dst); 4831 return DISAS_NEXT; 4832 } 4833 4834 static DisasJumpType op_xi(DisasContext *s, DisasOps *o) 4835 { 4836 o->in1 = tcg_temp_new_i64(); 4837 4838 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 4839 tcg_gen_qemu_ld_tl(o->in1, o->addr1, get_mem_index(s), s->insn->data); 4840 } else { 4841 /* Perform the atomic operation in memory. */ 4842 tcg_gen_atomic_fetch_xor_i64(o->in1, o->addr1, o->in2, get_mem_index(s), 4843 s->insn->data); 4844 } 4845 4846 /* Recompute also for atomic case: needed for setting CC. */ 4847 tcg_gen_xor_i64(o->out, o->in1, o->in2); 4848 4849 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { 4850 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); 4851 } 4852 return DISAS_NEXT; 4853 } 4854 4855 static DisasJumpType op_zero(DisasContext *s, DisasOps *o) 4856 { 4857 o->out = tcg_constant_i64(0); 4858 return DISAS_NEXT; 4859 } 4860 4861 static DisasJumpType op_zero2(DisasContext *s, DisasOps *o) 4862 { 4863 o->out = tcg_constant_i64(0); 4864 o->out2 = o->out; 4865 return DISAS_NEXT; 4866 } 4867 4868 #ifndef CONFIG_USER_ONLY 4869 static DisasJumpType op_clp(DisasContext *s, DisasOps *o) 4870 { 4871 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4872 4873 gen_helper_clp(tcg_env, r2); 4874 set_cc_static(s); 4875 return DISAS_NEXT; 4876 } 4877 4878 static DisasJumpType op_pcilg(DisasContext *s, DisasOps *o) 4879 { 4880 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4881 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4882 4883 gen_helper_pcilg(tcg_env, r1, r2); 4884 set_cc_static(s); 4885 return DISAS_NEXT; 4886 } 4887 4888 static DisasJumpType op_pcistg(DisasContext *s, DisasOps *o) 4889 { 4890 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4891 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4892 4893 gen_helper_pcistg(tcg_env, r1, r2); 4894 set_cc_static(s); 4895 return DISAS_NEXT; 4896 } 4897 4898 static DisasJumpType op_stpcifc(DisasContext *s, DisasOps *o) 4899 { 4900 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4901 TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); 4902 4903 gen_helper_stpcifc(tcg_env, r1, o->addr1, ar); 4904 set_cc_static(s); 4905 return DISAS_NEXT; 4906 } 4907 4908 static DisasJumpType op_sic(DisasContext *s, DisasOps *o) 4909 { 4910 gen_helper_sic(tcg_env, o->in1, o->in2); 4911 return DISAS_NEXT; 4912 } 4913 4914 static DisasJumpType op_rpcit(DisasContext *s, DisasOps *o) 4915 { 4916 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4917 TCGv_i32 r2 = tcg_constant_i32(get_field(s, r2)); 4918 4919 gen_helper_rpcit(tcg_env, r1, r2); 4920 set_cc_static(s); 4921 return DISAS_NEXT; 4922 } 4923 4924 static DisasJumpType op_pcistb(DisasContext *s, DisasOps *o) 4925 { 4926 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4927 TCGv_i32 r3 = tcg_constant_i32(get_field(s, r3)); 4928 TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); 4929 4930 gen_helper_pcistb(tcg_env, r1, r3, o->addr1, ar); 4931 set_cc_static(s); 4932 return DISAS_NEXT; 4933 } 4934 4935 static DisasJumpType op_mpcifc(DisasContext *s, DisasOps *o) 4936 { 4937 TCGv_i32 r1 = tcg_constant_i32(get_field(s, r1)); 4938 TCGv_i32 ar = tcg_constant_i32(get_field(s, b2)); 4939 4940 gen_helper_mpcifc(tcg_env, r1, o->addr1, ar); 4941 set_cc_static(s); 4942 return DISAS_NEXT; 4943 } 4944 #endif 4945 4946 #include "translate_vx.c.inc" 4947 4948 /* ====================================================================== */ 4949 /* The "Cc OUTput" generators. Given the generated output (and in some cases 4950 the original inputs), update the various cc data structures in order to 4951 be able to compute the new condition code. */ 4952 4953 static void cout_abs32(DisasContext *s, DisasOps *o) 4954 { 4955 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out); 4956 } 4957 4958 static void cout_abs64(DisasContext *s, DisasOps *o) 4959 { 4960 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out); 4961 } 4962 4963 static void cout_adds32(DisasContext *s, DisasOps *o) 4964 { 4965 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out); 4966 } 4967 4968 static void cout_adds64(DisasContext *s, DisasOps *o) 4969 { 4970 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out); 4971 } 4972 4973 static void cout_addu32(DisasContext *s, DisasOps *o) 4974 { 4975 tcg_gen_shri_i64(cc_src, o->out, 32); 4976 tcg_gen_ext32u_i64(cc_dst, o->out); 4977 gen_op_update2_cc_i64(s, CC_OP_ADDU, cc_src, cc_dst); 4978 } 4979 4980 static void cout_addu64(DisasContext *s, DisasOps *o) 4981 { 4982 gen_op_update2_cc_i64(s, CC_OP_ADDU, cc_src, o->out); 4983 } 4984 4985 static void cout_cmps32(DisasContext *s, DisasOps *o) 4986 { 4987 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2); 4988 } 4989 4990 static void cout_cmps64(DisasContext *s, DisasOps *o) 4991 { 4992 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2); 4993 } 4994 4995 static void cout_cmpu32(DisasContext *s, DisasOps *o) 4996 { 4997 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2); 4998 } 4999 5000 static void cout_cmpu64(DisasContext *s, DisasOps *o) 5001 { 5002 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2); 5003 } 5004 5005 static void cout_f32(DisasContext *s, DisasOps *o) 5006 { 5007 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out); 5008 } 5009 5010 static void cout_f64(DisasContext *s, DisasOps *o) 5011 { 5012 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out); 5013 } 5014 5015 static void cout_f128(DisasContext *s, DisasOps *o) 5016 { 5017 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2); 5018 } 5019 5020 static void cout_nabs32(DisasContext *s, DisasOps *o) 5021 { 5022 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out); 5023 } 5024 5025 static void cout_nabs64(DisasContext *s, DisasOps *o) 5026 { 5027 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out); 5028 } 5029 5030 static void cout_neg32(DisasContext *s, DisasOps *o) 5031 { 5032 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out); 5033 } 5034 5035 static void cout_neg64(DisasContext *s, DisasOps *o) 5036 { 5037 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out); 5038 } 5039 5040 static void cout_nz32(DisasContext *s, DisasOps *o) 5041 { 5042 tcg_gen_ext32u_i64(cc_dst, o->out); 5043 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst); 5044 } 5045 5046 static void cout_nz64(DisasContext *s, DisasOps *o) 5047 { 5048 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out); 5049 } 5050 5051 static void cout_s32(DisasContext *s, DisasOps *o) 5052 { 5053 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out); 5054 } 5055 5056 static void cout_s64(DisasContext *s, DisasOps *o) 5057 { 5058 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out); 5059 } 5060 5061 static void cout_subs32(DisasContext *s, DisasOps *o) 5062 { 5063 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out); 5064 } 5065 5066 static void cout_subs64(DisasContext *s, DisasOps *o) 5067 { 5068 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out); 5069 } 5070 5071 static void cout_subu32(DisasContext *s, DisasOps *o) 5072 { 5073 tcg_gen_sari_i64(cc_src, o->out, 32); 5074 tcg_gen_ext32u_i64(cc_dst, o->out); 5075 gen_op_update2_cc_i64(s, CC_OP_SUBU, cc_src, cc_dst); 5076 } 5077 5078 static void cout_subu64(DisasContext *s, DisasOps *o) 5079 { 5080 gen_op_update2_cc_i64(s, CC_OP_SUBU, cc_src, o->out); 5081 } 5082 5083 static void cout_tm32(DisasContext *s, DisasOps *o) 5084 { 5085 gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2); 5086 } 5087 5088 static void cout_tm64(DisasContext *s, DisasOps *o) 5089 { 5090 gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2); 5091 } 5092 5093 static void cout_muls32(DisasContext *s, DisasOps *o) 5094 { 5095 gen_op_update1_cc_i64(s, CC_OP_MULS_32, o->out); 5096 } 5097 5098 static void cout_muls64(DisasContext *s, DisasOps *o) 5099 { 5100 /* out contains "high" part, out2 contains "low" part of 128 bit result */ 5101 gen_op_update2_cc_i64(s, CC_OP_MULS_64, o->out, o->out2); 5102 } 5103 5104 /* ====================================================================== */ 5105 /* The "PREParation" generators. These initialize the DisasOps.OUT fields 5106 with the TCG register to which we will write. Used in combination with 5107 the "wout" generators, in some cases we need a new temporary, and in 5108 some cases we can write to a TCG global. */ 5109 5110 static void prep_new(DisasContext *s, DisasOps *o) 5111 { 5112 o->out = tcg_temp_new_i64(); 5113 } 5114 #define SPEC_prep_new 0 5115 5116 static void prep_new_P(DisasContext *s, DisasOps *o) 5117 { 5118 o->out = tcg_temp_new_i64(); 5119 o->out2 = tcg_temp_new_i64(); 5120 } 5121 #define SPEC_prep_new_P 0 5122 5123 static void prep_new_x(DisasContext *s, DisasOps *o) 5124 { 5125 o->out_128 = tcg_temp_new_i128(); 5126 } 5127 #define SPEC_prep_new_x 0 5128 5129 static void prep_r1(DisasContext *s, DisasOps *o) 5130 { 5131 o->out = regs[get_field(s, r1)]; 5132 } 5133 #define SPEC_prep_r1 0 5134 5135 static void prep_r1_P(DisasContext *s, DisasOps *o) 5136 { 5137 int r1 = get_field(s, r1); 5138 o->out = regs[r1]; 5139 o->out2 = regs[r1 + 1]; 5140 } 5141 #define SPEC_prep_r1_P SPEC_r1_even 5142 5143 /* ====================================================================== */ 5144 /* The "Write OUTput" generators. These generally perform some non-trivial 5145 copy of data to TCG globals, or to main memory. The trivial cases are 5146 generally handled by having a "prep" generator install the TCG global 5147 as the destination of the operation. */ 5148 5149 static void wout_r1(DisasContext *s, DisasOps *o) 5150 { 5151 store_reg(get_field(s, r1), o->out); 5152 } 5153 #define SPEC_wout_r1 0 5154 5155 static void wout_out2_r1(DisasContext *s, DisasOps *o) 5156 { 5157 store_reg(get_field(s, r1), o->out2); 5158 } 5159 #define SPEC_wout_out2_r1 0 5160 5161 static void wout_r1_8(DisasContext *s, DisasOps *o) 5162 { 5163 int r1 = get_field(s, r1); 5164 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8); 5165 } 5166 #define SPEC_wout_r1_8 0 5167 5168 static void wout_r1_16(DisasContext *s, DisasOps *o) 5169 { 5170 int r1 = get_field(s, r1); 5171 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16); 5172 } 5173 #define SPEC_wout_r1_16 0 5174 5175 static void wout_r1_32(DisasContext *s, DisasOps *o) 5176 { 5177 store_reg32_i64(get_field(s, r1), o->out); 5178 } 5179 #define SPEC_wout_r1_32 0 5180 5181 static void wout_r1_32h(DisasContext *s, DisasOps *o) 5182 { 5183 store_reg32h_i64(get_field(s, r1), o->out); 5184 } 5185 #define SPEC_wout_r1_32h 0 5186 5187 static void wout_r1_P32(DisasContext *s, DisasOps *o) 5188 { 5189 int r1 = get_field(s, r1); 5190 store_reg32_i64(r1, o->out); 5191 store_reg32_i64(r1 + 1, o->out2); 5192 } 5193 #define SPEC_wout_r1_P32 SPEC_r1_even 5194 5195 static void wout_r1_D32(DisasContext *s, DisasOps *o) 5196 { 5197 int r1 = get_field(s, r1); 5198 TCGv_i64 t = tcg_temp_new_i64(); 5199 store_reg32_i64(r1 + 1, o->out); 5200 tcg_gen_shri_i64(t, o->out, 32); 5201 store_reg32_i64(r1, t); 5202 } 5203 #define SPEC_wout_r1_D32 SPEC_r1_even 5204 5205 static void wout_r1_D64(DisasContext *s, DisasOps *o) 5206 { 5207 int r1 = get_field(s, r1); 5208 tcg_gen_extr_i128_i64(regs[r1 + 1], regs[r1], o->out_128); 5209 } 5210 #define SPEC_wout_r1_D64 SPEC_r1_even 5211 5212 static void wout_r3_P32(DisasContext *s, DisasOps *o) 5213 { 5214 int r3 = get_field(s, r3); 5215 store_reg32_i64(r3, o->out); 5216 store_reg32_i64(r3 + 1, o->out2); 5217 } 5218 #define SPEC_wout_r3_P32 SPEC_r3_even 5219 5220 static void wout_r3_P64(DisasContext *s, DisasOps *o) 5221 { 5222 int r3 = get_field(s, r3); 5223 store_reg(r3, o->out); 5224 store_reg(r3 + 1, o->out2); 5225 } 5226 #define SPEC_wout_r3_P64 SPEC_r3_even 5227 5228 static void wout_e1(DisasContext *s, DisasOps *o) 5229 { 5230 store_freg32_i64(get_field(s, r1), o->out); 5231 } 5232 #define SPEC_wout_e1 0 5233 5234 static void wout_f1(DisasContext *s, DisasOps *o) 5235 { 5236 store_freg(get_field(s, r1), o->out); 5237 } 5238 #define SPEC_wout_f1 0 5239 5240 static void wout_x1(DisasContext *s, DisasOps *o) 5241 { 5242 int f1 = get_field(s, r1); 5243 5244 /* Split out_128 into out+out2 for cout_f128. */ 5245 tcg_debug_assert(o->out == NULL); 5246 o->out = tcg_temp_new_i64(); 5247 o->out2 = tcg_temp_new_i64(); 5248 5249 tcg_gen_extr_i128_i64(o->out2, o->out, o->out_128); 5250 store_freg(f1, o->out); 5251 store_freg(f1 + 2, o->out2); 5252 } 5253 #define SPEC_wout_x1 SPEC_r1_f128 5254 5255 static void wout_x1_P(DisasContext *s, DisasOps *o) 5256 { 5257 int f1 = get_field(s, r1); 5258 store_freg(f1, o->out); 5259 store_freg(f1 + 2, o->out2); 5260 } 5261 #define SPEC_wout_x1_P SPEC_r1_f128 5262 5263 static void wout_cond_r1r2_32(DisasContext *s, DisasOps *o) 5264 { 5265 if (get_field(s, r1) != get_field(s, r2)) { 5266 store_reg32_i64(get_field(s, r1), o->out); 5267 } 5268 } 5269 #define SPEC_wout_cond_r1r2_32 0 5270 5271 static void wout_cond_e1e2(DisasContext *s, DisasOps *o) 5272 { 5273 if (get_field(s, r1) != get_field(s, r2)) { 5274 store_freg32_i64(get_field(s, r1), o->out); 5275 } 5276 } 5277 #define SPEC_wout_cond_e1e2 0 5278 5279 static void wout_m1_8(DisasContext *s, DisasOps *o) 5280 { 5281 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_UB); 5282 } 5283 #define SPEC_wout_m1_8 0 5284 5285 static void wout_m1_16(DisasContext *s, DisasOps *o) 5286 { 5287 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUW); 5288 } 5289 #define SPEC_wout_m1_16 0 5290 5291 #ifndef CONFIG_USER_ONLY 5292 static void wout_m1_16a(DisasContext *s, DisasOps *o) 5293 { 5294 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), MO_TEUW | MO_ALIGN); 5295 } 5296 #define SPEC_wout_m1_16a 0 5297 #endif 5298 5299 static void wout_m1_32(DisasContext *s, DisasOps *o) 5300 { 5301 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUL); 5302 } 5303 #define SPEC_wout_m1_32 0 5304 5305 #ifndef CONFIG_USER_ONLY 5306 static void wout_m1_32a(DisasContext *s, DisasOps *o) 5307 { 5308 tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), MO_TEUL | MO_ALIGN); 5309 } 5310 #define SPEC_wout_m1_32a 0 5311 #endif 5312 5313 static void wout_m1_64(DisasContext *s, DisasOps *o) 5314 { 5315 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUQ); 5316 } 5317 #define SPEC_wout_m1_64 0 5318 5319 #ifndef CONFIG_USER_ONLY 5320 static void wout_m1_64a(DisasContext *s, DisasOps *o) 5321 { 5322 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUQ | MO_ALIGN); 5323 } 5324 #define SPEC_wout_m1_64a 0 5325 #endif 5326 5327 static void wout_m2_32(DisasContext *s, DisasOps *o) 5328 { 5329 tcg_gen_qemu_st_i64(o->out, o->in2, get_mem_index(s), MO_TEUL); 5330 } 5331 #define SPEC_wout_m2_32 0 5332 5333 static void wout_in2_r1(DisasContext *s, DisasOps *o) 5334 { 5335 store_reg(get_field(s, r1), o->in2); 5336 } 5337 #define SPEC_wout_in2_r1 0 5338 5339 static void wout_in2_r1_32(DisasContext *s, DisasOps *o) 5340 { 5341 store_reg32_i64(get_field(s, r1), o->in2); 5342 } 5343 #define SPEC_wout_in2_r1_32 0 5344 5345 /* ====================================================================== */ 5346 /* The "INput 1" generators. These load the first operand to an insn. */ 5347 5348 static void in1_r1(DisasContext *s, DisasOps *o) 5349 { 5350 o->in1 = load_reg(get_field(s, r1)); 5351 } 5352 #define SPEC_in1_r1 0 5353 5354 static void in1_r1_o(DisasContext *s, DisasOps *o) 5355 { 5356 o->in1 = regs[get_field(s, r1)]; 5357 } 5358 #define SPEC_in1_r1_o 0 5359 5360 static void in1_r1_32s(DisasContext *s, DisasOps *o) 5361 { 5362 o->in1 = tcg_temp_new_i64(); 5363 tcg_gen_ext32s_i64(o->in1, regs[get_field(s, r1)]); 5364 } 5365 #define SPEC_in1_r1_32s 0 5366 5367 static void in1_r1_32u(DisasContext *s, DisasOps *o) 5368 { 5369 o->in1 = tcg_temp_new_i64(); 5370 tcg_gen_ext32u_i64(o->in1, regs[get_field(s, r1)]); 5371 } 5372 #define SPEC_in1_r1_32u 0 5373 5374 static void in1_r1_sr32(DisasContext *s, DisasOps *o) 5375 { 5376 o->in1 = tcg_temp_new_i64(); 5377 tcg_gen_shri_i64(o->in1, regs[get_field(s, r1)], 32); 5378 } 5379 #define SPEC_in1_r1_sr32 0 5380 5381 static void in1_r1p1(DisasContext *s, DisasOps *o) 5382 { 5383 o->in1 = load_reg(get_field(s, r1) + 1); 5384 } 5385 #define SPEC_in1_r1p1 SPEC_r1_even 5386 5387 static void in1_r1p1_o(DisasContext *s, DisasOps *o) 5388 { 5389 o->in1 = regs[get_field(s, r1) + 1]; 5390 } 5391 #define SPEC_in1_r1p1_o SPEC_r1_even 5392 5393 static void in1_r1p1_32s(DisasContext *s, DisasOps *o) 5394 { 5395 o->in1 = tcg_temp_new_i64(); 5396 tcg_gen_ext32s_i64(o->in1, regs[get_field(s, r1) + 1]); 5397 } 5398 #define SPEC_in1_r1p1_32s SPEC_r1_even 5399 5400 static void in1_r1p1_32u(DisasContext *s, DisasOps *o) 5401 { 5402 o->in1 = tcg_temp_new_i64(); 5403 tcg_gen_ext32u_i64(o->in1, regs[get_field(s, r1) + 1]); 5404 } 5405 #define SPEC_in1_r1p1_32u SPEC_r1_even 5406 5407 static void in1_r1_D32(DisasContext *s, DisasOps *o) 5408 { 5409 int r1 = get_field(s, r1); 5410 o->in1 = tcg_temp_new_i64(); 5411 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]); 5412 } 5413 #define SPEC_in1_r1_D32 SPEC_r1_even 5414 5415 static void in1_r2(DisasContext *s, DisasOps *o) 5416 { 5417 o->in1 = load_reg(get_field(s, r2)); 5418 } 5419 #define SPEC_in1_r2 0 5420 5421 static void in1_r2_sr32(DisasContext *s, DisasOps *o) 5422 { 5423 o->in1 = tcg_temp_new_i64(); 5424 tcg_gen_shri_i64(o->in1, regs[get_field(s, r2)], 32); 5425 } 5426 #define SPEC_in1_r2_sr32 0 5427 5428 static void in1_r2_32u(DisasContext *s, DisasOps *o) 5429 { 5430 o->in1 = tcg_temp_new_i64(); 5431 tcg_gen_ext32u_i64(o->in1, regs[get_field(s, r2)]); 5432 } 5433 #define SPEC_in1_r2_32u 0 5434 5435 static void in1_r3(DisasContext *s, DisasOps *o) 5436 { 5437 o->in1 = load_reg(get_field(s, r3)); 5438 } 5439 #define SPEC_in1_r3 0 5440 5441 static void in1_r3_o(DisasContext *s, DisasOps *o) 5442 { 5443 o->in1 = regs[get_field(s, r3)]; 5444 } 5445 #define SPEC_in1_r3_o 0 5446 5447 static void in1_r3_32s(DisasContext *s, DisasOps *o) 5448 { 5449 o->in1 = tcg_temp_new_i64(); 5450 tcg_gen_ext32s_i64(o->in1, regs[get_field(s, r3)]); 5451 } 5452 #define SPEC_in1_r3_32s 0 5453 5454 static void in1_r3_32u(DisasContext *s, DisasOps *o) 5455 { 5456 o->in1 = tcg_temp_new_i64(); 5457 tcg_gen_ext32u_i64(o->in1, regs[get_field(s, r3)]); 5458 } 5459 #define SPEC_in1_r3_32u 0 5460 5461 static void in1_r3_D32(DisasContext *s, DisasOps *o) 5462 { 5463 int r3 = get_field(s, r3); 5464 o->in1 = tcg_temp_new_i64(); 5465 tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]); 5466 } 5467 #define SPEC_in1_r3_D32 SPEC_r3_even 5468 5469 static void in1_r3_sr32(DisasContext *s, DisasOps *o) 5470 { 5471 o->in1 = tcg_temp_new_i64(); 5472 tcg_gen_shri_i64(o->in1, regs[get_field(s, r3)], 32); 5473 } 5474 #define SPEC_in1_r3_sr32 0 5475 5476 static void in1_e1(DisasContext *s, DisasOps *o) 5477 { 5478 o->in1 = load_freg32_i64(get_field(s, r1)); 5479 } 5480 #define SPEC_in1_e1 0 5481 5482 static void in1_f1(DisasContext *s, DisasOps *o) 5483 { 5484 o->in1 = load_freg(get_field(s, r1)); 5485 } 5486 #define SPEC_in1_f1 0 5487 5488 static void in1_x1(DisasContext *s, DisasOps *o) 5489 { 5490 o->in1_128 = load_freg_128(get_field(s, r1)); 5491 } 5492 #define SPEC_in1_x1 SPEC_r1_f128 5493 5494 /* Load the high double word of an extended (128-bit) format FP number */ 5495 static void in1_x2h(DisasContext *s, DisasOps *o) 5496 { 5497 o->in1 = load_freg(get_field(s, r2)); 5498 } 5499 #define SPEC_in1_x2h SPEC_r2_f128 5500 5501 static void in1_f3(DisasContext *s, DisasOps *o) 5502 { 5503 o->in1 = load_freg(get_field(s, r3)); 5504 } 5505 #define SPEC_in1_f3 0 5506 5507 static void in1_la1(DisasContext *s, DisasOps *o) 5508 { 5509 o->addr1 = get_address(s, 0, get_field(s, b1), get_field(s, d1)); 5510 } 5511 #define SPEC_in1_la1 0 5512 5513 static void in1_la2(DisasContext *s, DisasOps *o) 5514 { 5515 int x2 = have_field(s, x2) ? get_field(s, x2) : 0; 5516 o->addr1 = get_address(s, x2, get_field(s, b2), get_field(s, d2)); 5517 } 5518 #define SPEC_in1_la2 0 5519 5520 static void in1_m1_8u(DisasContext *s, DisasOps *o) 5521 { 5522 in1_la1(s, o); 5523 o->in1 = tcg_temp_new_i64(); 5524 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_UB); 5525 } 5526 #define SPEC_in1_m1_8u 0 5527 5528 static void in1_m1_16s(DisasContext *s, DisasOps *o) 5529 { 5530 in1_la1(s, o); 5531 o->in1 = tcg_temp_new_i64(); 5532 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TESW); 5533 } 5534 #define SPEC_in1_m1_16s 0 5535 5536 static void in1_m1_16u(DisasContext *s, DisasOps *o) 5537 { 5538 in1_la1(s, o); 5539 o->in1 = tcg_temp_new_i64(); 5540 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUW); 5541 } 5542 #define SPEC_in1_m1_16u 0 5543 5544 static void in1_m1_32s(DisasContext *s, DisasOps *o) 5545 { 5546 in1_la1(s, o); 5547 o->in1 = tcg_temp_new_i64(); 5548 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TESL); 5549 } 5550 #define SPEC_in1_m1_32s 0 5551 5552 static void in1_m1_32u(DisasContext *s, DisasOps *o) 5553 { 5554 in1_la1(s, o); 5555 o->in1 = tcg_temp_new_i64(); 5556 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUL); 5557 } 5558 #define SPEC_in1_m1_32u 0 5559 5560 static void in1_m1_64(DisasContext *s, DisasOps *o) 5561 { 5562 in1_la1(s, o); 5563 o->in1 = tcg_temp_new_i64(); 5564 tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUQ); 5565 } 5566 #define SPEC_in1_m1_64 0 5567 5568 /* ====================================================================== */ 5569 /* The "INput 2" generators. These load the second operand to an insn. */ 5570 5571 static void in2_r1_o(DisasContext *s, DisasOps *o) 5572 { 5573 o->in2 = regs[get_field(s, r1)]; 5574 } 5575 #define SPEC_in2_r1_o 0 5576 5577 static void in2_r1_16u(DisasContext *s, DisasOps *o) 5578 { 5579 o->in2 = tcg_temp_new_i64(); 5580 tcg_gen_ext16u_i64(o->in2, regs[get_field(s, r1)]); 5581 } 5582 #define SPEC_in2_r1_16u 0 5583 5584 static void in2_r1_32u(DisasContext *s, DisasOps *o) 5585 { 5586 o->in2 = tcg_temp_new_i64(); 5587 tcg_gen_ext32u_i64(o->in2, regs[get_field(s, r1)]); 5588 } 5589 #define SPEC_in2_r1_32u 0 5590 5591 static void in2_r1_D32(DisasContext *s, DisasOps *o) 5592 { 5593 int r1 = get_field(s, r1); 5594 o->in2 = tcg_temp_new_i64(); 5595 tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]); 5596 } 5597 #define SPEC_in2_r1_D32 SPEC_r1_even 5598 5599 static void in2_r2(DisasContext *s, DisasOps *o) 5600 { 5601 o->in2 = load_reg(get_field(s, r2)); 5602 } 5603 #define SPEC_in2_r2 0 5604 5605 static void in2_r2_o(DisasContext *s, DisasOps *o) 5606 { 5607 o->in2 = regs[get_field(s, r2)]; 5608 } 5609 #define SPEC_in2_r2_o 0 5610 5611 static void in2_r2_nz(DisasContext *s, DisasOps *o) 5612 { 5613 int r2 = get_field(s, r2); 5614 if (r2 != 0) { 5615 o->in2 = load_reg(r2); 5616 } 5617 } 5618 #define SPEC_in2_r2_nz 0 5619 5620 static void in2_r2_8s(DisasContext *s, DisasOps *o) 5621 { 5622 o->in2 = tcg_temp_new_i64(); 5623 tcg_gen_ext8s_i64(o->in2, regs[get_field(s, r2)]); 5624 } 5625 #define SPEC_in2_r2_8s 0 5626 5627 static void in2_r2_8u(DisasContext *s, DisasOps *o) 5628 { 5629 o->in2 = tcg_temp_new_i64(); 5630 tcg_gen_ext8u_i64(o->in2, regs[get_field(s, r2)]); 5631 } 5632 #define SPEC_in2_r2_8u 0 5633 5634 static void in2_r2_16s(DisasContext *s, DisasOps *o) 5635 { 5636 o->in2 = tcg_temp_new_i64(); 5637 tcg_gen_ext16s_i64(o->in2, regs[get_field(s, r2)]); 5638 } 5639 #define SPEC_in2_r2_16s 0 5640 5641 static void in2_r2_16u(DisasContext *s, DisasOps *o) 5642 { 5643 o->in2 = tcg_temp_new_i64(); 5644 tcg_gen_ext16u_i64(o->in2, regs[get_field(s, r2)]); 5645 } 5646 #define SPEC_in2_r2_16u 0 5647 5648 static void in2_r3(DisasContext *s, DisasOps *o) 5649 { 5650 o->in2 = load_reg(get_field(s, r3)); 5651 } 5652 #define SPEC_in2_r3 0 5653 5654 static void in2_r3_D64(DisasContext *s, DisasOps *o) 5655 { 5656 int r3 = get_field(s, r3); 5657 o->in2_128 = tcg_temp_new_i128(); 5658 tcg_gen_concat_i64_i128(o->in2_128, regs[r3 + 1], regs[r3]); 5659 } 5660 #define SPEC_in2_r3_D64 SPEC_r3_even 5661 5662 static void in2_r3_sr32(DisasContext *s, DisasOps *o) 5663 { 5664 o->in2 = tcg_temp_new_i64(); 5665 tcg_gen_shri_i64(o->in2, regs[get_field(s, r3)], 32); 5666 } 5667 #define SPEC_in2_r3_sr32 0 5668 5669 static void in2_r3_32u(DisasContext *s, DisasOps *o) 5670 { 5671 o->in2 = tcg_temp_new_i64(); 5672 tcg_gen_ext32u_i64(o->in2, regs[get_field(s, r3)]); 5673 } 5674 #define SPEC_in2_r3_32u 0 5675 5676 static void in2_r2_32s(DisasContext *s, DisasOps *o) 5677 { 5678 o->in2 = tcg_temp_new_i64(); 5679 tcg_gen_ext32s_i64(o->in2, regs[get_field(s, r2)]); 5680 } 5681 #define SPEC_in2_r2_32s 0 5682 5683 static void in2_r2_32u(DisasContext *s, DisasOps *o) 5684 { 5685 o->in2 = tcg_temp_new_i64(); 5686 tcg_gen_ext32u_i64(o->in2, regs[get_field(s, r2)]); 5687 } 5688 #define SPEC_in2_r2_32u 0 5689 5690 static void in2_r2_sr32(DisasContext *s, DisasOps *o) 5691 { 5692 o->in2 = tcg_temp_new_i64(); 5693 tcg_gen_shri_i64(o->in2, regs[get_field(s, r2)], 32); 5694 } 5695 #define SPEC_in2_r2_sr32 0 5696 5697 static void in2_e2(DisasContext *s, DisasOps *o) 5698 { 5699 o->in2 = load_freg32_i64(get_field(s, r2)); 5700 } 5701 #define SPEC_in2_e2 0 5702 5703 static void in2_f2(DisasContext *s, DisasOps *o) 5704 { 5705 o->in2 = load_freg(get_field(s, r2)); 5706 } 5707 #define SPEC_in2_f2 0 5708 5709 static void in2_x2(DisasContext *s, DisasOps *o) 5710 { 5711 o->in2_128 = load_freg_128(get_field(s, r2)); 5712 } 5713 #define SPEC_in2_x2 SPEC_r2_f128 5714 5715 /* Load the low double word of an extended (128-bit) format FP number */ 5716 static void in2_x2l(DisasContext *s, DisasOps *o) 5717 { 5718 o->in2 = load_freg(get_field(s, r2) + 2); 5719 } 5720 #define SPEC_in2_x2l SPEC_r2_f128 5721 5722 static void in2_ra2(DisasContext *s, DisasOps *o) 5723 { 5724 int r2 = get_field(s, r2); 5725 5726 /* Note: *don't* treat !r2 as 0, use the reg value. */ 5727 o->in2 = tcg_temp_new_i64(); 5728 gen_addi_and_wrap_i64(s, o->in2, regs[r2], 0); 5729 } 5730 #define SPEC_in2_ra2 0 5731 5732 static void in2_ra2_E(DisasContext *s, DisasOps *o) 5733 { 5734 return in2_ra2(s, o); 5735 } 5736 #define SPEC_in2_ra2_E SPEC_r2_even 5737 5738 static void in2_a2(DisasContext *s, DisasOps *o) 5739 { 5740 int x2 = have_field(s, x2) ? get_field(s, x2) : 0; 5741 o->in2 = get_address(s, x2, get_field(s, b2), get_field(s, d2)); 5742 } 5743 #define SPEC_in2_a2 0 5744 5745 static TCGv gen_ri2(DisasContext *s) 5746 { 5747 TCGv ri2 = NULL; 5748 bool is_imm; 5749 int imm; 5750 5751 disas_jdest(s, i2, is_imm, imm, ri2); 5752 if (is_imm) { 5753 ri2 = tcg_constant_i64(s->base.pc_next + (int64_t)imm * 2); 5754 } 5755 5756 return ri2; 5757 } 5758 5759 static void in2_ri2(DisasContext *s, DisasOps *o) 5760 { 5761 o->in2 = gen_ri2(s); 5762 } 5763 #define SPEC_in2_ri2 0 5764 5765 static void in2_sh(DisasContext *s, DisasOps *o) 5766 { 5767 int b2 = get_field(s, b2); 5768 int d2 = get_field(s, d2); 5769 5770 if (b2 == 0) { 5771 o->in2 = tcg_constant_i64(d2 & 0x3f); 5772 } else { 5773 o->in2 = get_address(s, 0, b2, d2); 5774 tcg_gen_andi_i64(o->in2, o->in2, 0x3f); 5775 } 5776 } 5777 #define SPEC_in2_sh 0 5778 5779 static void in2_m2_8u(DisasContext *s, DisasOps *o) 5780 { 5781 in2_a2(s, o); 5782 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_UB); 5783 } 5784 #define SPEC_in2_m2_8u 0 5785 5786 static void in2_m2_16s(DisasContext *s, DisasOps *o) 5787 { 5788 in2_a2(s, o); 5789 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TESW); 5790 } 5791 #define SPEC_in2_m2_16s 0 5792 5793 static void in2_m2_16u(DisasContext *s, DisasOps *o) 5794 { 5795 in2_a2(s, o); 5796 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUW); 5797 } 5798 #define SPEC_in2_m2_16u 0 5799 5800 static void in2_m2_32s(DisasContext *s, DisasOps *o) 5801 { 5802 in2_a2(s, o); 5803 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TESL); 5804 } 5805 #define SPEC_in2_m2_32s 0 5806 5807 static void in2_m2_32u(DisasContext *s, DisasOps *o) 5808 { 5809 in2_a2(s, o); 5810 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUL); 5811 } 5812 #define SPEC_in2_m2_32u 0 5813 5814 #ifndef CONFIG_USER_ONLY 5815 static void in2_m2_32ua(DisasContext *s, DisasOps *o) 5816 { 5817 in2_a2(s, o); 5818 tcg_gen_qemu_ld_tl(o->in2, o->in2, get_mem_index(s), MO_TEUL | MO_ALIGN); 5819 } 5820 #define SPEC_in2_m2_32ua 0 5821 #endif 5822 5823 static void in2_m2_64(DisasContext *s, DisasOps *o) 5824 { 5825 in2_a2(s, o); 5826 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ); 5827 } 5828 #define SPEC_in2_m2_64 0 5829 5830 static void in2_m2_64w(DisasContext *s, DisasOps *o) 5831 { 5832 in2_a2(s, o); 5833 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ); 5834 gen_addi_and_wrap_i64(s, o->in2, o->in2, 0); 5835 } 5836 #define SPEC_in2_m2_64w 0 5837 5838 #ifndef CONFIG_USER_ONLY 5839 static void in2_m2_64a(DisasContext *s, DisasOps *o) 5840 { 5841 in2_a2(s, o); 5842 tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN); 5843 } 5844 #define SPEC_in2_m2_64a 0 5845 #endif 5846 5847 static void in2_mri2_16s(DisasContext *s, DisasOps *o) 5848 { 5849 o->in2 = tcg_temp_new_i64(); 5850 tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s), MO_TESW); 5851 } 5852 #define SPEC_in2_mri2_16s 0 5853 5854 static void in2_mri2_16u(DisasContext *s, DisasOps *o) 5855 { 5856 o->in2 = tcg_temp_new_i64(); 5857 tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s), MO_TEUW); 5858 } 5859 #define SPEC_in2_mri2_16u 0 5860 5861 static void in2_mri2_32s(DisasContext *s, DisasOps *o) 5862 { 5863 o->in2 = tcg_temp_new_i64(); 5864 tcg_gen_qemu_ld_tl(o->in2, gen_ri2(s), get_mem_index(s), 5865 MO_TESL | MO_ALIGN); 5866 } 5867 #define SPEC_in2_mri2_32s 0 5868 5869 static void in2_mri2_32u(DisasContext *s, DisasOps *o) 5870 { 5871 o->in2 = tcg_temp_new_i64(); 5872 tcg_gen_qemu_ld_tl(o->in2, gen_ri2(s), get_mem_index(s), 5873 MO_TEUL | MO_ALIGN); 5874 } 5875 #define SPEC_in2_mri2_32u 0 5876 5877 static void in2_mri2_64(DisasContext *s, DisasOps *o) 5878 { 5879 o->in2 = tcg_temp_new_i64(); 5880 tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s), 5881 MO_TEUQ | MO_ALIGN); 5882 } 5883 #define SPEC_in2_mri2_64 0 5884 5885 static void in2_i2(DisasContext *s, DisasOps *o) 5886 { 5887 o->in2 = tcg_constant_i64(get_field(s, i2)); 5888 } 5889 #define SPEC_in2_i2 0 5890 5891 static void in2_i2_8u(DisasContext *s, DisasOps *o) 5892 { 5893 o->in2 = tcg_constant_i64((uint8_t)get_field(s, i2)); 5894 } 5895 #define SPEC_in2_i2_8u 0 5896 5897 static void in2_i2_16u(DisasContext *s, DisasOps *o) 5898 { 5899 o->in2 = tcg_constant_i64((uint16_t)get_field(s, i2)); 5900 } 5901 #define SPEC_in2_i2_16u 0 5902 5903 static void in2_i2_32u(DisasContext *s, DisasOps *o) 5904 { 5905 o->in2 = tcg_constant_i64((uint32_t)get_field(s, i2)); 5906 } 5907 #define SPEC_in2_i2_32u 0 5908 5909 static void in2_i2_16u_shl(DisasContext *s, DisasOps *o) 5910 { 5911 uint64_t i2 = (uint16_t)get_field(s, i2); 5912 o->in2 = tcg_constant_i64(i2 << s->insn->data); 5913 } 5914 #define SPEC_in2_i2_16u_shl 0 5915 5916 static void in2_i2_32u_shl(DisasContext *s, DisasOps *o) 5917 { 5918 uint64_t i2 = (uint32_t)get_field(s, i2); 5919 o->in2 = tcg_constant_i64(i2 << s->insn->data); 5920 } 5921 #define SPEC_in2_i2_32u_shl 0 5922 5923 #ifndef CONFIG_USER_ONLY 5924 static void in2_insn(DisasContext *s, DisasOps *o) 5925 { 5926 o->in2 = tcg_constant_i64(s->fields.raw_insn); 5927 } 5928 #define SPEC_in2_insn 0 5929 #endif 5930 5931 /* ====================================================================== */ 5932 5933 /* Find opc within the table of insns. This is formulated as a switch 5934 statement so that (1) we get compile-time notice of cut-paste errors 5935 for duplicated opcodes, and (2) the compiler generates the binary 5936 search tree, rather than us having to post-process the table. */ 5937 5938 #define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \ 5939 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, 0) 5940 5941 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \ 5942 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, 0) 5943 5944 #define F(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, FL) \ 5945 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, FL) 5946 5947 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) insn_ ## NM, 5948 5949 enum DisasInsnEnum { 5950 #include "insn-data.h.inc" 5951 }; 5952 5953 #undef E 5954 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) { \ 5955 .opc = OPC, \ 5956 .flags = FL, \ 5957 .fmt = FMT_##FT, \ 5958 .fac = FAC_##FC, \ 5959 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \ 5960 .name = #NM, \ 5961 .help_in1 = in1_##I1, \ 5962 .help_in2 = in2_##I2, \ 5963 .help_prep = prep_##P, \ 5964 .help_wout = wout_##W, \ 5965 .help_cout = cout_##CC, \ 5966 .help_op = op_##OP, \ 5967 .data = D \ 5968 }, 5969 5970 /* Allow 0 to be used for NULL in the table below. */ 5971 #define in1_0 NULL 5972 #define in2_0 NULL 5973 #define prep_0 NULL 5974 #define wout_0 NULL 5975 #define cout_0 NULL 5976 #define op_0 NULL 5977 5978 #define SPEC_in1_0 0 5979 #define SPEC_in2_0 0 5980 #define SPEC_prep_0 0 5981 #define SPEC_wout_0 0 5982 5983 /* Give smaller names to the various facilities. */ 5984 #define FAC_Z S390_FEAT_ZARCH 5985 #define FAC_CASS S390_FEAT_COMPARE_AND_SWAP_AND_STORE 5986 #define FAC_DFP S390_FEAT_DFP 5987 #define FAC_DFPR S390_FEAT_FLOATING_POINT_SUPPORT_ENH /* DFP-rounding */ 5988 #define FAC_DO S390_FEAT_STFLE_45 /* distinct-operands */ 5989 #define FAC_EE S390_FEAT_EXECUTE_EXT 5990 #define FAC_EI S390_FEAT_EXTENDED_IMMEDIATE 5991 #define FAC_FPE S390_FEAT_FLOATING_POINT_EXT 5992 #define FAC_FPSSH S390_FEAT_FLOATING_POINT_SUPPORT_ENH /* FPS-sign-handling */ 5993 #define FAC_FPRGR S390_FEAT_FLOATING_POINT_SUPPORT_ENH /* FPR-GR-transfer */ 5994 #define FAC_GIE S390_FEAT_GENERAL_INSTRUCTIONS_EXT 5995 #define FAC_HFP_MA S390_FEAT_HFP_MADDSUB 5996 #define FAC_HW S390_FEAT_STFLE_45 /* high-word */ 5997 #define FAC_IEEEE_SIM S390_FEAT_FLOATING_POINT_SUPPORT_ENH /* IEEE-exception-simulation */ 5998 #define FAC_MIE S390_FEAT_STFLE_49 /* misc-instruction-extensions */ 5999 #define FAC_LAT S390_FEAT_STFLE_49 /* load-and-trap */ 6000 #define FAC_LOC S390_FEAT_STFLE_45 /* load/store on condition 1 */ 6001 #define FAC_LOC2 S390_FEAT_STFLE_53 /* load/store on condition 2 */ 6002 #define FAC_LD S390_FEAT_LONG_DISPLACEMENT 6003 #define FAC_PC S390_FEAT_STFLE_45 /* population count */ 6004 #define FAC_SCF S390_FEAT_STORE_CLOCK_FAST 6005 #define FAC_SFLE S390_FEAT_STFLE 6006 #define FAC_ILA S390_FEAT_STFLE_45 /* interlocked-access-facility 1 */ 6007 #define FAC_MVCOS S390_FEAT_MOVE_WITH_OPTIONAL_SPEC 6008 #define FAC_LPP S390_FEAT_SET_PROGRAM_PARAMETERS /* load-program-parameter */ 6009 #define FAC_DAT_ENH S390_FEAT_DAT_ENH 6010 #define FAC_E2 S390_FEAT_EXTENDED_TRANSLATION_2 6011 #define FAC_EH S390_FEAT_STFLE_49 /* execution-hint */ 6012 #define FAC_PPA S390_FEAT_STFLE_49 /* processor-assist */ 6013 #define FAC_LZRB S390_FEAT_STFLE_53 /* load-and-zero-rightmost-byte */ 6014 #define FAC_ETF3 S390_FEAT_EXTENDED_TRANSLATION_3 6015 #define FAC_MSA S390_FEAT_MSA /* message-security-assist facility */ 6016 #define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */ 6017 #define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */ 6018 #define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */ 6019 #define FAC_MSA8 S390_FEAT_MSA_EXT_8 /* msa-extension-8 facility */ 6020 #define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME 6021 #define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */ 6022 #define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION 6023 #define FAC_V S390_FEAT_VECTOR /* vector facility */ 6024 #define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */ 6025 #define FAC_VE2 S390_FEAT_VECTOR_ENH2 /* vector enhancements facility 2 */ 6026 #define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */ 6027 #define FAC_MIE3 S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */ 6028 6029 static const DisasInsn insn_info[] = { 6030 #include "insn-data.h.inc" 6031 }; 6032 6033 #undef E 6034 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) \ 6035 case OPC: return &insn_info[insn_ ## NM]; 6036 6037 static const DisasInsn *lookup_opc(uint16_t opc) 6038 { 6039 switch (opc) { 6040 #include "insn-data.h.inc" 6041 default: 6042 return NULL; 6043 } 6044 } 6045 6046 #undef F 6047 #undef E 6048 #undef D 6049 #undef C 6050 6051 /* Extract a field from the insn. The INSN should be left-aligned in 6052 the uint64_t so that we can more easily utilize the big-bit-endian 6053 definitions we extract from the Principals of Operation. */ 6054 6055 static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn) 6056 { 6057 uint32_t r, m; 6058 6059 if (f->size == 0) { 6060 return; 6061 } 6062 6063 /* Zero extract the field from the insn. */ 6064 r = (insn << f->beg) >> (64 - f->size); 6065 6066 /* Sign-extend, or un-swap the field as necessary. */ 6067 switch (f->type) { 6068 case 0: /* unsigned */ 6069 break; 6070 case 1: /* signed */ 6071 assert(f->size <= 32); 6072 m = 1u << (f->size - 1); 6073 r = (r ^ m) - m; 6074 break; 6075 case 2: /* dl+dh split, signed 20 bit. */ 6076 r = ((int8_t)r << 12) | (r >> 8); 6077 break; 6078 case 3: /* MSB stored in RXB */ 6079 g_assert(f->size == 4); 6080 switch (f->beg) { 6081 case 8: 6082 r |= extract64(insn, 63 - 36, 1) << 4; 6083 break; 6084 case 12: 6085 r |= extract64(insn, 63 - 37, 1) << 4; 6086 break; 6087 case 16: 6088 r |= extract64(insn, 63 - 38, 1) << 4; 6089 break; 6090 case 32: 6091 r |= extract64(insn, 63 - 39, 1) << 4; 6092 break; 6093 default: 6094 g_assert_not_reached(); 6095 } 6096 break; 6097 default: 6098 abort(); 6099 } 6100 6101 /* 6102 * Validate that the "compressed" encoding we selected above is valid. 6103 * I.e. we haven't made two different original fields overlap. 6104 */ 6105 assert(((o->presentC >> f->indexC) & 1) == 0); 6106 o->presentC |= 1 << f->indexC; 6107 o->presentO |= 1 << f->indexO; 6108 6109 o->c[f->indexC] = r; 6110 } 6111 6112 /* Lookup the insn at the current PC, extracting the operands into O and 6113 returning the info struct for the insn. Returns NULL for invalid insn. */ 6114 6115 static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s) 6116 { 6117 uint64_t insn, pc = s->base.pc_next; 6118 int op, op2, ilen; 6119 const DisasInsn *info; 6120 6121 if (unlikely(s->ex_value)) { 6122 uint64_t be_insn; 6123 6124 /* Drop the EX data now, so that it's clear on exception paths. */ 6125 tcg_gen_st_i64(tcg_constant_i64(0), tcg_env, 6126 offsetof(CPUS390XState, ex_value)); 6127 6128 /* Extract the values saved by EXECUTE. */ 6129 insn = s->ex_value & 0xffffffffffff0000ull; 6130 ilen = s->ex_value & 0xf; 6131 op = insn >> 56; 6132 6133 /* Register insn bytes with translator so plugins work. */ 6134 be_insn = cpu_to_be64(insn); 6135 translator_fake_ld(&s->base, &be_insn, get_ilen(op)); 6136 } else { 6137 insn = ld_code2(env, s, pc); 6138 op = (insn >> 8) & 0xff; 6139 ilen = get_ilen(op); 6140 switch (ilen) { 6141 case 2: 6142 insn = insn << 48; 6143 break; 6144 case 4: 6145 insn = ld_code4(env, s, pc) << 32; 6146 break; 6147 case 6: 6148 insn = (insn << 48) | (ld_code4(env, s, pc + 2) << 16); 6149 break; 6150 default: 6151 g_assert_not_reached(); 6152 } 6153 } 6154 s->pc_tmp = s->base.pc_next + ilen; 6155 s->ilen = ilen; 6156 6157 /* We can't actually determine the insn format until we've looked up 6158 the full insn opcode. Which we can't do without locating the 6159 secondary opcode. Assume by default that OP2 is at bit 40; for 6160 those smaller insns that don't actually have a secondary opcode 6161 this will correctly result in OP2 = 0. */ 6162 switch (op) { 6163 case 0x01: /* E */ 6164 case 0x80: /* S */ 6165 case 0x82: /* S */ 6166 case 0x93: /* S */ 6167 case 0xb2: /* S, RRF, RRE, IE */ 6168 case 0xb3: /* RRE, RRD, RRF */ 6169 case 0xb9: /* RRE, RRF */ 6170 case 0xe5: /* SSE, SIL */ 6171 op2 = (insn << 8) >> 56; 6172 break; 6173 case 0xa5: /* RI */ 6174 case 0xa7: /* RI */ 6175 case 0xc0: /* RIL */ 6176 case 0xc2: /* RIL */ 6177 case 0xc4: /* RIL */ 6178 case 0xc6: /* RIL */ 6179 case 0xc8: /* SSF */ 6180 case 0xcc: /* RIL */ 6181 op2 = (insn << 12) >> 60; 6182 break; 6183 case 0xc5: /* MII */ 6184 case 0xc7: /* SMI */ 6185 case 0xd0 ... 0xdf: /* SS */ 6186 case 0xe1: /* SS */ 6187 case 0xe2: /* SS */ 6188 case 0xe8: /* SS */ 6189 case 0xe9: /* SS */ 6190 case 0xea: /* SS */ 6191 case 0xee ... 0xf3: /* SS */ 6192 case 0xf8 ... 0xfd: /* SS */ 6193 op2 = 0; 6194 break; 6195 default: 6196 op2 = (insn << 40) >> 56; 6197 break; 6198 } 6199 6200 memset(&s->fields, 0, sizeof(s->fields)); 6201 s->fields.raw_insn = insn; 6202 s->fields.op = op; 6203 s->fields.op2 = op2; 6204 6205 /* Lookup the instruction. */ 6206 info = lookup_opc(op << 8 | op2); 6207 s->insn = info; 6208 6209 /* If we found it, extract the operands. */ 6210 if (info != NULL) { 6211 DisasFormat fmt = info->fmt; 6212 int i; 6213 6214 for (i = 0; i < NUM_C_FIELD; ++i) { 6215 extract_field(&s->fields, &format_info[fmt].op[i], insn); 6216 } 6217 } 6218 return info; 6219 } 6220 6221 static bool is_afp_reg(int reg) 6222 { 6223 return reg % 2 || reg > 6; 6224 } 6225 6226 static bool is_fp_pair(int reg) 6227 { 6228 /* 0,1,4,5,8,9,12,13: to exclude the others, check for single bit */ 6229 return !(reg & 0x2); 6230 } 6231 6232 static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) 6233 { 6234 const DisasInsn *insn; 6235 DisasJumpType ret = DISAS_NEXT; 6236 DisasOps o = {}; 6237 bool icount = false; 6238 6239 /* Search for the insn in the table. */ 6240 insn = extract_insn(env, s); 6241 6242 /* Update insn_start now that we know the ILEN. */ 6243 tcg_set_insn_start_param(s->base.insn_start, 2, s->ilen); 6244 6245 /* Not found means unimplemented/illegal opcode. */ 6246 if (insn == NULL) { 6247 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n", 6248 s->fields.op, s->fields.op2); 6249 gen_illegal_opcode(s); 6250 ret = DISAS_NORETURN; 6251 goto out; 6252 } 6253 6254 #ifndef CONFIG_USER_ONLY 6255 if (s->base.tb->flags & FLAG_MASK_PER_IFETCH) { 6256 /* With ifetch set, psw_addr and cc_op are always up-to-date. */ 6257 gen_helper_per_ifetch(tcg_env, tcg_constant_i32(s->ilen)); 6258 } 6259 #endif 6260 6261 /* process flags */ 6262 if (insn->flags) { 6263 /* privileged instruction */ 6264 if ((s->base.tb->flags & FLAG_MASK_PSTATE) && (insn->flags & IF_PRIV)) { 6265 gen_program_exception(s, PGM_PRIVILEGED); 6266 ret = DISAS_NORETURN; 6267 goto out; 6268 } 6269 6270 /* if AFP is not enabled, instructions and registers are forbidden */ 6271 if (!(s->base.tb->flags & FLAG_MASK_AFP)) { 6272 uint8_t dxc = 0; 6273 6274 if ((insn->flags & IF_AFP1) && is_afp_reg(get_field(s, r1))) { 6275 dxc = 1; 6276 } 6277 if ((insn->flags & IF_AFP2) && is_afp_reg(get_field(s, r2))) { 6278 dxc = 1; 6279 } 6280 if ((insn->flags & IF_AFP3) && is_afp_reg(get_field(s, r3))) { 6281 dxc = 1; 6282 } 6283 if (insn->flags & IF_BFP) { 6284 dxc = 2; 6285 } 6286 if (insn->flags & IF_DFP) { 6287 dxc = 3; 6288 } 6289 if (insn->flags & IF_VEC) { 6290 dxc = 0xfe; 6291 } 6292 if (dxc) { 6293 gen_data_exception(dxc); 6294 ret = DISAS_NORETURN; 6295 goto out; 6296 } 6297 } 6298 6299 /* if vector instructions not enabled, executing them is forbidden */ 6300 if (insn->flags & IF_VEC) { 6301 if (!((s->base.tb->flags & FLAG_MASK_VECTOR))) { 6302 gen_data_exception(0xfe); 6303 ret = DISAS_NORETURN; 6304 goto out; 6305 } 6306 } 6307 6308 /* input/output is the special case for icount mode */ 6309 if (unlikely(insn->flags & IF_IO)) { 6310 icount = translator_io_start(&s->base); 6311 } 6312 } 6313 6314 /* Check for insn specification exceptions. */ 6315 if (insn->spec) { 6316 if ((insn->spec & SPEC_r1_even && get_field(s, r1) & 1) || 6317 (insn->spec & SPEC_r2_even && get_field(s, r2) & 1) || 6318 (insn->spec & SPEC_r3_even && get_field(s, r3) & 1) || 6319 (insn->spec & SPEC_r1_f128 && !is_fp_pair(get_field(s, r1))) || 6320 (insn->spec & SPEC_r2_f128 && !is_fp_pair(get_field(s, r2)))) { 6321 gen_program_exception(s, PGM_SPECIFICATION); 6322 ret = DISAS_NORETURN; 6323 goto out; 6324 } 6325 } 6326 6327 /* Implement the instruction. */ 6328 if (insn->help_in1) { 6329 insn->help_in1(s, &o); 6330 } 6331 if (insn->help_in2) { 6332 insn->help_in2(s, &o); 6333 } 6334 if (insn->help_prep) { 6335 insn->help_prep(s, &o); 6336 } 6337 if (insn->help_op) { 6338 ret = insn->help_op(s, &o); 6339 if (ret == DISAS_NORETURN) { 6340 goto out; 6341 } 6342 } 6343 if (insn->help_wout) { 6344 insn->help_wout(s, &o); 6345 } 6346 if (insn->help_cout) { 6347 insn->help_cout(s, &o); 6348 } 6349 6350 /* io should be the last instruction in tb when icount is enabled */ 6351 if (unlikely(icount && ret == DISAS_NEXT)) { 6352 ret = DISAS_TOO_MANY; 6353 } 6354 6355 #ifndef CONFIG_USER_ONLY 6356 if (s->base.tb->flags & FLAG_MASK_PER_IFETCH) { 6357 switch (ret) { 6358 case DISAS_TOO_MANY: 6359 s->base.is_jmp = DISAS_PC_CC_UPDATED; 6360 /* fall through */ 6361 case DISAS_NEXT: 6362 tcg_gen_movi_i64(psw_addr, s->pc_tmp); 6363 break; 6364 default: 6365 break; 6366 } 6367 update_cc_op(s); 6368 gen_helper_per_check_exception(tcg_env); 6369 } 6370 #endif 6371 6372 out: 6373 /* Advance to the next instruction. */ 6374 s->base.pc_next = s->pc_tmp; 6375 return ret; 6376 } 6377 6378 static void s390x_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 6379 { 6380 DisasContext *dc = container_of(dcbase, DisasContext, base); 6381 6382 /* 31-bit mode */ 6383 if (!(dc->base.tb->flags & FLAG_MASK_64)) { 6384 dc->base.pc_first &= 0x7fffffff; 6385 dc->base.pc_next = dc->base.pc_first; 6386 } 6387 6388 dc->cc_op = CC_OP_DYNAMIC; 6389 dc->ex_value = dc->base.tb->cs_base; 6390 dc->exit_to_mainloop = dc->ex_value; 6391 } 6392 6393 static void s390x_tr_tb_start(DisasContextBase *db, CPUState *cs) 6394 { 6395 } 6396 6397 static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 6398 { 6399 DisasContext *dc = container_of(dcbase, DisasContext, base); 6400 6401 /* Delay the set of ilen until we've read the insn. */ 6402 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 0); 6403 } 6404 6405 static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s, 6406 uint64_t pc) 6407 { 6408 uint64_t insn = translator_lduw(env, &s->base, pc); 6409 6410 return pc + get_ilen((insn >> 8) & 0xff); 6411 } 6412 6413 static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 6414 { 6415 CPUS390XState *env = cpu_env(cs); 6416 DisasContext *dc = container_of(dcbase, DisasContext, base); 6417 6418 dc->base.is_jmp = translate_one(env, dc); 6419 if (dc->base.is_jmp == DISAS_NEXT) { 6420 if (dc->ex_value || 6421 !translator_is_same_page(dcbase, dc->base.pc_next) || 6422 !translator_is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next))) { 6423 dc->base.is_jmp = DISAS_TOO_MANY; 6424 } 6425 } 6426 } 6427 6428 static void s390x_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 6429 { 6430 DisasContext *dc = container_of(dcbase, DisasContext, base); 6431 6432 switch (dc->base.is_jmp) { 6433 case DISAS_NORETURN: 6434 break; 6435 case DISAS_TOO_MANY: 6436 update_psw_addr(dc); 6437 /* FALLTHRU */ 6438 case DISAS_PC_UPDATED: 6439 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the 6440 cc op type is in env */ 6441 update_cc_op(dc); 6442 /* FALLTHRU */ 6443 case DISAS_PC_CC_UPDATED: 6444 /* Exit the TB, either by raising a debug exception or by return. */ 6445 if (dc->exit_to_mainloop) { 6446 tcg_gen_exit_tb(NULL, 0); 6447 } else { 6448 tcg_gen_lookup_and_goto_ptr(); 6449 } 6450 break; 6451 default: 6452 g_assert_not_reached(); 6453 } 6454 } 6455 6456 static bool s390x_tr_disas_log(const DisasContextBase *dcbase, 6457 CPUState *cs, FILE *logfile) 6458 { 6459 DisasContext *dc = container_of(dcbase, DisasContext, base); 6460 6461 if (unlikely(dc->ex_value)) { 6462 /* The ex_value has been recorded with translator_fake_ld. */ 6463 fprintf(logfile, "IN: EXECUTE\n"); 6464 target_disas(logfile, cs, &dc->base); 6465 return true; 6466 } 6467 return false; 6468 } 6469 6470 static const TranslatorOps s390x_tr_ops = { 6471 .init_disas_context = s390x_tr_init_disas_context, 6472 .tb_start = s390x_tr_tb_start, 6473 .insn_start = s390x_tr_insn_start, 6474 .translate_insn = s390x_tr_translate_insn, 6475 .tb_stop = s390x_tr_tb_stop, 6476 .disas_log = s390x_tr_disas_log, 6477 }; 6478 6479 void s390x_translate_code(CPUState *cs, TranslationBlock *tb, 6480 int *max_insns, vaddr pc, void *host_pc) 6481 { 6482 DisasContext dc; 6483 6484 translator_loop(cs, tb, max_insns, pc, host_pc, &s390x_tr_ops, &dc.base); 6485 } 6486 6487 void s390x_restore_state_to_opc(CPUState *cs, 6488 const TranslationBlock *tb, 6489 const uint64_t *data) 6490 { 6491 CPUS390XState *env = cpu_env(cs); 6492 int cc_op = data[1]; 6493 6494 env->psw.addr = data[0]; 6495 6496 /* Update the CC opcode if it is not already up-to-date. */ 6497 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) { 6498 env->cc_op = cc_op; 6499 } 6500 6501 /* Record ILEN. */ 6502 env->int_pgm_ilen = data[2]; 6503 } 6504