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