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