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