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