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