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