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