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