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