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