]> git.proxmox.com Git - mirror_qemu.git/blame - target/s390x/translate.c
s390x/pci: let pci devices start in configured mode
[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 update_psw_addr(s);
2128 gen_op_calc_cc(s);
972e35b9 2129
8df7eef3
AJ
2130 gen_helper_diag(cpu_env, r1, r3, func_code);
2131
2132 tcg_temp_free_i32(func_code);
2133 tcg_temp_free_i32(r3);
2134 tcg_temp_free_i32(r1);
972e35b9
RH
2135 return NO_EXIT;
2136}
2137#endif
2138
891452e5
RH
2139static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
2140{
2141 gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
2142 return_low128(o->out);
2143 return NO_EXIT;
2144}
2145
2146static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
2147{
2148 gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
2149 return_low128(o->out);
2150 return NO_EXIT;
2151}
2152
2153static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
2154{
2155 gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
2156 return_low128(o->out);
2157 return NO_EXIT;
2158}
2159
2160static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
2161{
2162 gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
2163 return_low128(o->out);
2164 return NO_EXIT;
2165}
2166
f08a5c31
RH
2167static ExitStatus op_deb(DisasContext *s, DisasOps *o)
2168{
2169 gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
2170 return NO_EXIT;
2171}
2172
2173static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
2174{
2175 gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
2176 return NO_EXIT;
2177}
2178
2179static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
2180{
2181 gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2182 return_low128(o->out2);
2183 return NO_EXIT;
2184}
2185
d62a4c97
RH
2186static ExitStatus op_ear(DisasContext *s, DisasOps *o)
2187{
2188 int r2 = get_field(s->fields, r2);
2189 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
2190 return NO_EXIT;
2191}
2192
0774710f
RH
2193static ExitStatus op_ecag(DisasContext *s, DisasOps *o)
2194{
2195 /* No cache information provided. */
2196 tcg_gen_movi_i64(o->out, -1);
2197 return NO_EXIT;
2198}
2199
ea20490f
RH
2200static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
2201{
2202 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
2203 return NO_EXIT;
2204}
2205
e30a9d3f
RH
2206static ExitStatus op_epsw(DisasContext *s, DisasOps *o)
2207{
2208 int r1 = get_field(s->fields, r1);
2209 int r2 = get_field(s->fields, r2);
2210 TCGv_i64 t = tcg_temp_new_i64();
2211
2212 /* Note the "subsequently" in the PoO, which implies a defined result
2213 if r1 == r2. Thus we cannot defer these writes to an output hook. */
2214 tcg_gen_shri_i64(t, psw_mask, 32);
2215 store_reg32_i64(r1, t);
2216 if (r2 != 0) {
2217 store_reg32_i64(r2, psw_mask);
2218 }
2219
2220 tcg_temp_free_i64(t);
2221 return NO_EXIT;
2222}
2223
6e764e97
RH
2224static ExitStatus op_ex(DisasContext *s, DisasOps *o)
2225{
a72da8b7 2226 int r1 = get_field(s->fields, r1);
83500793 2227 TCGv_i32 ilen;
a72da8b7 2228 TCGv_i64 v1;
6e764e97 2229
303c681a
RH
2230 /* Nested EXECUTE is not allowed. */
2231 if (unlikely(s->ex_value)) {
2232 gen_program_exception(s, PGM_EXECUTE);
2233 return EXIT_NORETURN;
2234 }
2235
6e764e97 2236 update_psw_addr(s);
303c681a 2237 update_cc_op(s);
6e764e97 2238
a72da8b7
RH
2239 if (r1 == 0) {
2240 v1 = tcg_const_i64(0);
2241 } else {
2242 v1 = regs[r1];
2243 }
2244
99e57856 2245 ilen = tcg_const_i32(s->ilen);
a72da8b7 2246 gen_helper_ex(cpu_env, ilen, v1, o->in2);
83500793 2247 tcg_temp_free_i32(ilen);
6e764e97 2248
a72da8b7
RH
2249 if (r1 == 0) {
2250 tcg_temp_free_i64(v1);
2251 }
2252
06fc0348 2253 return EXIT_PC_CC_UPDATED;
6e764e97
RH
2254}
2255
ed0bcece
AJ
2256static ExitStatus op_fieb(DisasContext *s, DisasOps *o)
2257{
2258 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2259 gen_helper_fieb(o->out, cpu_env, o->in2, m3);
2260 tcg_temp_free_i32(m3);
2261 return NO_EXIT;
2262}
2263
2264static ExitStatus op_fidb(DisasContext *s, DisasOps *o)
2265{
2266 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2267 gen_helper_fidb(o->out, cpu_env, o->in2, m3);
2268 tcg_temp_free_i32(m3);
2269 return NO_EXIT;
2270}
2271
2272static ExitStatus op_fixb(DisasContext *s, DisasOps *o)
2273{
2274 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
2275 gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3);
2276 return_low128(o->out2);
2277 tcg_temp_free_i32(m3);
2278 return NO_EXIT;
2279}
2280
102bf2c6
RH
2281static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
2282{
2283 /* We'll use the original input for cc computation, since we get to
2284 compare that against 0, which ought to be better than comparing
2285 the real output against 64. It also lets cc_dst be a convenient
2286 temporary during our computation. */
2287 gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
2288
2289 /* R1 = IN ? CLZ(IN) : 64. */
0f9712b1 2290 tcg_gen_clzi_i64(o->out, o->in2, 64);
102bf2c6
RH
2291
2292 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2293 value by 64, which is undefined. But since the shift is 64 iff the
2294 input is zero, we still get the correct result after and'ing. */
2295 tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
2296 tcg_gen_shr_i64(o->out2, o->out2, o->out);
2297 tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
2298 return NO_EXIT;
2299}
2300
58a9e35b
RH
2301static ExitStatus op_icm(DisasContext *s, DisasOps *o)
2302{
2303 int m3 = get_field(s->fields, m3);
2304 int pos, len, base = s->insn->data;
2305 TCGv_i64 tmp = tcg_temp_new_i64();
2306 uint64_t ccm;
2307
2308 switch (m3) {
2309 case 0xf:
2310 /* Effectively a 32-bit load. */
2311 tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
2312 len = 32;
2313 goto one_insert;
2314
2315 case 0xc:
2316 case 0x6:
2317 case 0x3:
2318 /* Effectively a 16-bit load. */
2319 tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
2320 len = 16;
2321 goto one_insert;
2322
2323 case 0x8:
2324 case 0x4:
2325 case 0x2:
2326 case 0x1:
2327 /* Effectively an 8-bit load. */
2328 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2329 len = 8;
2330 goto one_insert;
2331
2332 one_insert:
2333 pos = base + ctz32(m3) * 8;
2334 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
2335 ccm = ((1ull << len) - 1) << pos;
2336 break;
2337
2338 default:
2339 /* This is going to be a sequence of loads and inserts. */
2340 pos = base + 32 - 8;
2341 ccm = 0;
2342 while (m3) {
2343 if (m3 & 0x8) {
2344 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2345 tcg_gen_addi_i64(o->in2, o->in2, 1);
2346 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
2347 ccm |= 0xff << pos;
2348 }
2349 m3 = (m3 << 1) & 0xf;
2350 pos -= 8;
2351 }
2352 break;
2353 }
2354
2355 tcg_gen_movi_i64(tmp, ccm);
2356 gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
2357 tcg_temp_free_i64(tmp);
2358 return NO_EXIT;
2359}
2360
facfc864
RH
2361static ExitStatus op_insi(DisasContext *s, DisasOps *o)
2362{
2363 int shift = s->insn->data & 0xff;
2364 int size = s->insn->data >> 8;
2365 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
2366 return NO_EXIT;
2367}
2368
6e2704e7
RH
2369static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
2370{
2371 TCGv_i64 t1;
2372
2373 gen_op_calc_cc(s);
2374 tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
2375
2376 t1 = tcg_temp_new_i64();
2377 tcg_gen_shli_i64(t1, psw_mask, 20);
2378 tcg_gen_shri_i64(t1, t1, 36);
2379 tcg_gen_or_i64(o->out, o->out, t1);
2380
2381 tcg_gen_extu_i32_i64(t1, cc_op);
2382 tcg_gen_shli_i64(t1, t1, 28);
2383 tcg_gen_or_i64(o->out, o->out, t1);
2384 tcg_temp_free_i64(t1);
2385 return NO_EXIT;
2386}
2387
cfef53e3 2388#ifndef CONFIG_USER_ONLY
be7f28de
DH
2389static ExitStatus op_idte(DisasContext *s, DisasOps *o)
2390{
2391 TCGv_i32 m4;
2392
2393 check_privileged(s);
2394 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
2395 m4 = tcg_const_i32(get_field(s->fields, m4));
2396 } else {
2397 m4 = tcg_const_i32(0);
2398 }
2399 gen_helper_idte(cpu_env, o->in1, o->in2, m4);
2400 tcg_temp_free_i32(m4);
2401 return NO_EXIT;
2402}
2403
cfef53e3
RH
2404static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
2405{
1f58720c
AJ
2406 TCGv_i32 m4;
2407
cfef53e3 2408 check_privileged(s);
faf1c63d
DH
2409 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING)) {
2410 m4 = tcg_const_i32(get_field(s->fields, m4));
2411 } else {
2412 m4 = tcg_const_i32(0);
2413 }
1f58720c
AJ
2414 gen_helper_ipte(cpu_env, o->in1, o->in2, m4);
2415 tcg_temp_free_i32(m4);
cfef53e3
RH
2416 return NO_EXIT;
2417}
8026417c
RH
2418
2419static ExitStatus op_iske(DisasContext *s, DisasOps *o)
2420{
2421 check_privileged(s);
2422 gen_helper_iske(o->out, cpu_env, o->in2);
2423 return NO_EXIT;
2424}
cfef53e3
RH
2425#endif
2426
7705c750
DH
2427static ExitStatus op_msa(DisasContext *s, DisasOps *o)
2428{
2429 int r1 = have_field(s->fields, r1) ? get_field(s->fields, r1) : 0;
2430 int r2 = have_field(s->fields, r2) ? get_field(s->fields, r2) : 0;
2431 int r3 = have_field(s->fields, r3) ? get_field(s->fields, r3) : 0;
2432 TCGv_i32 t_r1, t_r2, t_r3, type;
2433
2434 switch (s->insn->data) {
2435 case S390_FEAT_TYPE_KMCTR:
2436 if (r3 & 1 || !r3) {
2437 gen_program_exception(s, PGM_SPECIFICATION);
2438 return EXIT_NORETURN;
2439 }
2440 /* FALL THROUGH */
2441 case S390_FEAT_TYPE_PPNO:
2442 case S390_FEAT_TYPE_KMF:
2443 case S390_FEAT_TYPE_KMC:
2444 case S390_FEAT_TYPE_KMO:
2445 case S390_FEAT_TYPE_KM:
2446 if (r1 & 1 || !r1) {
2447 gen_program_exception(s, PGM_SPECIFICATION);
2448 return EXIT_NORETURN;
2449 }
2450 /* FALL THROUGH */
2451 case S390_FEAT_TYPE_KMAC:
2452 case S390_FEAT_TYPE_KIMD:
2453 case S390_FEAT_TYPE_KLMD:
2454 if (r2 & 1 || !r2) {
2455 gen_program_exception(s, PGM_SPECIFICATION);
2456 return EXIT_NORETURN;
2457 }
2458 /* FALL THROUGH */
2459 case S390_FEAT_TYPE_PCKMO:
2460 case S390_FEAT_TYPE_PCC:
2461 break;
2462 default:
2463 g_assert_not_reached();
2464 };
2465
2466 t_r1 = tcg_const_i32(r1);
2467 t_r2 = tcg_const_i32(r2);
2468 t_r3 = tcg_const_i32(r3);
2469 type = tcg_const_i32(s->insn->data);
2470 gen_helper_msa(cc_op, cpu_env, t_r1, t_r2, t_r3, type);
2471 set_cc_static(s);
2472 tcg_temp_free_i32(t_r1);
2473 tcg_temp_free_i32(t_r2);
2474 tcg_temp_free_i32(t_r3);
2475 tcg_temp_free_i32(type);
2476 return NO_EXIT;
2477}
2478
9c8be598
AJ
2479static ExitStatus op_keb(DisasContext *s, DisasOps *o)
2480{
2481 gen_helper_keb(cc_op, cpu_env, o->in1, o->in2);
2482 set_cc_static(s);
2483 return NO_EXIT;
2484}
2485
2486static ExitStatus op_kdb(DisasContext *s, DisasOps *o)
2487{
2488 gen_helper_kdb(cc_op, cpu_env, o->in1, o->in2);
2489 set_cc_static(s);
2490 return NO_EXIT;
2491}
2492
2493static ExitStatus op_kxb(DisasContext *s, DisasOps *o)
2494{
2495 gen_helper_kxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
2496 set_cc_static(s);
2497 return NO_EXIT;
2498}
2499
4dba4d6f
RH
2500static ExitStatus op_laa(DisasContext *s, DisasOps *o)
2501{
2502 /* The real output is indeed the original value in memory;
2503 recompute the addition for the computation of CC. */
2504 tcg_gen_atomic_fetch_add_i64(o->in2, o->in2, o->in1, get_mem_index(s),
2505 s->insn->data | MO_ALIGN);
2506 /* However, we need to recompute the addition for setting CC. */
2507 tcg_gen_add_i64(o->out, o->in1, o->in2);
2508 return NO_EXIT;
2509}
2510
2511static ExitStatus op_lan(DisasContext *s, DisasOps *o)
2512{
2513 /* The real output is indeed the original value in memory;
2514 recompute the addition for the computation of CC. */
2515 tcg_gen_atomic_fetch_and_i64(o->in2, o->in2, o->in1, get_mem_index(s),
2516 s->insn->data | MO_ALIGN);
2517 /* However, we need to recompute the operation for setting CC. */
2518 tcg_gen_and_i64(o->out, o->in1, o->in2);
2519 return NO_EXIT;
2520}
2521
2522static ExitStatus op_lao(DisasContext *s, DisasOps *o)
2523{
2524 /* The real output is indeed the original value in memory;
2525 recompute the addition for the computation of CC. */
2526 tcg_gen_atomic_fetch_or_i64(o->in2, o->in2, o->in1, get_mem_index(s),
2527 s->insn->data | MO_ALIGN);
2528 /* However, we need to recompute the operation for setting CC. */
2529 tcg_gen_or_i64(o->out, o->in1, o->in2);
2530 return NO_EXIT;
2531}
2532
2533static ExitStatus op_lax(DisasContext *s, DisasOps *o)
2534{
2535 /* The real output is indeed the original value in memory;
2536 recompute the addition for the computation of CC. */
2537 tcg_gen_atomic_fetch_xor_i64(o->in2, o->in2, o->in1, get_mem_index(s),
2538 s->insn->data | MO_ALIGN);
2539 /* However, we need to recompute the operation for setting CC. */
2540 tcg_gen_xor_i64(o->out, o->in1, o->in2);
2541 return NO_EXIT;
2542}
2543
587626f8
RH
2544static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
2545{
2546 gen_helper_ldeb(o->out, cpu_env, o->in2);
2547 return NO_EXIT;
2548}
2549
2550static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
2551{
2552 gen_helper_ledb(o->out, cpu_env, o->in2);
2553 return NO_EXIT;
2554}
2555
2556static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
2557{
2558 gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
2559 return NO_EXIT;
2560}
2561
2562static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
2563{
2564 gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
2565 return NO_EXIT;
2566}
2567
2568static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
2569{
2570 gen_helper_lxdb(o->out, cpu_env, o->in2);
2571 return_low128(o->out2);
2572 return NO_EXIT;
2573}
2574
2575static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
2576{
2577 gen_helper_lxeb(o->out, cpu_env, o->in2);
2578 return_low128(o->out2);
2579 return NO_EXIT;
2580}
2581
7691c23b
RH
2582static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
2583{
2584 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
2585 return NO_EXIT;
2586}
2587
c698d876
RH
2588static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
2589{
2590 tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
2591 return NO_EXIT;
2592}
2593
2594static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
2595{
2596 tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
2597 return NO_EXIT;
2598}
2599
2600static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
2601{
2602 tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
2603 return NO_EXIT;
2604}
2605
2606static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
2607{
2608 tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
2609 return NO_EXIT;
2610}
2611
22c37a08
RH
2612static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
2613{
2614 tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
2615 return NO_EXIT;
2616}
2617
2618static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
2619{
2620 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
2621 return NO_EXIT;
2622}
2623
2624static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
2625{
2626 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
2627 return NO_EXIT;
2628}
2629
782a8479
AJ
2630static ExitStatus op_lat(DisasContext *s, DisasOps *o)
2631{
2632 TCGLabel *lab = gen_new_label();
2633 store_reg32_i64(get_field(s->fields, r1), o->in2);
2634 /* The value is stored even in case of trap. */
2635 tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab);
2636 gen_trap(s);
2637 gen_set_label(lab);
2638 return NO_EXIT;
2639}
2640
2641static ExitStatus op_lgat(DisasContext *s, DisasOps *o)
2642{
2643 TCGLabel *lab = gen_new_label();
2644 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
2645 /* The value is stored even in case of trap. */
2646 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
2647 gen_trap(s);
2648 gen_set_label(lab);
2649 return NO_EXIT;
2650}
2651
2652static ExitStatus op_lfhat(DisasContext *s, DisasOps *o)
2653{
2654 TCGLabel *lab = gen_new_label();
2655 store_reg32h_i64(get_field(s->fields, r1), o->in2);
2656 /* The value is stored even in case of trap. */
2657 tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab);
2658 gen_trap(s);
2659 gen_set_label(lab);
2660 return NO_EXIT;
2661}
2662
2663static ExitStatus op_llgfat(DisasContext *s, DisasOps *o)
2664{
2665 TCGLabel *lab = gen_new_label();
2666 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
2667 /* The value is stored even in case of trap. */
2668 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
2669 gen_trap(s);
2670 gen_set_label(lab);
2671 return NO_EXIT;
2672}
2673
2674static ExitStatus op_llgtat(DisasContext *s, DisasOps *o)
2675{
2676 TCGLabel *lab = gen_new_label();
2677 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
2678 /* The value is stored even in case of trap. */
2679 tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab);
2680 gen_trap(s);
2681 gen_set_label(lab);
2682 return NO_EXIT;
2683}
2684
632086da
RH
2685static ExitStatus op_loc(DisasContext *s, DisasOps *o)
2686{
2687 DisasCompare c;
2688
2689 disas_jcc(s, &c, get_field(s->fields, m3));
2690
2691 if (c.is_64) {
2692 tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
2693 o->in2, o->in1);
2694 free_compare(&c);
2695 } else {
2696 TCGv_i32 t32 = tcg_temp_new_i32();
2697 TCGv_i64 t, z;
2698
2699 tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
2700 free_compare(&c);
2701
2702 t = tcg_temp_new_i64();
2703 tcg_gen_extu_i32_i64(t, t32);
2704 tcg_temp_free_i32(t32);
2705
2706 z = tcg_const_i64(0);
2707 tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
2708 tcg_temp_free_i64(t);
2709 tcg_temp_free_i64(z);
2710 }
2711
2712 return NO_EXIT;
2713}
2714
8b5ff571 2715#ifndef CONFIG_USER_ONLY
504488b8
RH
2716static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
2717{
2718 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2719 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2720 check_privileged(s);
504488b8
RH
2721 gen_helper_lctl(cpu_env, r1, o->in2, r3);
2722 tcg_temp_free_i32(r1);
2723 tcg_temp_free_i32(r3);
9dec2388
DH
2724 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
2725 return EXIT_PC_STALE_NOCHAIN;
504488b8
RH
2726}
2727
3e398cf9
RH
2728static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
2729{
2730 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2731 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2732 check_privileged(s);
3e398cf9
RH
2733 gen_helper_lctlg(cpu_env, r1, o->in2, r3);
2734 tcg_temp_free_i32(r1);
2735 tcg_temp_free_i32(r3);
9dec2388
DH
2736 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
2737 return EXIT_PC_STALE_NOCHAIN;
3e398cf9 2738}
1807aaa5 2739
d8fe4a9c
RH
2740static ExitStatus op_lra(DisasContext *s, DisasOps *o)
2741{
2742 check_privileged(s);
d8fe4a9c
RH
2743 gen_helper_lra(o->out, cpu_env, o->in2);
2744 set_cc_static(s);
2745 return NO_EXIT;
2746}
2747
190b2422
MB
2748static ExitStatus op_lpp(DisasContext *s, DisasOps *o)
2749{
2750 check_privileged(s);
2751
2752 tcg_gen_st_i64(o->in2, cpu_env, offsetof(CPUS390XState, pp));
2753 return NO_EXIT;
2754}
2755
8b5ff571
RH
2756static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
2757{
2758 TCGv_i64 t1, t2;
2759
2760 check_privileged(s);
3da0ab35 2761 per_breaking_event(s);
8b5ff571
RH
2762
2763 t1 = tcg_temp_new_i64();
2764 t2 = tcg_temp_new_i64();
2765 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2766 tcg_gen_addi_i64(o->in2, o->in2, 4);
2767 tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
2768 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2769 tcg_gen_shli_i64(t1, t1, 32);
2770 gen_helper_load_psw(cpu_env, t1, t2);
2771 tcg_temp_free_i64(t1);
2772 tcg_temp_free_i64(t2);
2773 return EXIT_NORETURN;
2774}
7ab938d7
RH
2775
2776static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
2777{
2778 TCGv_i64 t1, t2;
2779
2780 check_privileged(s);
3da0ab35 2781 per_breaking_event(s);
7ab938d7
RH
2782
2783 t1 = tcg_temp_new_i64();
2784 t2 = tcg_temp_new_i64();
2785 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2786 tcg_gen_addi_i64(o->in2, o->in2, 8);
2787 tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
2788 gen_helper_load_psw(cpu_env, t1, t2);
2789 tcg_temp_free_i64(t1);
2790 tcg_temp_free_i64(t2);
2791 return EXIT_NORETURN;
2792}
8b5ff571
RH
2793#endif
2794
7df3e93a
RH
2795static ExitStatus op_lam(DisasContext *s, DisasOps *o)
2796{
2797 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2798 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
7df3e93a
RH
2799 gen_helper_lam(cpu_env, r1, o->in2, r3);
2800 tcg_temp_free_i32(r1);
2801 tcg_temp_free_i32(r3);
2802 return NO_EXIT;
2803}
2804
77f8d6c3
RH
2805static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
2806{
2807 int r1 = get_field(s->fields, r1);
2808 int r3 = get_field(s->fields, r3);
aa752a4a 2809 TCGv_i64 t1, t2;
77f8d6c3 2810
aa752a4a
AJ
2811 /* Only one register to read. */
2812 t1 = tcg_temp_new_i64();
2813 if (unlikely(r1 == r3)) {
2814 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2815 store_reg32_i64(r1, t1);
2816 tcg_temp_free(t1);
2817 return NO_EXIT;
2818 }
2819
2820 /* First load the values of the first and last registers to trigger
2821 possible page faults. */
2822 t2 = tcg_temp_new_i64();
2823 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2824 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
2825 tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
2826 store_reg32_i64(r1, t1);
2827 store_reg32_i64(r3, t2);
2828
2829 /* Only two registers to read. */
2830 if (((r1 + 1) & 15) == r3) {
2831 tcg_temp_free(t2);
2832 tcg_temp_free(t1);
2833 return NO_EXIT;
2834 }
2835
2836 /* Then load the remaining registers. Page fault can't occur. */
2837 r3 = (r3 - 1) & 15;
2838 tcg_gen_movi_i64(t2, 4);
2839 while (r1 != r3) {
77f8d6c3 2840 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2841 tcg_gen_add_i64(o->in2, o->in2, t2);
2842 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2843 store_reg32_i64(r1, t1);
77f8d6c3 2844 }
aa752a4a
AJ
2845 tcg_temp_free(t2);
2846 tcg_temp_free(t1);
77f8d6c3 2847
77f8d6c3
RH
2848 return NO_EXIT;
2849}
2850
2851static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
2852{
2853 int r1 = get_field(s->fields, r1);
2854 int r3 = get_field(s->fields, r3);
aa752a4a 2855 TCGv_i64 t1, t2;
77f8d6c3 2856
aa752a4a
AJ
2857 /* Only one register to read. */
2858 t1 = tcg_temp_new_i64();
2859 if (unlikely(r1 == r3)) {
2860 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2861 store_reg32h_i64(r1, t1);
2862 tcg_temp_free(t1);
2863 return NO_EXIT;
2864 }
2865
2866 /* First load the values of the first and last registers to trigger
2867 possible page faults. */
2868 t2 = tcg_temp_new_i64();
2869 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2870 tcg_gen_addi_i64(t2, o->in2, 4 * ((r3 - r1) & 15));
2871 tcg_gen_qemu_ld32u(t2, t2, get_mem_index(s));
2872 store_reg32h_i64(r1, t1);
2873 store_reg32h_i64(r3, t2);
2874
2875 /* Only two registers to read. */
2876 if (((r1 + 1) & 15) == r3) {
2877 tcg_temp_free(t2);
2878 tcg_temp_free(t1);
2879 return NO_EXIT;
2880 }
2881
2882 /* Then load the remaining registers. Page fault can't occur. */
2883 r3 = (r3 - 1) & 15;
2884 tcg_gen_movi_i64(t2, 4);
2885 while (r1 != r3) {
77f8d6c3 2886 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2887 tcg_gen_add_i64(o->in2, o->in2, t2);
2888 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2889 store_reg32h_i64(r1, t1);
77f8d6c3 2890 }
aa752a4a
AJ
2891 tcg_temp_free(t2);
2892 tcg_temp_free(t1);
77f8d6c3 2893
77f8d6c3
RH
2894 return NO_EXIT;
2895}
2896
2897static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
2898{
2899 int r1 = get_field(s->fields, r1);
2900 int r3 = get_field(s->fields, r3);
aa752a4a 2901 TCGv_i64 t1, t2;
77f8d6c3 2902
aa752a4a
AJ
2903 /* Only one register to read. */
2904 if (unlikely(r1 == r3)) {
77f8d6c3 2905 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
aa752a4a
AJ
2906 return NO_EXIT;
2907 }
2908
2909 /* First load the values of the first and last registers to trigger
2910 possible page faults. */
2911 t1 = tcg_temp_new_i64();
2912 t2 = tcg_temp_new_i64();
2913 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2914 tcg_gen_addi_i64(t2, o->in2, 8 * ((r3 - r1) & 15));
2915 tcg_gen_qemu_ld64(regs[r3], t2, get_mem_index(s));
2916 tcg_gen_mov_i64(regs[r1], t1);
2917 tcg_temp_free(t2);
2918
2919 /* Only two registers to read. */
2920 if (((r1 + 1) & 15) == r3) {
2921 tcg_temp_free(t1);
2922 return NO_EXIT;
2923 }
2924
2925 /* Then load the remaining registers. Page fault can't occur. */
2926 r3 = (r3 - 1) & 15;
2927 tcg_gen_movi_i64(t1, 8);
2928 while (r1 != r3) {
77f8d6c3 2929 r1 = (r1 + 1) & 15;
aa752a4a
AJ
2930 tcg_gen_add_i64(o->in2, o->in2, t1);
2931 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
77f8d6c3 2932 }
aa752a4a 2933 tcg_temp_free(t1);
77f8d6c3 2934
77f8d6c3
RH
2935 return NO_EXIT;
2936}
2937
1807aaa5
EB
2938static ExitStatus op_lpd(DisasContext *s, DisasOps *o)
2939{
2940 TCGv_i64 a1, a2;
2941 TCGMemOp mop = s->insn->data;
2942
2943 /* In a parallel context, stop the world and single step. */
6476615d 2944 if (tb_cflags(s->tb) & CF_PARALLEL) {
1807aaa5
EB
2945 potential_page_fault(s);
2946 gen_exception(EXCP_ATOMIC);
2947 return EXIT_NORETURN;
2948 }
2949
2950 /* In a serial context, perform the two loads ... */
2951 a1 = get_address(s, 0, get_field(s->fields, b1), get_field(s->fields, d1));
2952 a2 = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
2953 tcg_gen_qemu_ld_i64(o->out, a1, get_mem_index(s), mop | MO_ALIGN);
2954 tcg_gen_qemu_ld_i64(o->out2, a2, get_mem_index(s), mop | MO_ALIGN);
2955 tcg_temp_free_i64(a1);
2956 tcg_temp_free_i64(a2);
2957
2958 /* ... and indicate that we performed them while interlocked. */
2959 gen_op_movi_cc(s, 0);
2960 return NO_EXIT;
2961}
2962
e22dfdb2
AJ
2963static ExitStatus op_lpq(DisasContext *s, DisasOps *o)
2964{
6476615d
EC
2965 if (tb_cflags(s->tb) & CF_PARALLEL) {
2966 gen_helper_lpq_parallel(o->out, cpu_env, o->in2);
2967 } else {
2968 gen_helper_lpq(o->out, cpu_env, o->in2);
2969 }
e22dfdb2
AJ
2970 return_low128(o->out2);
2971 return NO_EXIT;
2972}
2973
9c3fd85b
RH
2974#ifndef CONFIG_USER_ONLY
2975static ExitStatus op_lura(DisasContext *s, DisasOps *o)
2976{
2977 check_privileged(s);
9c3fd85b
RH
2978 gen_helper_lura(o->out, cpu_env, o->in2);
2979 return NO_EXIT;
2980}
2981
2982static ExitStatus op_lurag(DisasContext *s, DisasOps *o)
2983{
2984 check_privileged(s);
9c3fd85b
RH
2985 gen_helper_lurag(o->out, cpu_env, o->in2);
2986 return NO_EXIT;
2987}
2988#endif
2989
c2a5c1d7
RH
2990static ExitStatus op_lzrb(DisasContext *s, DisasOps *o)
2991{
2992 tcg_gen_andi_i64(o->out, o->in2, -256);
2993 return NO_EXIT;
2994}
2995
22c37a08
RH
2996static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
2997{
2998 o->out = o->in2;
2999 o->g_out = o->g_in2;
3000 TCGV_UNUSED_I64(o->in2);
3001 o->g_in2 = false;
3002 return NO_EXIT;
3003}
3004
a1c7610a
AJ
3005static ExitStatus op_mov2e(DisasContext *s, DisasOps *o)
3006{
3007 int b2 = get_field(s->fields, b2);
3008 TCGv ar1 = tcg_temp_new_i64();
3009
3010 o->out = o->in2;
3011 o->g_out = o->g_in2;
3012 TCGV_UNUSED_I64(o->in2);
3013 o->g_in2 = false;
3014
3015 switch (s->tb->flags & FLAG_MASK_ASC) {
159fed45 3016 case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT:
a1c7610a
AJ
3017 tcg_gen_movi_i64(ar1, 0);
3018 break;
159fed45 3019 case PSW_ASC_ACCREG >> FLAG_MASK_PSW_SHIFT:
a1c7610a
AJ
3020 tcg_gen_movi_i64(ar1, 1);
3021 break;
159fed45 3022 case PSW_ASC_SECONDARY >> FLAG_MASK_PSW_SHIFT:
a1c7610a
AJ
3023 if (b2) {
3024 tcg_gen_ld32u_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[b2]));
3025 } else {
3026 tcg_gen_movi_i64(ar1, 0);
3027 }
3028 break;
159fed45 3029 case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT:
a1c7610a
AJ
3030 tcg_gen_movi_i64(ar1, 2);
3031 break;
3032 }
3033
3034 tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1]));
3035 tcg_temp_free_i64(ar1);
3036
3037 return NO_EXIT;
3038}
3039
d764a8d1
RH
3040static ExitStatus op_movx(DisasContext *s, DisasOps *o)
3041{
3042 o->out = o->in1;
3043 o->out2 = o->in2;
3044 o->g_out = o->g_in1;
3045 o->g_out2 = o->g_in2;
3046 TCGV_UNUSED_I64(o->in1);
3047 TCGV_UNUSED_I64(o->in2);
3048 o->g_in1 = o->g_in2 = false;
3049 return NO_EXIT;
3050}
3051
af9e5a04
RH
3052static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
3053{
3054 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
af9e5a04
RH
3055 gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
3056 tcg_temp_free_i32(l);
3057 return NO_EXIT;
3058}
3059
6c9deca8
AJ
3060static ExitStatus op_mvcin(DisasContext *s, DisasOps *o)
3061{
3062 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3063 gen_helper_mvcin(cpu_env, l, o->addr1, o->in2);
3064 tcg_temp_free_i32(l);
3065 return NO_EXIT;
3066}
3067
e1eaada9
RH
3068static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
3069{
d3327121
AJ
3070 int r1 = get_field(s->fields, r1);
3071 int r2 = get_field(s->fields, r2);
3072 TCGv_i32 t1, t2;
3073
3074 /* r1 and r2 must be even. */
3075 if (r1 & 1 || r2 & 1) {
3076 gen_program_exception(s, PGM_SPECIFICATION);
3077 return EXIT_NORETURN;
3078 }
3079
3080 t1 = tcg_const_i32(r1);
3081 t2 = tcg_const_i32(r2);
3082 gen_helper_mvcl(cc_op, cpu_env, t1, t2);
3083 tcg_temp_free_i32(t1);
3084 tcg_temp_free_i32(t2);
e1eaada9
RH
3085 set_cc_static(s);
3086 return NO_EXIT;
3087}
3088
eb66e6a9
RH
3089static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
3090{
d3327121
AJ
3091 int r1 = get_field(s->fields, r1);
3092 int r3 = get_field(s->fields, r3);
3093 TCGv_i32 t1, t3;
3094
3095 /* r1 and r3 must be even. */
3096 if (r1 & 1 || r3 & 1) {
3097 gen_program_exception(s, PGM_SPECIFICATION);
3098 return EXIT_NORETURN;
3099 }
3100
3101 t1 = tcg_const_i32(r1);
3102 t3 = tcg_const_i32(r3);
3103 gen_helper_mvcle(cc_op, cpu_env, t1, o->in2, t3);
3104 tcg_temp_free_i32(t1);
3105 tcg_temp_free_i32(t3);
eb66e6a9
RH
3106 set_cc_static(s);
3107 return NO_EXIT;
3108}
3109
16f2e4b8
AJ
3110static ExitStatus op_mvclu(DisasContext *s, DisasOps *o)
3111{
3112 int r1 = get_field(s->fields, r1);
3113 int r3 = get_field(s->fields, r3);
3114 TCGv_i32 t1, t3;
3115
3116 /* r1 and r3 must be even. */
3117 if (r1 & 1 || r3 & 1) {
3118 gen_program_exception(s, PGM_SPECIFICATION);
3119 return EXIT_NORETURN;
3120 }
3121
3122 t1 = tcg_const_i32(r1);
3123 t3 = tcg_const_i32(r3);
3124 gen_helper_mvclu(cc_op, cpu_env, t1, o->in2, t3);
3125 tcg_temp_free_i32(t1);
3126 tcg_temp_free_i32(t3);
3127 set_cc_static(s);
3128 return NO_EXIT;
3129}
3130
3e7e5e0b
DH
3131static ExitStatus op_mvcos(DisasContext *s, DisasOps *o)
3132{
3133 int r3 = get_field(s->fields, r3);
3134 gen_helper_mvcos(cc_op, cpu_env, o->addr1, o->in2, regs[r3]);
3135 set_cc_static(s);
3136 return NO_EXIT;
3137}
3138
97c3ab61
RH
3139#ifndef CONFIG_USER_ONLY
3140static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
3141{
3142 int r1 = get_field(s->fields, l1);
3143 check_privileged(s);
97c3ab61
RH
3144 gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
3145 set_cc_static(s);
3146 return NO_EXIT;
3147}
3148
3149static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
3150{
3151 int r1 = get_field(s->fields, l1);
3152 check_privileged(s);
97c3ab61
RH
3153 gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
3154 set_cc_static(s);
3155 return NO_EXIT;
3156}
3157#endif
3158
256dab6f
AJ
3159static ExitStatus op_mvn(DisasContext *s, DisasOps *o)
3160{
3161 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3162 gen_helper_mvn(cpu_env, l, o->addr1, o->in2);
3163 tcg_temp_free_i32(l);
3164 return NO_EXIT;
3165}
3166
fdc0a747
AJ
3167static ExitStatus op_mvo(DisasContext *s, DisasOps *o)
3168{
3169 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3170 gen_helper_mvo(cpu_env, l, o->addr1, o->in2);
3171 tcg_temp_free_i32(l);
3172 return NO_EXIT;
3173}
3174
ee6c38d5
RH
3175static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
3176{
7cf96fca 3177 gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2);
ee6c38d5
RH
3178 set_cc_static(s);
3179 return NO_EXIT;
3180}
3181
aa31bf60
RH
3182static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
3183{
aa31bf60
RH
3184 gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
3185 set_cc_static(s);
3186 return_low128(o->in2);
3187 return NO_EXIT;
3188}
3189
01f8db88
AJ
3190static ExitStatus op_mvz(DisasContext *s, DisasOps *o)
3191{
3192 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3193 gen_helper_mvz(cpu_env, l, o->addr1, o->in2);
3194 tcg_temp_free_i32(l);
3195 return NO_EXIT;
3196}
3197
d1c04a2b
RH
3198static ExitStatus op_mul(DisasContext *s, DisasOps *o)
3199{
3200 tcg_gen_mul_i64(o->out, o->in1, o->in2);
3201 return NO_EXIT;
3202}
3203
1ac5889f
RH
3204static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
3205{
dc46d1c6 3206 tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2);
1ac5889f
RH
3207 return NO_EXIT;
3208}
3209
83b00736
RH
3210static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
3211{
3212 gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
3213 return NO_EXIT;
3214}
3215
3216static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
3217{
3218 gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
3219 return NO_EXIT;
3220}
3221
3222static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
3223{
3224 gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
3225 return NO_EXIT;
3226}
3227
3228static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
3229{
3230 gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
3231 return_low128(o->out2);
3232 return NO_EXIT;
3233}
3234
3235static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
3236{
3237 gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
3238 return_low128(o->out2);
3239 return NO_EXIT;
3240}
3241
722bfec3
RH
3242static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
3243{
3244 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
3245 gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
3246 tcg_temp_free_i64(r3);
3247 return NO_EXIT;
3248}
3249
3250static ExitStatus op_madb(DisasContext *s, DisasOps *o)
3251{
3252 int r3 = get_field(s->fields, r3);
3253 gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
3254 return NO_EXIT;
3255}
3256
3257static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
3258{
3259 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
3260 gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
3261 tcg_temp_free_i64(r3);
3262 return NO_EXIT;
3263}
3264
3265static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
3266{
3267 int r3 = get_field(s->fields, r3);
3268 gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
3269 return NO_EXIT;
3270}
3271
b9bca3e5
RH
3272static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
3273{
d3010781
AJ
3274 TCGv_i64 z, n;
3275 z = tcg_const_i64(0);
3276 n = tcg_temp_new_i64();
3277 tcg_gen_neg_i64(n, o->in2);
3278 tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2);
3279 tcg_temp_free_i64(n);
3280 tcg_temp_free_i64(z);
b9bca3e5
RH
3281 return NO_EXIT;
3282}
3283
5d7fd045
RH
3284static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
3285{
3286 tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
3287 return NO_EXIT;
3288}
3289
3290static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
3291{
3292 tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
3293 return NO_EXIT;
3294}
3295
3296static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
3297{
3298 tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
3299 tcg_gen_mov_i64(o->out2, o->in2);
3300 return NO_EXIT;
3301}
3302
0a949039
RH
3303static ExitStatus op_nc(DisasContext *s, DisasOps *o)
3304{
3305 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
0a949039
RH
3306 gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
3307 tcg_temp_free_i32(l);
3308 set_cc_static(s);
3309 return NO_EXIT;
3310}
3311
b9bca3e5
RH
3312static ExitStatus op_neg(DisasContext *s, DisasOps *o)
3313{
3314 tcg_gen_neg_i64(o->out, o->in2);
3315 return NO_EXIT;
3316}
3317
5d7fd045
RH
3318static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
3319{
3320 tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
3321 return NO_EXIT;
3322}
3323
3324static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
3325{
3326 tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
3327 return NO_EXIT;
3328}
3329
3330static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
3331{
3332 tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
3333 tcg_gen_mov_i64(o->out2, o->in2);
3334 return NO_EXIT;
3335}
3336
0a949039
RH
3337static ExitStatus op_oc(DisasContext *s, DisasOps *o)
3338{
3339 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
0a949039
RH
3340 gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
3341 tcg_temp_free_i32(l);
3342 set_cc_static(s);
3343 return NO_EXIT;
3344}
3345
3bbfbd1f
RH
3346static ExitStatus op_or(DisasContext *s, DisasOps *o)
3347{
3348 tcg_gen_or_i64(o->out, o->in1, o->in2);
3349 return NO_EXIT;
3350}
3351
facfc864
RH
3352static ExitStatus op_ori(DisasContext *s, DisasOps *o)
3353{
3354 int shift = s->insn->data & 0xff;
3355 int size = s->insn->data >> 8;
3356 uint64_t mask = ((1ull << size) - 1) << shift;
3357
3358 assert(!o->g_in2);
3359 tcg_gen_shli_i64(o->in2, o->in2, shift);
3360 tcg_gen_or_i64(o->out, o->in1, o->in2);
3361
3362 /* Produce the CC from only the bits manipulated. */
3363 tcg_gen_andi_i64(cc_dst, o->out, mask);
3364 set_cc_nz_u64(s, cc_dst);
3365 return NO_EXIT;
3366}
3367
76c57490
AJ
3368static ExitStatus op_pack(DisasContext *s, DisasOps *o)
3369{
3370 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3371 gen_helper_pack(cpu_env, l, o->addr1, o->in2);
3372 tcg_temp_free_i32(l);
3373 return NO_EXIT;
3374}
3375
3bd3d6d3
AJ
3376static ExitStatus op_pka(DisasContext *s, DisasOps *o)
3377{
3378 int l2 = get_field(s->fields, l2) + 1;
3379 TCGv_i32 l;
3380
3381 /* The length must not exceed 32 bytes. */
3382 if (l2 > 32) {
3383 gen_program_exception(s, PGM_SPECIFICATION);
3384 return EXIT_NORETURN;
3385 }
3386 l = tcg_const_i32(l2);
3387 gen_helper_pka(cpu_env, o->addr1, o->in2, l);
3388 tcg_temp_free_i32(l);
3389 return NO_EXIT;
3390}
3391
4e256bef
AJ
3392static ExitStatus op_pku(DisasContext *s, DisasOps *o)
3393{
3394 int l2 = get_field(s->fields, l2) + 1;
3395 TCGv_i32 l;
3396
3397 /* The length must be even and should not exceed 64 bytes. */
3398 if ((l2 & 1) || (l2 > 64)) {
3399 gen_program_exception(s, PGM_SPECIFICATION);
3400 return EXIT_NORETURN;
3401 }
3402 l = tcg_const_i32(l2);
3403 gen_helper_pku(cpu_env, o->addr1, o->in2, l);
3404 tcg_temp_free_i32(l);
3405 return NO_EXIT;
3406}
3407
99b4f24b
RH
3408static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
3409{
3410 gen_helper_popcnt(o->out, o->in2);
3411 return NO_EXIT;
3412}
3413
0568d8aa
RH
3414#ifndef CONFIG_USER_ONLY
3415static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
3416{
3417 check_privileged(s);
3418 gen_helper_ptlb(cpu_env);
3419 return NO_EXIT;
3420}
3421#endif
3422
2d6a8698
RH
3423static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
3424{
3425 int i3 = get_field(s->fields, i3);
3426 int i4 = get_field(s->fields, i4);
3427 int i5 = get_field(s->fields, i5);
3428 int do_zero = i4 & 0x80;
3429 uint64_t mask, imask, pmask;
3430 int pos, len, rot;
3431
3432 /* Adjust the arguments for the specific insn. */
3433 switch (s->fields->op2) {
3434 case 0x55: /* risbg */
3435 i3 &= 63;
3436 i4 &= 63;
3437 pmask = ~0;
3438 break;
3439 case 0x5d: /* risbhg */
3440 i3 &= 31;
3441 i4 &= 31;
3442 pmask = 0xffffffff00000000ull;
3443 break;
3444 case 0x51: /* risblg */
3445 i3 &= 31;
3446 i4 &= 31;
3447 pmask = 0x00000000ffffffffull;
3448 break;
3449 default:
3450 abort();
3451 }
3452
3453 /* MASK is the set of bits to be inserted from R2.
3454 Take care for I3/I4 wraparound. */
3455 mask = pmask >> i3;
3456 if (i3 <= i4) {
3457 mask ^= pmask >> i4 >> 1;
3458 } else {
3459 mask |= ~(pmask >> i4 >> 1);
3460 }
3461 mask &= pmask;
3462
3463 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
3464 insns, we need to keep the other half of the register. */
3465 imask = ~mask | ~pmask;
3466 if (do_zero) {
3467 if (s->fields->op2 == 0x55) {
3468 imask = 0;
3469 } else {
3470 imask = ~pmask;
3471 }
3472 }
3473
f6156b8f
RH
3474 len = i4 - i3 + 1;
3475 pos = 63 - i4;
3476 rot = i5 & 63;
3477 if (s->fields->op2 == 0x5d) {
3478 pos += 32;
3479 }
3480
3481 /* In some cases we can implement this with extract. */
dbdaaff4
RH
3482 if (imask == 0 && pos == 0 && len > 0 && len <= rot) {
3483 tcg_gen_extract_i64(o->out, o->in2, 64 - rot, len);
f6156b8f
RH
3484 return NO_EXIT;
3485 }
3486
3487 /* In some cases we can implement this with deposit. */
3488 if (len > 0 && (imask == 0 || ~mask == imask)) {
2d6a8698
RH
3489 /* Note that we rotate the bits to be inserted to the lsb, not to
3490 the position as described in the PoO. */
f6156b8f 3491 rot = (rot - pos) & 63;
2d6a8698 3492 } else {
f6156b8f 3493 pos = -1;
2d6a8698
RH
3494 }
3495
3496 /* Rotate the input as necessary. */
3497 tcg_gen_rotli_i64(o->in2, o->in2, rot);
3498
3499 /* Insert the selected bits into the output. */
3500 if (pos >= 0) {
f6156b8f
RH
3501 if (imask == 0) {
3502 tcg_gen_deposit_z_i64(o->out, o->in2, pos, len);
3503 } else {
3504 tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
3505 }
2d6a8698
RH
3506 } else if (imask == 0) {
3507 tcg_gen_andi_i64(o->out, o->in2, mask);
3508 } else {
3509 tcg_gen_andi_i64(o->in2, o->in2, mask);
3510 tcg_gen_andi_i64(o->out, o->out, imask);
3511 tcg_gen_or_i64(o->out, o->out, o->in2);
3512 }
3513 return NO_EXIT;
d6c6372e
RH
3514}
3515
3516static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
3517{
3518 int i3 = get_field(s->fields, i3);
3519 int i4 = get_field(s->fields, i4);
3520 int i5 = get_field(s->fields, i5);
3521 uint64_t mask;
3522
3523 /* If this is a test-only form, arrange to discard the result. */
3524 if (i3 & 0x80) {
3525 o->out = tcg_temp_new_i64();
3526 o->g_out = false;
3527 }
3528
3529 i3 &= 63;
3530 i4 &= 63;
3531 i5 &= 63;
3532
3533 /* MASK is the set of bits to be operated on from R2.
3534 Take care for I3/I4 wraparound. */
3535 mask = ~0ull >> i3;
3536 if (i3 <= i4) {
3537 mask ^= ~0ull >> i4 >> 1;
3538 } else {
3539 mask |= ~(~0ull >> i4 >> 1);
3540 }
3541
3542 /* Rotate the input as necessary. */
3543 tcg_gen_rotli_i64(o->in2, o->in2, i5);
3544
3545 /* Operate. */
3546 switch (s->fields->op2) {
3547 case 0x55: /* AND */
3548 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
3549 tcg_gen_and_i64(o->out, o->out, o->in2);
3550 break;
3551 case 0x56: /* OR */
3552 tcg_gen_andi_i64(o->in2, o->in2, mask);
3553 tcg_gen_or_i64(o->out, o->out, o->in2);
3554 break;
3555 case 0x57: /* XOR */
3556 tcg_gen_andi_i64(o->in2, o->in2, mask);
3557 tcg_gen_xor_i64(o->out, o->out, o->in2);
3558 break;
3559 default:
3560 abort();
3561 }
3562
3563 /* Set the CC. */
3564 tcg_gen_andi_i64(cc_dst, o->out, mask);
3565 set_cc_nz_u64(s, cc_dst);
3566 return NO_EXIT;
2d6a8698
RH
3567}
3568
d54f5865
RH
3569static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
3570{
3571 tcg_gen_bswap16_i64(o->out, o->in2);
3572 return NO_EXIT;
3573}
3574
3575static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
3576{
3577 tcg_gen_bswap32_i64(o->out, o->in2);
3578 return NO_EXIT;
3579}
3580
3581static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
3582{
3583 tcg_gen_bswap64_i64(o->out, o->in2);
3584 return NO_EXIT;
3585}
3586
cbe24bfa
RH
3587static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
3588{
3589 TCGv_i32 t1 = tcg_temp_new_i32();
3590 TCGv_i32 t2 = tcg_temp_new_i32();
3591 TCGv_i32 to = tcg_temp_new_i32();
ecc7b3aa
RH
3592 tcg_gen_extrl_i64_i32(t1, o->in1);
3593 tcg_gen_extrl_i64_i32(t2, o->in2);
cbe24bfa
RH
3594 tcg_gen_rotl_i32(to, t1, t2);
3595 tcg_gen_extu_i32_i64(o->out, to);
3596 tcg_temp_free_i32(t1);
3597 tcg_temp_free_i32(t2);
3598 tcg_temp_free_i32(to);
3599 return NO_EXIT;
3600}
3601
3602static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
3603{
3604 tcg_gen_rotl_i64(o->out, o->in1, o->in2);
3605 return NO_EXIT;
3606}
3607
5cc69c54
RH
3608#ifndef CONFIG_USER_ONLY
3609static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
3610{
3611 check_privileged(s);
3612 gen_helper_rrbe(cc_op, cpu_env, o->in2);
3613 set_cc_static(s);
3614 return NO_EXIT;
3615}
14244b21
RH
3616
3617static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
3618{
3619 check_privileged(s);
3620 gen_helper_sacf(cpu_env, o->in2);
3621 /* Addressing mode has changed, so end the block. */
3622 return EXIT_PC_STALE;
3623}
8612c935 3624#endif
44dd33ba
AG
3625
3626static ExitStatus op_sam(DisasContext *s, DisasOps *o)
3627{
3628 int sam = s->insn->data;
8612c935
RH
3629 TCGv_i64 tsam;
3630 uint64_t mask;
44dd33ba 3631
8612c935
RH
3632 switch (sam) {
3633 case 0:
3634 mask = 0xffffff;
3635 break;
3636 case 1:
3637 mask = 0x7fffffff;
3638 break;
3639 default:
3640 mask = -1;
3641 break;
3642 }
3643
631b22ea 3644 /* Bizarre but true, we check the address of the current insn for the
8612c935
RH
3645 specification exception, not the next to be executed. Thus the PoO
3646 documents that Bad Things Happen two bytes before the end. */
3647 if (s->pc & ~mask) {
3648 gen_program_exception(s, PGM_SPECIFICATION);
3649 return EXIT_NORETURN;
3650 }
3651 s->next_pc &= mask;
44dd33ba 3652
8612c935
RH
3653 tsam = tcg_const_i64(sam);
3654 tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2);
44dd33ba 3655 tcg_temp_free_i64(tsam);
8612c935
RH
3656
3657 /* Always exit the TB, since we (may have) changed execution mode. */
44dd33ba
AG
3658 return EXIT_PC_STALE;
3659}
5cc69c54 3660
d62a4c97
RH
3661static ExitStatus op_sar(DisasContext *s, DisasOps *o)
3662{
3663 int r1 = get_field(s->fields, r1);
3664 tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
3665 return NO_EXIT;
3666}
3667
1a800a2d
RH
3668static ExitStatus op_seb(DisasContext *s, DisasOps *o)
3669{
3670 gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
3671 return NO_EXIT;
3672}
3673
3674static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
3675{
3676 gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
3677 return NO_EXIT;
3678}
3679
3680static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
3681{
3682 gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
3683 return_low128(o->out2);
3684 return NO_EXIT;
3685}
3686
16d7b2a4
RH
3687static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
3688{
3689 gen_helper_sqeb(o->out, cpu_env, o->in2);
3690 return NO_EXIT;
3691}
3692
3693static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
3694{
3695 gen_helper_sqdb(o->out, cpu_env, o->in2);
3696 return NO_EXIT;
3697}
3698
3699static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
3700{
3701 gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
3702 return_low128(o->out2);
3703 return NO_EXIT;
3704}
3705
0c240015 3706#ifndef CONFIG_USER_ONLY
dc458df9
RH
3707static ExitStatus op_servc(DisasContext *s, DisasOps *o)
3708{
3709 check_privileged(s);
3710 potential_page_fault(s);
3711 gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
3712 set_cc_static(s);
3713 return NO_EXIT;
3714}
3715
0c240015
RH
3716static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
3717{
3718 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
11b0079c 3719 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
0c240015 3720 check_privileged(s);
11b0079c 3721 gen_helper_sigp(cc_op, cpu_env, o->in2, r1, r3);
1e8e69f0 3722 set_cc_static(s);
0c240015 3723 tcg_temp_free_i32(r1);
11b0079c 3724 tcg_temp_free_i32(r3);
0c240015
RH
3725 return NO_EXIT;
3726}
3727#endif
3728
b92fa334
RH
3729static ExitStatus op_soc(DisasContext *s, DisasOps *o)
3730{
3731 DisasCompare c;
45aa9aa3 3732 TCGv_i64 a, h;
42a268c2
RH
3733 TCGLabel *lab;
3734 int r1;
b92fa334
RH
3735
3736 disas_jcc(s, &c, get_field(s->fields, m3));
3737
c095ed73
AG
3738 /* We want to store when the condition is fulfilled, so branch
3739 out when it's not */
3740 c.cond = tcg_invert_cond(c.cond);
3741
b92fa334
RH
3742 lab = gen_new_label();
3743 if (c.is_64) {
3744 tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
3745 } else {
3746 tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
3747 }
3748 free_compare(&c);
3749
3750 r1 = get_field(s->fields, r1);
3751 a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
45aa9aa3
RH
3752 switch (s->insn->data) {
3753 case 1: /* STOCG */
b92fa334 3754 tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
45aa9aa3
RH
3755 break;
3756 case 0: /* STOC */
b92fa334 3757 tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
45aa9aa3
RH
3758 break;
3759 case 2: /* STOCFH */
3760 h = tcg_temp_new_i64();
3761 tcg_gen_shri_i64(h, regs[r1], 32);
3762 tcg_gen_qemu_st32(h, a, get_mem_index(s));
3763 tcg_temp_free_i64(h);
3764 break;
3765 default:
3766 g_assert_not_reached();
b92fa334
RH
3767 }
3768 tcg_temp_free_i64(a);
3769
3770 gen_set_label(lab);
3771 return NO_EXIT;
3772}
3773
cbe24bfa
RH
3774static ExitStatus op_sla(DisasContext *s, DisasOps *o)
3775{
3776 uint64_t sign = 1ull << s->insn->data;
3777 enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
3778 gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
3779 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3780 /* The arithmetic left shift is curious in that it does not affect
3781 the sign bit. Copy that over from the source unchanged. */
3782 tcg_gen_andi_i64(o->out, o->out, ~sign);
3783 tcg_gen_andi_i64(o->in1, o->in1, sign);
3784 tcg_gen_or_i64(o->out, o->out, o->in1);
3785 return NO_EXIT;
3786}
3787
3788static ExitStatus op_sll(DisasContext *s, DisasOps *o)
3789{
3790 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3791 return NO_EXIT;
3792}
3793
3794static ExitStatus op_sra(DisasContext *s, DisasOps *o)
3795{
3796 tcg_gen_sar_i64(o->out, o->in1, o->in2);
3797 return NO_EXIT;
3798}
3799
3800static ExitStatus op_srl(DisasContext *s, DisasOps *o)
3801{
3802 tcg_gen_shr_i64(o->out, o->in1, o->in2);
3803 return NO_EXIT;
3804}
3805
8379bfdb
RH
3806static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
3807{
3808 gen_helper_sfpc(cpu_env, o->in2);
3809 return NO_EXIT;
3810}
3811
411edc22
RH
3812static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
3813{
3814 gen_helper_sfas(cpu_env, o->in2);
3815 return NO_EXIT;
3816}
3817
a12000b9
RH
3818static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
3819{
3820 int b2 = get_field(s->fields, b2);
3821 int d2 = get_field(s->fields, d2);
3822 TCGv_i64 t1 = tcg_temp_new_i64();
3823 TCGv_i64 t2 = tcg_temp_new_i64();
3824 int mask, pos, len;
3825
3826 switch (s->fields->op2) {
3827 case 0x99: /* SRNM */
3828 pos = 0, len = 2;
3829 break;
3830 case 0xb8: /* SRNMB */
3831 pos = 0, len = 3;
3832 break;
3833 case 0xb9: /* SRNMT */
3834 pos = 4, len = 3;
5b90a866 3835 break;
a12000b9
RH
3836 default:
3837 tcg_abort();
3838 }
3839 mask = (1 << len) - 1;
3840
3841 /* Insert the value into the appropriate field of the FPC. */
3842 if (b2 == 0) {
3843 tcg_gen_movi_i64(t1, d2 & mask);
3844 } else {
3845 tcg_gen_addi_i64(t1, regs[b2], d2);
3846 tcg_gen_andi_i64(t1, t1, mask);
3847 }
3848 tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
3849 tcg_gen_deposit_i64(t2, t2, t1, pos, len);
3850 tcg_temp_free_i64(t1);
3851
3852 /* Then install the new FPC to set the rounding mode in fpu_status. */
3853 gen_helper_sfpc(cpu_env, t2);
3854 tcg_temp_free_i64(t2);
3855 return NO_EXIT;
3856}
3857
6b257354
DH
3858static ExitStatus op_spm(DisasContext *s, DisasOps *o)
3859{
3860 tcg_gen_extrl_i64_i32(cc_op, o->in1);
3861 tcg_gen_extract_i32(cc_op, cc_op, 28, 2);
3862 set_cc_static(s);
3863
3864 tcg_gen_shri_i64(o->in1, o->in1, 24);
3865 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in1, PSW_SHIFT_MASK_PM, 4);
3866 return NO_EXIT;
3867}
3868
7d30bb73 3869#ifndef CONFIG_USER_ONLY
28d55556
RH
3870static ExitStatus op_spka(DisasContext *s, DisasOps *o)
3871{
3872 check_privileged(s);
3873 tcg_gen_shri_i64(o->in2, o->in2, 4);
c8bd9537 3874 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4);
28d55556
RH
3875 return NO_EXIT;
3876}
3877
2bbde27f
RH
3878static ExitStatus op_sske(DisasContext *s, DisasOps *o)
3879{
3880 check_privileged(s);
3881 gen_helper_sske(cpu_env, o->in1, o->in2);
3882 return NO_EXIT;
3883}
3884
7d30bb73
RH
3885static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
3886{
3887 check_privileged(s);
3888 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
542f70c2
RH
3889 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
3890 return EXIT_PC_STALE_NOCHAIN;
7d30bb73 3891}
145cdb40 3892
411fea3d
RH
3893static ExitStatus op_stap(DisasContext *s, DisasOps *o)
3894{
3895 check_privileged(s);
ca5c1457 3896 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id));
411fea3d
RH
3897 return NO_EXIT;
3898}
3899
434c91a5
RH
3900static ExitStatus op_stck(DisasContext *s, DisasOps *o)
3901{
3902 gen_helper_stck(o->out, cpu_env);
3903 /* ??? We don't implement clock states. */
3904 gen_op_movi_cc(s, 0);
3905 return NO_EXIT;
39a5003c
RH
3906}
3907
3908static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
3909{
3910 TCGv_i64 c1 = tcg_temp_new_i64();
3911 TCGv_i64 c2 = tcg_temp_new_i64();
3912 gen_helper_stck(c1, cpu_env);
3913 /* Shift the 64-bit value into its place as a zero-extended
3914 104-bit value. Note that "bit positions 64-103 are always
3915 non-zero so that they compare differently to STCK"; we set
3916 the least significant bit to 1. */
3917 tcg_gen_shli_i64(c2, c1, 56);
3918 tcg_gen_shri_i64(c1, c1, 8);
3919 tcg_gen_ori_i64(c2, c2, 0x10000);
3920 tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
3921 tcg_gen_addi_i64(o->in2, o->in2, 8);
3922 tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
3923 tcg_temp_free_i64(c1);
3924 tcg_temp_free_i64(c2);
3925 /* ??? We don't implement clock states. */
3926 gen_op_movi_cc(s, 0);
3927 return NO_EXIT;
434c91a5
RH
3928}
3929
dd3eb7b5
RH
3930static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
3931{
3932 check_privileged(s);
3933 gen_helper_sckc(cpu_env, o->in2);
3934 return NO_EXIT;
3935}
3936
3937static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
3938{
3939 check_privileged(s);
3940 gen_helper_stckc(o->out, cpu_env);
3941 return NO_EXIT;
3942}
3943
3e398cf9
RH
3944static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
3945{
3946 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3947 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3948 check_privileged(s);
3e398cf9
RH
3949 gen_helper_stctg(cpu_env, r1, o->in2, r3);
3950 tcg_temp_free_i32(r1);
3951 tcg_temp_free_i32(r3);
3952 return NO_EXIT;
3953}
3954
504488b8
RH
3955static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
3956{
3957 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3958 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3959 check_privileged(s);
504488b8
RH
3960 gen_helper_stctl(cpu_env, r1, o->in2, r3);
3961 tcg_temp_free_i32(r1);
3962 tcg_temp_free_i32(r3);
3963 return NO_EXIT;
3964}
3965
71bd6669
RH
3966static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
3967{
3968 check_privileged(s);
076d4d39
DH
3969 tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid));
3970 tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN);
71bd6669
RH
3971 return NO_EXIT;
3972}
3973
c4f0a863
RH
3974static ExitStatus op_spt(DisasContext *s, DisasOps *o)
3975{
3976 check_privileged(s);
3977 gen_helper_spt(cpu_env, o->in2);
3978 return NO_EXIT;
3979}
3980
fc778b55
RH
3981static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
3982{
fc778b55 3983 check_privileged(s);
5bf83628 3984 gen_helper_stfl(cpu_env);
fc778b55
RH
3985 return NO_EXIT;
3986}
3987
c4f0a863
RH
3988static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
3989{
3990 check_privileged(s);
3991 gen_helper_stpt(o->out, cpu_env);
3992 return NO_EXIT;
3993}
3994
d14b3e09
RH
3995static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
3996{
3997 check_privileged(s);
3998 potential_page_fault(s);
3999 gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
4000 set_cc_static(s);
4001 return NO_EXIT;
4002}
4003
e805a0d3
RH
4004static ExitStatus op_spx(DisasContext *s, DisasOps *o)
4005{
4006 check_privileged(s);
4007 gen_helper_spx(cpu_env, o->in2);
4008 return NO_EXIT;
4009}
4010
ad8a4570 4011static ExitStatus op_xsch(DisasContext *s, DisasOps *o)
2c423fc0
RH
4012{
4013 check_privileged(s);
ad8a4570
AG
4014 potential_page_fault(s);
4015 gen_helper_xsch(cpu_env, regs[1]);
4016 set_cc_static(s);
4017 return NO_EXIT;
4018}
4019
4020static ExitStatus op_csch(DisasContext *s, DisasOps *o)
4021{
4022 check_privileged(s);
4023 potential_page_fault(s);
4024 gen_helper_csch(cpu_env, regs[1]);
4025 set_cc_static(s);
4026 return NO_EXIT;
4027}
4028
4029static ExitStatus op_hsch(DisasContext *s, DisasOps *o)
4030{
4031 check_privileged(s);
4032 potential_page_fault(s);
4033 gen_helper_hsch(cpu_env, regs[1]);
4034 set_cc_static(s);
4035 return NO_EXIT;
4036}
4037
4038static ExitStatus op_msch(DisasContext *s, DisasOps *o)
4039{
4040 check_privileged(s);
4041 potential_page_fault(s);
4042 gen_helper_msch(cpu_env, regs[1], o->in2);
4043 set_cc_static(s);
4044 return NO_EXIT;
4045}
4046
4047static ExitStatus op_rchp(DisasContext *s, DisasOps *o)
4048{
4049 check_privileged(s);
4050 potential_page_fault(s);
4051 gen_helper_rchp(cpu_env, regs[1]);
4052 set_cc_static(s);
4053 return NO_EXIT;
4054}
4055
4056static ExitStatus op_rsch(DisasContext *s, DisasOps *o)
4057{
4058 check_privileged(s);
4059 potential_page_fault(s);
4060 gen_helper_rsch(cpu_env, regs[1]);
4061 set_cc_static(s);
4062 return NO_EXIT;
4063}
4064
4065static ExitStatus op_ssch(DisasContext *s, DisasOps *o)
4066{
4067 check_privileged(s);
4068 potential_page_fault(s);
4069 gen_helper_ssch(cpu_env, regs[1], o->in2);
4070 set_cc_static(s);
4071 return NO_EXIT;
4072}
4073
4074static ExitStatus op_stsch(DisasContext *s, DisasOps *o)
4075{
4076 check_privileged(s);
4077 potential_page_fault(s);
4078 gen_helper_stsch(cpu_env, regs[1], o->in2);
4079 set_cc_static(s);
4080 return NO_EXIT;
4081}
4082
4083static ExitStatus op_tsch(DisasContext *s, DisasOps *o)
4084{
4085 check_privileged(s);
4086 potential_page_fault(s);
4087 gen_helper_tsch(cpu_env, regs[1], o->in2);
4088 set_cc_static(s);
4089 return NO_EXIT;
4090}
4091
4092static ExitStatus op_chsc(DisasContext *s, DisasOps *o)
4093{
4094 check_privileged(s);
4095 potential_page_fault(s);
4096 gen_helper_chsc(cpu_env, o->in2);
4097 set_cc_static(s);
2c423fc0
RH
4098 return NO_EXIT;
4099}
4100
e805a0d3
RH
4101static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
4102{
4103 check_privileged(s);
4104 tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
4105 tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
4106 return NO_EXIT;
4107}
4108
145cdb40
RH
4109static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
4110{
4111 uint64_t i2 = get_field(s->fields, i2);
4112 TCGv_i64 t;
4113
4114 check_privileged(s);
4115
4116 /* It is important to do what the instruction name says: STORE THEN.
4117 If we let the output hook perform the store then if we fault and
4118 restart, we'll have the wrong SYSTEM MASK in place. */
4119 t = tcg_temp_new_i64();
4120 tcg_gen_shri_i64(t, psw_mask, 56);
4121 tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
4122 tcg_temp_free_i64(t);
4123
4124 if (s->fields->op == 0xac) {
4125 tcg_gen_andi_i64(psw_mask, psw_mask,
4126 (i2 << 56) | 0x00ffffffffffffffull);
4127 } else {
4128 tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
4129 }
542f70c2
RH
4130
4131 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
4132 return EXIT_PC_STALE_NOCHAIN;
145cdb40 4133}
204504e2
RH
4134
4135static ExitStatus op_stura(DisasContext *s, DisasOps *o)
4136{
4137 check_privileged(s);
204504e2
RH
4138 gen_helper_stura(cpu_env, o->in2, o->in1);
4139 return NO_EXIT;
4140}
9c3fd85b
RH
4141
4142static ExitStatus op_sturg(DisasContext *s, DisasOps *o)
4143{
4144 check_privileged(s);
9c3fd85b
RH
4145 gen_helper_sturg(cpu_env, o->in2, o->in1);
4146 return NO_EXIT;
4147}
7d30bb73
RH
4148#endif
4149
5bf83628
RH
4150static ExitStatus op_stfle(DisasContext *s, DisasOps *o)
4151{
5bf83628
RH
4152 gen_helper_stfle(cc_op, cpu_env, o->in2);
4153 set_cc_static(s);
4154 return NO_EXIT;
4155}
4156
2b280b97
RH
4157static ExitStatus op_st8(DisasContext *s, DisasOps *o)
4158{
4159 tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
4160 return NO_EXIT;
4161}
4162
4163static ExitStatus op_st16(DisasContext *s, DisasOps *o)
4164{
4165 tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
4166 return NO_EXIT;
4167}
4168
4169static ExitStatus op_st32(DisasContext *s, DisasOps *o)
4170{
4171 tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
4172 return NO_EXIT;
4173}
4174
4175static ExitStatus op_st64(DisasContext *s, DisasOps *o)
4176{
4177 tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
4178 return NO_EXIT;
4179}
4180
7df3e93a
RH
4181static ExitStatus op_stam(DisasContext *s, DisasOps *o)
4182{
4183 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
4184 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
7df3e93a
RH
4185 gen_helper_stam(cpu_env, r1, o->in2, r3);
4186 tcg_temp_free_i32(r1);
4187 tcg_temp_free_i32(r3);
4188 return NO_EXIT;
4189}
4190
2ae68059
RH
4191static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
4192{
4193 int m3 = get_field(s->fields, m3);
4194 int pos, base = s->insn->data;
4195 TCGv_i64 tmp = tcg_temp_new_i64();
4196
4197 pos = base + ctz32(m3) * 8;
4198 switch (m3) {
4199 case 0xf:
4200 /* Effectively a 32-bit store. */
4201 tcg_gen_shri_i64(tmp, o->in1, pos);
4202 tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
4203 break;
4204
4205 case 0xc:
4206 case 0x6:
4207 case 0x3:
4208 /* Effectively a 16-bit store. */
4209 tcg_gen_shri_i64(tmp, o->in1, pos);
4210 tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
4211 break;
4212
4213 case 0x8:
4214 case 0x4:
4215 case 0x2:
4216 case 0x1:
4217 /* Effectively an 8-bit store. */
4218 tcg_gen_shri_i64(tmp, o->in1, pos);
4219 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
4220 break;
4221
4222 default:
4223 /* This is going to be a sequence of shifts and stores. */
4224 pos = base + 32 - 8;
4225 while (m3) {
4226 if (m3 & 0x8) {
4227 tcg_gen_shri_i64(tmp, o->in1, pos);
4228 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
4229 tcg_gen_addi_i64(o->in2, o->in2, 1);
4230 }
4231 m3 = (m3 << 1) & 0xf;
4232 pos -= 8;
4233 }
4234 break;
4235 }
4236 tcg_temp_free_i64(tmp);
4237 return NO_EXIT;
4238}
4239
77f8d6c3
RH
4240static ExitStatus op_stm(DisasContext *s, DisasOps *o)
4241{
4242 int r1 = get_field(s->fields, r1);
4243 int r3 = get_field(s->fields, r3);
4244 int size = s->insn->data;
4245 TCGv_i64 tsize = tcg_const_i64(size);
4246
4247 while (1) {
4248 if (size == 8) {
4249 tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
4250 } else {
4251 tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
4252 }
4253 if (r1 == r3) {
4254 break;
4255 }
4256 tcg_gen_add_i64(o->in2, o->in2, tsize);
4257 r1 = (r1 + 1) & 15;
4258 }
4259
4260 tcg_temp_free_i64(tsize);
4261 return NO_EXIT;
4262}
4263
4264static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
4265{
4266 int r1 = get_field(s->fields, r1);
4267 int r3 = get_field(s->fields, r3);
4268 TCGv_i64 t = tcg_temp_new_i64();
4269 TCGv_i64 t4 = tcg_const_i64(4);
4270 TCGv_i64 t32 = tcg_const_i64(32);
4271
4272 while (1) {
4273 tcg_gen_shl_i64(t, regs[r1], t32);
4274 tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
4275 if (r1 == r3) {
4276 break;
4277 }
4278 tcg_gen_add_i64(o->in2, o->in2, t4);
4279 r1 = (r1 + 1) & 15;
4280 }
4281
4282 tcg_temp_free_i64(t);
4283 tcg_temp_free_i64(t4);
4284 tcg_temp_free_i64(t32);
4285 return NO_EXIT;
4286}
4287
c21b610f
AJ
4288static ExitStatus op_stpq(DisasContext *s, DisasOps *o)
4289{
6476615d
EC
4290 if (tb_cflags(s->tb) & CF_PARALLEL) {
4291 gen_helper_stpq_parallel(cpu_env, o->in2, o->out2, o->out);
4292 } else {
4293 gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
4294 }
c21b610f
AJ
4295 return NO_EXIT;
4296}
4297
4600c994
RH
4298static ExitStatus op_srst(DisasContext *s, DisasOps *o)
4299{
7591db78
RH
4300 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
4301 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
4302
4303 gen_helper_srst(cpu_env, r1, r2);
4304
4305 tcg_temp_free_i32(r1);
4306 tcg_temp_free_i32(r2);
4600c994 4307 set_cc_static(s);
4600c994
RH
4308 return NO_EXIT;
4309}
4310
be7acb58
RH
4311static ExitStatus op_srstu(DisasContext *s, DisasOps *o)
4312{
4313 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
4314 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
4315
4316 gen_helper_srstu(cpu_env, r1, r2);
4317
4318 tcg_temp_free_i32(r1);
4319 tcg_temp_free_i32(r2);
4320 set_cc_static(s);
4321 return NO_EXIT;
4322}
4323
ad044d09
RH
4324static ExitStatus op_sub(DisasContext *s, DisasOps *o)
4325{
4326 tcg_gen_sub_i64(o->out, o->in1, o->in2);
4327 return NO_EXIT;
4328}
4329
4e4bb438
RH
4330static ExitStatus op_subb(DisasContext *s, DisasOps *o)
4331{
c95ec459
RH
4332 DisasCompare cmp;
4333 TCGv_i64 borrow;
4e4bb438 4334
c95ec459 4335 tcg_gen_sub_i64(o->out, o->in1, o->in2);
4e4bb438 4336
c95ec459
RH
4337 /* The !borrow flag is the msb of CC. Since we want the inverse of
4338 that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
4339 disas_jcc(s, &cmp, 8 | 4);
4340 borrow = tcg_temp_new_i64();
4341 if (cmp.is_64) {
4342 tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
4343 } else {
4344 TCGv_i32 t = tcg_temp_new_i32();
4345 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
4346 tcg_gen_extu_i32_i64(borrow, t);
4347 tcg_temp_free_i32(t);
4348 }
4349 free_compare(&cmp);
4350
4351 tcg_gen_sub_i64(o->out, o->out, borrow);
4352 tcg_temp_free_i64(borrow);
4e4bb438
RH
4353 return NO_EXIT;
4354}
4355
b9836c1a
RH
4356static ExitStatus op_svc(DisasContext *s, DisasOps *o)
4357{
4358 TCGv_i32 t;
4359
4360 update_psw_addr(s);
7a6c7067 4361 update_cc_op(s);
b9836c1a
RH
4362
4363 t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
4364 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
4365 tcg_temp_free_i32(t);
4366
99e57856 4367 t = tcg_const_i32(s->ilen);
b9836c1a
RH
4368 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
4369 tcg_temp_free_i32(t);
4370
4371 gen_exception(EXCP_SVC);
4372 return EXIT_NORETURN;
4373}
4374
0c0974d7
AJ
4375static ExitStatus op_tam(DisasContext *s, DisasOps *o)
4376{
4377 int cc = 0;
4378
4379 cc |= (s->tb->flags & FLAG_MASK_64) ? 2 : 0;
4380 cc |= (s->tb->flags & FLAG_MASK_32) ? 1 : 0;
4381 gen_op_movi_cc(s, cc);
4382 return NO_EXIT;
4383}
4384
31aa97d1
RH
4385static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
4386{
af39bc8c 4387 gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2);
31aa97d1
RH
4388 set_cc_static(s);
4389 return NO_EXIT;
4390}
4391
4392static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
4393{
af39bc8c 4394 gen_helper_tcdb(cc_op, cpu_env, o->in1, o->in2);
31aa97d1
RH
4395 set_cc_static(s);
4396 return NO_EXIT;
4397}
4398
4399static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
4400{
af39bc8c 4401 gen_helper_tcxb(cc_op, cpu_env, o->out, o->out2, o->in2);
31aa97d1
RH
4402 set_cc_static(s);
4403 return NO_EXIT;
4404}
4405
112bf079 4406#ifndef CONFIG_USER_ONLY
f79f1ca4
TH
4407
4408static ExitStatus op_testblock(DisasContext *s, DisasOps *o)
4409{
4410 check_privileged(s);
f79f1ca4
TH
4411 gen_helper_testblock(cc_op, cpu_env, o->in2);
4412 set_cc_static(s);
4413 return NO_EXIT;
4414}
4415
112bf079
RH
4416static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
4417{
112bf079
RH
4418 gen_helper_tprot(cc_op, o->addr1, o->in2);
4419 set_cc_static(s);
4420 return NO_EXIT;
4421}
f79f1ca4 4422
112bf079
RH
4423#endif
4424
5d4a655a
AJ
4425static ExitStatus op_tp(DisasContext *s, DisasOps *o)
4426{
4427 TCGv_i32 l1 = tcg_const_i32(get_field(s->fields, l1) + 1);
4428 gen_helper_tp(cc_op, cpu_env, o->addr1, l1);
4429 tcg_temp_free_i32(l1);
4430 set_cc_static(s);
4431 return NO_EXIT;
4432}
4433
0a949039
RH
4434static ExitStatus op_tr(DisasContext *s, DisasOps *o)
4435{
4436 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
0a949039
RH
4437 gen_helper_tr(cpu_env, l, o->addr1, o->in2);
4438 tcg_temp_free_i32(l);
4439 set_cc_static(s);
4440 return NO_EXIT;
4441}
4442
3f4de675
AJ
4443static ExitStatus op_tre(DisasContext *s, DisasOps *o)
4444{
3f4de675
AJ
4445 gen_helper_tre(o->out, cpu_env, o->out, o->out2, o->in2);
4446 return_low128(o->out2);
4447 set_cc_static(s);
4448 return NO_EXIT;
4449}
4450
54f00775
AJ
4451static ExitStatus op_trt(DisasContext *s, DisasOps *o)
4452{
4453 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
54f00775
AJ
4454 gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2);
4455 tcg_temp_free_i32(l);
4456 set_cc_static(s);
4457 return NO_EXIT;
4458}
4459
b213c9f5
RH
4460static ExitStatus op_trtr(DisasContext *s, DisasOps *o)
4461{
4462 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
4463 gen_helper_trtr(cc_op, cpu_env, l, o->addr1, o->in2);
4464 tcg_temp_free_i32(l);
4465 set_cc_static(s);
4466 return NO_EXIT;
4467}
4468
4065ae76
AJ
4469static ExitStatus op_trXX(DisasContext *s, DisasOps *o)
4470{
4471 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
4472 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
4473 TCGv_i32 sizes = tcg_const_i32(s->insn->opc & 3);
4474 TCGv_i32 tst = tcg_temp_new_i32();
4475 int m3 = get_field(s->fields, m3);
4476
3c39c800
RH
4477 if (!s390_has_feat(S390_FEAT_ETF2_ENH)) {
4478 m3 = 0;
4479 }
4065ae76
AJ
4480 if (m3 & 1) {
4481 tcg_gen_movi_i32(tst, -1);
4482 } else {
4483 tcg_gen_extrl_i64_i32(tst, regs[0]);
4484 if (s->insn->opc & 3) {
4485 tcg_gen_ext8u_i32(tst, tst);
4486 } else {
4487 tcg_gen_ext16u_i32(tst, tst);
4488 }
4489 }
4490 gen_helper_trXX(cc_op, cpu_env, r1, r2, tst, sizes);
4491
4492 tcg_temp_free_i32(r1);
4493 tcg_temp_free_i32(r2);
4494 tcg_temp_free_i32(sizes);
4495 tcg_temp_free_i32(tst);
4496 set_cc_static(s);
4497 return NO_EXIT;
4498}
4499
6699adfc
AJ
4500static ExitStatus op_ts(DisasContext *s, DisasOps *o)
4501{
4502 TCGv_i32 t1 = tcg_const_i32(0xff);
4503 tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB);
4504 tcg_gen_extract_i32(cc_op, t1, 7, 1);
4505 tcg_temp_free_i32(t1);
4506 set_cc_static(s);
4507 return NO_EXIT;
4508}
4509
0a949039
RH
4510static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
4511{
4512 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
0a949039
RH
4513 gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
4514 tcg_temp_free_i32(l);
4515 return NO_EXIT;
4516}
4517
1a35f08a
AJ
4518static ExitStatus op_unpka(DisasContext *s, DisasOps *o)
4519{
4520 int l1 = get_field(s->fields, l1) + 1;
4521 TCGv_i32 l;
4522
4523 /* The length must not exceed 32 bytes. */
4524 if (l1 > 32) {
4525 gen_program_exception(s, PGM_SPECIFICATION);
4526 return EXIT_NORETURN;
4527 }
4528 l = tcg_const_i32(l1);
4529 gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2);
4530 tcg_temp_free_i32(l);
4531 set_cc_static(s);
4532 return NO_EXIT;
4533}
4534
15417787
AJ
4535static ExitStatus op_unpku(DisasContext *s, DisasOps *o)
4536{
4537 int l1 = get_field(s->fields, l1) + 1;
4538 TCGv_i32 l;
4539
4540 /* The length must be even and should not exceed 64 bytes. */
4541 if ((l1 & 1) || (l1 > 64)) {
4542 gen_program_exception(s, PGM_SPECIFICATION);
4543 return EXIT_NORETURN;
4544 }
4545 l = tcg_const_i32(l1);
4546 gen_helper_unpku(cc_op, cpu_env, o->addr1, l, o->in2);
4547 tcg_temp_free_i32(l);
4548 set_cc_static(s);
4549 return NO_EXIT;
4550}
4551
4552
0a949039
RH
4553static ExitStatus op_xc(DisasContext *s, DisasOps *o)
4554{
d074ac6d
RH
4555 int d1 = get_field(s->fields, d1);
4556 int d2 = get_field(s->fields, d2);
4557 int b1 = get_field(s->fields, b1);
4558 int b2 = get_field(s->fields, b2);
4559 int l = get_field(s->fields, l1);
4560 TCGv_i32 t32;
4561
4562 o->addr1 = get_address(s, 0, b1, d1);
4563
4564 /* If the addresses are identical, this is a store/memset of zero. */
4565 if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
4566 o->in2 = tcg_const_i64(0);
4567
4568 l++;
4569 while (l >= 8) {
4570 tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
4571 l -= 8;
4572 if (l > 0) {
4573 tcg_gen_addi_i64(o->addr1, o->addr1, 8);
4574 }
4575 }
4576 if (l >= 4) {
4577 tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
4578 l -= 4;
4579 if (l > 0) {
4580 tcg_gen_addi_i64(o->addr1, o->addr1, 4);
4581 }
4582 }
4583 if (l >= 2) {
4584 tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
4585 l -= 2;
4586 if (l > 0) {
4587 tcg_gen_addi_i64(o->addr1, o->addr1, 2);
4588 }
4589 }
4590 if (l) {
4591 tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
4592 }
4593 gen_op_movi_cc(s, 0);
4594 return NO_EXIT;
4595 }
4596
4597 /* But in general we'll defer to a helper. */
4598 o->in2 = get_address(s, 0, b2, d2);
4599 t32 = tcg_const_i32(l);
d074ac6d
RH
4600 gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
4601 tcg_temp_free_i32(t32);
0a949039
RH
4602 set_cc_static(s);
4603 return NO_EXIT;
4604}
4605
3bbfbd1f
RH
4606static ExitStatus op_xor(DisasContext *s, DisasOps *o)
4607{
4608 tcg_gen_xor_i64(o->out, o->in1, o->in2);
4609 return NO_EXIT;
4610}
4611
facfc864
RH
4612static ExitStatus op_xori(DisasContext *s, DisasOps *o)
4613{
4614 int shift = s->insn->data & 0xff;
4615 int size = s->insn->data >> 8;
4616 uint64_t mask = ((1ull << size) - 1) << shift;
4617
4618 assert(!o->g_in2);
4619 tcg_gen_shli_i64(o->in2, o->in2, shift);
4620 tcg_gen_xor_i64(o->out, o->in1, o->in2);
4621
4622 /* Produce the CC from only the bits manipulated. */
4623 tcg_gen_andi_i64(cc_dst, o->out, mask);
4624 set_cc_nz_u64(s, cc_dst);
4625 return NO_EXIT;
4626}
4627
24db8412
RH
4628static ExitStatus op_zero(DisasContext *s, DisasOps *o)
4629{
4630 o->out = tcg_const_i64(0);
4631 return NO_EXIT;
4632}
4633
4634static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
4635{
4636 o->out = tcg_const_i64(0);
4637 o->out2 = o->out;
4638 o->g_out2 = true;
4639 return NO_EXIT;
4640}
4641
ad044d09
RH
4642/* ====================================================================== */
4643/* The "Cc OUTput" generators. Given the generated output (and in some cases
4644 the original inputs), update the various cc data structures in order to
4645 be able to compute the new condition code. */
4646
b9bca3e5
RH
4647static void cout_abs32(DisasContext *s, DisasOps *o)
4648{
4649 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
4650}
4651
4652static void cout_abs64(DisasContext *s, DisasOps *o)
4653{
4654 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
4655}
4656
ad044d09
RH
4657static void cout_adds32(DisasContext *s, DisasOps *o)
4658{
4659 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
4660}
4661
4662static void cout_adds64(DisasContext *s, DisasOps *o)
4663{
4664 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
4665}
4666
4667static void cout_addu32(DisasContext *s, DisasOps *o)
4668{
4669 gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
4670}
4671
4672static void cout_addu64(DisasContext *s, DisasOps *o)
4673{
4674 gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
4675}
4676
4e4bb438
RH
4677static void cout_addc32(DisasContext *s, DisasOps *o)
4678{
4679 gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
4680}
4681
4682static void cout_addc64(DisasContext *s, DisasOps *o)
4683{
4684 gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
4685}
4686
a7e836d5
RH
4687static void cout_cmps32(DisasContext *s, DisasOps *o)
4688{
4689 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
4690}
4691
4692static void cout_cmps64(DisasContext *s, DisasOps *o)
4693{
4694 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
4695}
4696
4697static void cout_cmpu32(DisasContext *s, DisasOps *o)
4698{
4699 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
4700}
4701
4702static void cout_cmpu64(DisasContext *s, DisasOps *o)
4703{
4704 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
4705}
4706
587626f8
RH
4707static void cout_f32(DisasContext *s, DisasOps *o)
4708{
4709 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
4710}
4711
4712static void cout_f64(DisasContext *s, DisasOps *o)
4713{
4714 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
4715}
4716
4717static void cout_f128(DisasContext *s, DisasOps *o)
4718{
4719 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
4720}
4721
b9bca3e5
RH
4722static void cout_nabs32(DisasContext *s, DisasOps *o)
4723{
4724 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
4725}
4726
4727static void cout_nabs64(DisasContext *s, DisasOps *o)
4728{
4729 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
4730}
4731
4732static void cout_neg32(DisasContext *s, DisasOps *o)
4733{
4734 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
4735}
4736
4737static void cout_neg64(DisasContext *s, DisasOps *o)
4738{
4739 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
4740}
4741
3bbfbd1f
RH
4742static void cout_nz32(DisasContext *s, DisasOps *o)
4743{
4744 tcg_gen_ext32u_i64(cc_dst, o->out);
4745 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
4746}
4747
4748static void cout_nz64(DisasContext *s, DisasOps *o)
4749{
4750 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
4751}
4752
11bf2d73
RH
4753static void cout_s32(DisasContext *s, DisasOps *o)
4754{
4755 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
4756}
4757
4758static void cout_s64(DisasContext *s, DisasOps *o)
4759{
4760 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
4761}
4762
ad044d09
RH
4763static void cout_subs32(DisasContext *s, DisasOps *o)
4764{
4765 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
4766}
4767
4768static void cout_subs64(DisasContext *s, DisasOps *o)
4769{
4770 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
4771}
4772
4773static void cout_subu32(DisasContext *s, DisasOps *o)
4774{
4775 gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
4776}
4777
4778static void cout_subu64(DisasContext *s, DisasOps *o)
4779{
4780 gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
4781}
4782
4e4bb438
RH
4783static void cout_subb32(DisasContext *s, DisasOps *o)
4784{
4785 gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
4786}
4787
4788static void cout_subb64(DisasContext *s, DisasOps *o)
4789{
4790 gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
4791}
4792
00d2dc19
RH
4793static void cout_tm32(DisasContext *s, DisasOps *o)
4794{
4795 gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
4796}
4797
4798static void cout_tm64(DisasContext *s, DisasOps *o)
4799{
4800 gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
4801}
4802
ad044d09 4803/* ====================================================================== */
805a2505 4804/* The "PREParation" generators. These initialize the DisasOps.OUT fields
ad044d09
RH
4805 with the TCG register to which we will write. Used in combination with
4806 the "wout" generators, in some cases we need a new temporary, and in
4807 some cases we can write to a TCG global. */
4808
4809static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
4810{
4811 o->out = tcg_temp_new_i64();
4812}
49f7ee80 4813#define SPEC_prep_new 0
ad044d09 4814
891452e5
RH
4815static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
4816{
4817 o->out = tcg_temp_new_i64();
4818 o->out2 = tcg_temp_new_i64();
4819}
49f7ee80 4820#define SPEC_prep_new_P 0
891452e5 4821
ad044d09
RH
4822static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4823{
4824 o->out = regs[get_field(f, r1)];
4825 o->g_out = true;
4826}
49f7ee80 4827#define SPEC_prep_r1 0
ad044d09 4828
1ac5889f
RH
4829static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
4830{
1ac5889f
RH
4831 int r1 = get_field(f, r1);
4832 o->out = regs[r1];
49f7ee80 4833 o->out2 = regs[r1 + 1];
1ac5889f
RH
4834 o->g_out = o->g_out2 = true;
4835}
49f7ee80 4836#define SPEC_prep_r1_P SPEC_r1_even
1ac5889f 4837
587626f8
RH
4838static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
4839{
4840 o->out = fregs[get_field(f, r1)];
4841 o->g_out = true;
4842}
49f7ee80 4843#define SPEC_prep_f1 0
587626f8
RH
4844
4845static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
4846{
587626f8
RH
4847 int r1 = get_field(f, r1);
4848 o->out = fregs[r1];
49f7ee80 4849 o->out2 = fregs[r1 + 2];
587626f8
RH
4850 o->g_out = o->g_out2 = true;
4851}
49f7ee80 4852#define SPEC_prep_x1 SPEC_r1_f128
587626f8 4853
ad044d09
RH
4854/* ====================================================================== */
4855/* The "Write OUTput" generators. These generally perform some non-trivial
4856 copy of data to TCG globals, or to main memory. The trivial cases are
4857 generally handled by having a "prep" generator install the TCG global
4858 as the destination of the operation. */
4859
22c37a08
RH
4860static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
4861{
4862 store_reg(get_field(f, r1), o->out);
4863}
49f7ee80 4864#define SPEC_wout_r1 0
22c37a08 4865
afdc70be
RH
4866static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
4867{
4868 int r1 = get_field(f, r1);
4869 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
4870}
49f7ee80 4871#define SPEC_wout_r1_8 0
afdc70be 4872
d54f5865
RH
4873static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
4874{
4875 int r1 = get_field(f, r1);
4876 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
4877}
49f7ee80 4878#define SPEC_wout_r1_16 0
d54f5865 4879
ad044d09
RH
4880static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4881{
4882 store_reg32_i64(get_field(f, r1), o->out);
4883}
49f7ee80 4884#define SPEC_wout_r1_32 0
ad044d09 4885
a1f12d85
AJ
4886static void wout_r1_32h(DisasContext *s, DisasFields *f, DisasOps *o)
4887{
4888 store_reg32h_i64(get_field(f, r1), o->out);
4889}
4890#define SPEC_wout_r1_32h 0
4891
891452e5
RH
4892static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
4893{
891452e5
RH
4894 int r1 = get_field(f, r1);
4895 store_reg32_i64(r1, o->out);
49f7ee80 4896 store_reg32_i64(r1 + 1, o->out2);
891452e5 4897}
49f7ee80 4898#define SPEC_wout_r1_P32 SPEC_r1_even
891452e5 4899
d87aaf93
RH
4900static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4901{
d87aaf93 4902 int r1 = get_field(f, r1);
49f7ee80 4903 store_reg32_i64(r1 + 1, o->out);
d87aaf93
RH
4904 tcg_gen_shri_i64(o->out, o->out, 32);
4905 store_reg32_i64(r1, o->out);
4906}
49f7ee80 4907#define SPEC_wout_r1_D32 SPEC_r1_even
22c37a08 4908
1807aaa5
EB
4909static void wout_r3_P32(DisasContext *s, DisasFields *f, DisasOps *o)
4910{
4911 int r3 = get_field(f, r3);
4912 store_reg32_i64(r3, o->out);
4913 store_reg32_i64(r3 + 1, o->out2);
4914}
4915#define SPEC_wout_r3_P32 SPEC_r3_even
4916
4917static void wout_r3_P64(DisasContext *s, DisasFields *f, DisasOps *o)
4918{
4919 int r3 = get_field(f, r3);
4920 store_reg(r3, o->out);
4921 store_reg(r3 + 1, o->out2);
4922}
4923#define SPEC_wout_r3_P64 SPEC_r3_even
4924
d764a8d1
RH
4925static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
4926{
4927 store_freg32_i64(get_field(f, r1), o->out);
4928}
49f7ee80 4929#define SPEC_wout_e1 0
d764a8d1
RH
4930
4931static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
4932{
4933 store_freg(get_field(f, r1), o->out);
4934}
49f7ee80 4935#define SPEC_wout_f1 0
d764a8d1
RH
4936
4937static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
4938{
4939 int f1 = get_field(s->fields, r1);
4940 store_freg(f1, o->out);
49f7ee80 4941 store_freg(f1 + 2, o->out2);
d764a8d1 4942}
49f7ee80 4943#define SPEC_wout_x1 SPEC_r1_f128
d764a8d1 4944
22c37a08
RH
4945static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4946{
4947 if (get_field(f, r1) != get_field(f, r2)) {
4948 store_reg32_i64(get_field(f, r1), o->out);
4949 }
4950}
49f7ee80 4951#define SPEC_wout_cond_r1r2_32 0
d87aaf93 4952
d764a8d1
RH
4953static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
4954{
4955 if (get_field(f, r1) != get_field(f, r2)) {
4956 store_freg32_i64(get_field(f, r1), o->out);
4957 }
4958}
49f7ee80 4959#define SPEC_wout_cond_e1e2 0
d764a8d1 4960
6a04d76a
RH
4961static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
4962{
4963 tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
4964}
49f7ee80 4965#define SPEC_wout_m1_8 0
6a04d76a
RH
4966
4967static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
4968{
4969 tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
4970}
49f7ee80 4971#define SPEC_wout_m1_16 0
6a04d76a 4972
ad044d09
RH
4973static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
4974{
4975 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
4976}
49f7ee80 4977#define SPEC_wout_m1_32 0
ad044d09
RH
4978
4979static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4980{
4981 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
4982}
49f7ee80 4983#define SPEC_wout_m1_64 0
ad044d09 4984
ea20490f
RH
4985static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
4986{
4987 tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
4988}
49f7ee80 4989#define SPEC_wout_m2_32 0
ea20490f 4990
4dba4d6f 4991static void wout_in2_r1(DisasContext *s, DisasFields *f, DisasOps *o)
57af7289 4992{
4dba4d6f 4993 store_reg(get_field(f, r1), o->in2);
57af7289 4994}
4dba4d6f 4995#define SPEC_wout_in2_r1 0
57af7289 4996
4dba4d6f 4997static void wout_in2_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
57af7289 4998{
4dba4d6f 4999 store_reg32_i64(get_field(f, r1), o->in2);
57af7289 5000}
4dba4d6f 5001#define SPEC_wout_in2_r1_32 0
57af7289 5002
ad044d09
RH
5003/* ====================================================================== */
5004/* The "INput 1" generators. These load the first operand to an insn. */
5005
5006static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
5007{
5008 o->in1 = load_reg(get_field(f, r1));
5009}
49f7ee80 5010#define SPEC_in1_r1 0
ad044d09 5011
d1c04a2b
RH
5012static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
5013{
5014 o->in1 = regs[get_field(f, r1)];
5015 o->g_in1 = true;
5016}
49f7ee80 5017#define SPEC_in1_r1_o 0
d1c04a2b 5018
cbe24bfa
RH
5019static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5020{
5021 o->in1 = tcg_temp_new_i64();
5022 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
5023}
49f7ee80 5024#define SPEC_in1_r1_32s 0
cbe24bfa
RH
5025
5026static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5027{
5028 o->in1 = tcg_temp_new_i64();
5029 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
5030}
49f7ee80 5031#define SPEC_in1_r1_32u 0
cbe24bfa 5032
32a44d58
RH
5033static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
5034{
5035 o->in1 = tcg_temp_new_i64();
5036 tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
5037}
49f7ee80 5038#define SPEC_in1_r1_sr32 0
32a44d58 5039
1ac5889f
RH
5040static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
5041{
49f7ee80 5042 o->in1 = load_reg(get_field(f, r1) + 1);
1ac5889f 5043}
49f7ee80 5044#define SPEC_in1_r1p1 SPEC_r1_even
1ac5889f 5045
d87aaf93
RH
5046static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5047{
d87aaf93 5048 o->in1 = tcg_temp_new_i64();
49f7ee80 5049 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 5050}
49f7ee80 5051#define SPEC_in1_r1p1_32s SPEC_r1_even
d87aaf93
RH
5052
5053static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5054{
d87aaf93 5055 o->in1 = tcg_temp_new_i64();
49f7ee80 5056 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
d87aaf93 5057}
49f7ee80 5058#define SPEC_in1_r1p1_32u SPEC_r1_even
d87aaf93 5059
891452e5
RH
5060static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
5061{
891452e5
RH
5062 int r1 = get_field(f, r1);
5063 o->in1 = tcg_temp_new_i64();
5064 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
5065}
49f7ee80 5066#define SPEC_in1_r1_D32 SPEC_r1_even
891452e5 5067
ad044d09
RH
5068static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
5069{
5070 o->in1 = load_reg(get_field(f, r2));
5071}
49f7ee80 5072#define SPEC_in1_r2 0
ad044d09 5073
a1f12d85
AJ
5074static void in1_r2_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
5075{
5076 o->in1 = tcg_temp_new_i64();
5077 tcg_gen_shri_i64(o->in1, regs[get_field(f, r2)], 32);
5078}
5079#define SPEC_in1_r2_sr32 0
5080
ad044d09
RH
5081static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
5082{
5083 o->in1 = load_reg(get_field(f, r3));
5084}
49f7ee80 5085#define SPEC_in1_r3 0
ad044d09 5086
cbe24bfa
RH
5087static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
5088{
5089 o->in1 = regs[get_field(f, r3)];
5090 o->g_in1 = true;
5091}
49f7ee80 5092#define SPEC_in1_r3_o 0
cbe24bfa
RH
5093
5094static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5095{
5096 o->in1 = tcg_temp_new_i64();
5097 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
5098}
49f7ee80 5099#define SPEC_in1_r3_32s 0
cbe24bfa
RH
5100
5101static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5102{
5103 o->in1 = tcg_temp_new_i64();
5104 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
5105}
49f7ee80 5106#define SPEC_in1_r3_32u 0
cbe24bfa 5107
b7886de3
RH
5108static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
5109{
5110 int r3 = get_field(f, r3);
5111 o->in1 = tcg_temp_new_i64();
5112 tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
5113}
5114#define SPEC_in1_r3_D32 SPEC_r3_even
5115
00574261
RH
5116static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
5117{
5118 o->in1 = load_freg32_i64(get_field(f, r1));
5119}
49f7ee80 5120#define SPEC_in1_e1 0
00574261
RH
5121
5122static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
5123{
5124 o->in1 = fregs[get_field(f, r1)];
5125 o->g_in1 = true;
5126}
49f7ee80 5127#define SPEC_in1_f1_o 0
00574261 5128
587626f8
RH
5129static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
5130{
587626f8
RH
5131 int r1 = get_field(f, r1);
5132 o->out = fregs[r1];
49f7ee80 5133 o->out2 = fregs[r1 + 2];
587626f8
RH
5134 o->g_out = o->g_out2 = true;
5135}
49f7ee80 5136#define SPEC_in1_x1_o SPEC_r1_f128
587626f8 5137
2db014b5
RH
5138static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
5139{
5140 o->in1 = fregs[get_field(f, r3)];
5141 o->g_in1 = true;
5142}
49f7ee80 5143#define SPEC_in1_f3_o 0
2db014b5 5144
ad044d09
RH
5145static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
5146{
5147 o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
5148}
49f7ee80 5149#define SPEC_in1_la1 0
ad044d09 5150
e025e52a
RH
5151static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
5152{
5153 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
5154 o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
5155}
49f7ee80 5156#define SPEC_in1_la2 0
e025e52a 5157
a7e836d5
RH
5158static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
5159{
5160 in1_la1(s, f, o);
5161 o->in1 = tcg_temp_new_i64();
5162 tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
5163}
49f7ee80 5164#define SPEC_in1_m1_8u 0
a7e836d5
RH
5165
5166static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
5167{
5168 in1_la1(s, f, o);
5169 o->in1 = tcg_temp_new_i64();
5170 tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
5171}
49f7ee80 5172#define SPEC_in1_m1_16s 0
a7e836d5
RH
5173
5174static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5175{
5176 in1_la1(s, f, o);
5177 o->in1 = tcg_temp_new_i64();
5178 tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
5179}
49f7ee80 5180#define SPEC_in1_m1_16u 0
a7e836d5 5181
ad044d09
RH
5182static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5183{
5184 in1_la1(s, f, o);
5185 o->in1 = tcg_temp_new_i64();
5186 tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
5187}
49f7ee80 5188#define SPEC_in1_m1_32s 0
ad044d09 5189
e272b3ac
RH
5190static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5191{
5192 in1_la1(s, f, o);
5193 o->in1 = tcg_temp_new_i64();
5194 tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
5195}
49f7ee80 5196#define SPEC_in1_m1_32u 0
e272b3ac 5197
ad044d09
RH
5198static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
5199{
5200 in1_la1(s, f, o);
5201 o->in1 = tcg_temp_new_i64();
5202 tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
5203}
49f7ee80 5204#define SPEC_in1_m1_64 0
ad044d09
RH
5205
5206/* ====================================================================== */
5207/* The "INput 2" generators. These load the second operand to an insn. */
5208
e025e52a
RH
5209static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
5210{
5211 o->in2 = regs[get_field(f, r1)];
5212 o->g_in2 = true;
5213}
49f7ee80 5214#define SPEC_in2_r1_o 0
e025e52a
RH
5215
5216static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5217{
5218 o->in2 = tcg_temp_new_i64();
5219 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
5220}
49f7ee80 5221#define SPEC_in2_r1_16u 0
e025e52a
RH
5222
5223static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5224{
5225 o->in2 = tcg_temp_new_i64();
5226 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
5227}
49f7ee80 5228#define SPEC_in2_r1_32u 0
e025e52a 5229
b7886de3
RH
5230static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
5231{
5232 int r1 = get_field(f, r1);
5233 o->in2 = tcg_temp_new_i64();
5234 tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
5235}
5236#define SPEC_in2_r1_D32 SPEC_r1_even
5237
ad044d09
RH
5238static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
5239{
5240 o->in2 = load_reg(get_field(f, r2));
5241}
49f7ee80 5242#define SPEC_in2_r2 0
ad044d09 5243
d1c04a2b
RH
5244static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
5245{
5246 o->in2 = regs[get_field(f, r2)];
5247 o->g_in2 = true;
5248}
49f7ee80 5249#define SPEC_in2_r2_o 0
d1c04a2b 5250
8ac33cdb
RH
5251static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
5252{
5253 int r2 = get_field(f, r2);
5254 if (r2 != 0) {
5255 o->in2 = load_reg(r2);
5256 }
5257}
49f7ee80 5258#define SPEC_in2_r2_nz 0
8ac33cdb 5259
c698d876
RH
5260static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
5261{
5262 o->in2 = tcg_temp_new_i64();
5263 tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
5264}
49f7ee80 5265#define SPEC_in2_r2_8s 0
c698d876
RH
5266
5267static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
5268{
5269 o->in2 = tcg_temp_new_i64();
5270 tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
5271}
49f7ee80 5272#define SPEC_in2_r2_8u 0
c698d876
RH
5273
5274static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
5275{
5276 o->in2 = tcg_temp_new_i64();
5277 tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
5278}
49f7ee80 5279#define SPEC_in2_r2_16s 0
c698d876
RH
5280
5281static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5282{
5283 o->in2 = tcg_temp_new_i64();
5284 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
5285}
49f7ee80 5286#define SPEC_in2_r2_16u 0
c698d876 5287
ad044d09
RH
5288static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
5289{
5290 o->in2 = load_reg(get_field(f, r3));
5291}
49f7ee80 5292#define SPEC_in2_r3 0
ad044d09 5293
a1f12d85
AJ
5294static void in2_r3_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
5295{
5296 o->in2 = tcg_temp_new_i64();
5297 tcg_gen_shri_i64(o->in2, regs[get_field(f, r3)], 32);
5298}
5299#define SPEC_in2_r3_sr32 0
5300
ad044d09
RH
5301static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5302{
5303 o->in2 = tcg_temp_new_i64();
5304 tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
5305}
49f7ee80 5306#define SPEC_in2_r2_32s 0
ad044d09
RH
5307
5308static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5309{
5310 o->in2 = tcg_temp_new_i64();
5311 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
5312}
49f7ee80 5313#define SPEC_in2_r2_32u 0
ad044d09 5314
a1f12d85
AJ
5315static void in2_r2_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
5316{
5317 o->in2 = tcg_temp_new_i64();
5318 tcg_gen_shri_i64(o->in2, regs[get_field(f, r2)], 32);
5319}
5320#define SPEC_in2_r2_sr32 0
5321
d764a8d1
RH
5322static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
5323{
5324 o->in2 = load_freg32_i64(get_field(f, r2));
5325}
49f7ee80 5326#define SPEC_in2_e2 0
d764a8d1
RH
5327
5328static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
5329{
5330 o->in2 = fregs[get_field(f, r2)];
5331 o->g_in2 = true;
5332}
49f7ee80 5333#define SPEC_in2_f2_o 0
d764a8d1
RH
5334
5335static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
5336{
587626f8
RH
5337 int r2 = get_field(f, r2);
5338 o->in1 = fregs[r2];
49f7ee80 5339 o->in2 = fregs[r2 + 2];
d764a8d1
RH
5340 o->g_in1 = o->g_in2 = true;
5341}
49f7ee80 5342#define SPEC_in2_x2_o SPEC_r2_f128
d764a8d1 5343
374724f9
RH
5344static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
5345{
5346 o->in2 = get_address(s, 0, get_field(f, r2), 0);
5347}
49f7ee80 5348#define SPEC_in2_ra2 0
374724f9 5349
ad044d09
RH
5350static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
5351{
5352 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
5353 o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
5354}
49f7ee80 5355#define SPEC_in2_a2 0
ad044d09 5356
a7e836d5
RH
5357static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
5358{
5359 o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
5360}
49f7ee80 5361#define SPEC_in2_ri2 0
a7e836d5 5362
cbe24bfa
RH
5363static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
5364{
5365 help_l2_shift(s, f, o, 31);
5366}
49f7ee80 5367#define SPEC_in2_sh32 0
cbe24bfa
RH
5368
5369static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
5370{
5371 help_l2_shift(s, f, o, 63);
5372}
49f7ee80 5373#define SPEC_in2_sh64 0
cbe24bfa 5374
afdc70be
RH
5375static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
5376{
5377 in2_a2(s, f, o);
5378 tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
5379}
49f7ee80 5380#define SPEC_in2_m2_8u 0
afdc70be 5381
d82287de
RH
5382static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
5383{
5384 in2_a2(s, f, o);
5385 tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
5386}
49f7ee80 5387#define SPEC_in2_m2_16s 0
d82287de 5388
d54f5865
RH
5389static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5390{
5391 in2_a2(s, f, o);
5392 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
5393}
49f7ee80 5394#define SPEC_in2_m2_16u 0
d54f5865 5395
ad044d09
RH
5396static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5397{
5398 in2_a2(s, f, o);
5399 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
5400}
49f7ee80 5401#define SPEC_in2_m2_32s 0
ad044d09
RH
5402
5403static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5404{
5405 in2_a2(s, f, o);
5406 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
5407}
49f7ee80 5408#define SPEC_in2_m2_32u 0
ad044d09
RH
5409
5410static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
5411{
5412 in2_a2(s, f, o);
5413 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
5414}
49f7ee80 5415#define SPEC_in2_m2_64 0
ad044d09 5416
a7e836d5
RH
5417static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5418{
5419 in2_ri2(s, f, o);
5420 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
5421}
49f7ee80 5422#define SPEC_in2_mri2_16u 0
a7e836d5
RH
5423
5424static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
5425{
5426 in2_ri2(s, f, o);
5427 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
5428}
49f7ee80 5429#define SPEC_in2_mri2_32s 0
a7e836d5
RH
5430
5431static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5432{
5433 in2_ri2(s, f, o);
5434 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
5435}
49f7ee80 5436#define SPEC_in2_mri2_32u 0
a7e836d5
RH
5437
5438static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
5439{
5440 in2_ri2(s, f, o);
5441 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
5442}
49f7ee80 5443#define SPEC_in2_mri2_64 0
a7e836d5 5444
ad044d09
RH
5445static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
5446{
5447 o->in2 = tcg_const_i64(get_field(f, i2));
5448}
49f7ee80 5449#define SPEC_in2_i2 0
ad044d09 5450
a7e836d5
RH
5451static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
5452{
5453 o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
5454}
49f7ee80 5455#define SPEC_in2_i2_8u 0
a7e836d5
RH
5456
5457static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
5458{
5459 o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
5460}
49f7ee80 5461#define SPEC_in2_i2_16u 0
a7e836d5 5462
ad044d09
RH
5463static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
5464{
5465 o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
5466}
49f7ee80 5467#define SPEC_in2_i2_32u 0
ad044d09 5468
ade9dea4
RH
5469static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
5470{
5471 uint64_t i2 = (uint16_t)get_field(f, i2);
5472 o->in2 = tcg_const_i64(i2 << s->insn->data);
5473}
49f7ee80 5474#define SPEC_in2_i2_16u_shl 0
ade9dea4
RH
5475
5476static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
5477{
5478 uint64_t i2 = (uint32_t)get_field(f, i2);
5479 o->in2 = tcg_const_i64(i2 << s->insn->data);
5480}
49f7ee80 5481#define SPEC_in2_i2_32u_shl 0
ade9dea4 5482
ad8a4570
AG
5483#ifndef CONFIG_USER_ONLY
5484static void in2_insn(DisasContext *s, DisasFields *f, DisasOps *o)
5485{
5486 o->in2 = tcg_const_i64(s->fields->raw_insn);
5487}
5488#define SPEC_in2_insn 0
5489#endif
5490
ad044d09
RH
5491/* ====================================================================== */
5492
5493/* Find opc within the table of insns. This is formulated as a switch
5494 statement so that (1) we get compile-time notice of cut-paste errors
5495 for duplicated opcodes, and (2) the compiler generates the binary
5496 search tree, rather than us having to post-process the table. */
5497
5498#define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
5499 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
5500
5501#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
5502
5503enum DisasInsnEnum {
5504#include "insn-data.def"
5505};
5506
5507#undef D
49f7ee80
RH
5508#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
5509 .opc = OPC, \
5510 .fmt = FMT_##FT, \
5511 .fac = FAC_##FC, \
5512 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
5513 .name = #NM, \
5514 .help_in1 = in1_##I1, \
5515 .help_in2 = in2_##I2, \
5516 .help_prep = prep_##P, \
5517 .help_wout = wout_##W, \
5518 .help_cout = cout_##CC, \
5519 .help_op = op_##OP, \
5520 .data = D \
ad044d09
RH
5521 },
5522
5523/* Allow 0 to be used for NULL in the table below. */
5524#define in1_0 NULL
5525#define in2_0 NULL
5526#define prep_0 NULL
5527#define wout_0 NULL
5528#define cout_0 NULL
5529#define op_0 NULL
5530
49f7ee80
RH
5531#define SPEC_in1_0 0
5532#define SPEC_in2_0 0
5533#define SPEC_prep_0 0
5534#define SPEC_wout_0 0
5535
d20bd43c
RH
5536/* Give smaller names to the various facilities. */
5537#define FAC_Z S390_FEAT_ZARCH
5538#define FAC_CASS S390_FEAT_COMPARE_AND_SWAP_AND_STORE
d20bd43c
RH
5539#define FAC_DFP S390_FEAT_DFP
5540#define FAC_DFPR S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* DFP-rounding */
5541#define FAC_DO S390_FEAT_STFLE_45 /* distinct-operands */
5542#define FAC_EE S390_FEAT_EXECUTE_EXT
5543#define FAC_EI S390_FEAT_EXTENDED_IMMEDIATE
5544#define FAC_FPE S390_FEAT_FLOATING_POINT_EXT
5545#define FAC_FPSSH S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* FPS-sign-handling */
5546#define FAC_FPRGR S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* FPR-GR-transfer */
5547#define FAC_GIE S390_FEAT_GENERAL_INSTRUCTIONS_EXT
5548#define FAC_HFP_MA S390_FEAT_HFP_MADDSUB
5549#define FAC_HW S390_FEAT_STFLE_45 /* high-word */
5550#define FAC_IEEEE_SIM S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* IEEE-exception-simulation */
5551#define FAC_MIE S390_FEAT_STFLE_49 /* misc-instruction-extensions */
5552#define FAC_LAT S390_FEAT_STFLE_49 /* load-and-trap */
5553#define FAC_LOC S390_FEAT_STFLE_45 /* load/store on condition 1 */
45aa9aa3 5554#define FAC_LOC2 S390_FEAT_STFLE_53 /* load/store on condition 2 */
d20bd43c
RH
5555#define FAC_LD S390_FEAT_LONG_DISPLACEMENT
5556#define FAC_PC S390_FEAT_STFLE_45 /* population count */
5557#define FAC_SCF S390_FEAT_STORE_CLOCK_FAST
5558#define FAC_SFLE S390_FEAT_STFLE
5559#define FAC_ILA S390_FEAT_STFLE_45 /* interlocked-access-facility 1 */
3e7e5e0b 5560#define FAC_MVCOS S390_FEAT_MOVE_WITH_OPTIONAL_SPEC
d20bd43c
RH
5561#define FAC_LPP S390_FEAT_SET_PROGRAM_PARAMETERS /* load-program-parameter */
5562#define FAC_DAT_ENH S390_FEAT_DAT_ENH
5563#define FAC_E2 S390_FEAT_EXTENDED_TRANSLATION_2
6a68acd5 5564#define FAC_EH S390_FEAT_STFLE_49 /* execution-hint */
632c61a9 5565#define FAC_PPA S390_FEAT_STFLE_49 /* processor-assist */
c2a5c1d7 5566#define FAC_LZRB S390_FEAT_STFLE_53 /* load-and-zero-rightmost-byte */
941ef3db 5567#define FAC_ETF3 S390_FEAT_EXTENDED_TRANSLATION_3
7705c750
DH
5568#define FAC_MSA S390_FEAT_MSA /* message-security-assist facility */
5569#define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */
5570#define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */
5571#define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */
d20bd43c 5572
ad044d09
RH
5573static const DisasInsn insn_info[] = {
5574#include "insn-data.def"
5575};
5576
5577#undef D
5578#define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
5579 case OPC: return &insn_info[insn_ ## NM];
5580
5581static const DisasInsn *lookup_opc(uint16_t opc)
5582{
5583 switch (opc) {
5584#include "insn-data.def"
5585 default:
5586 return NULL;
5587 }
5588}
5589
5590#undef D
5591#undef C
5592
5593/* Extract a field from the insn. The INSN should be left-aligned in
5594 the uint64_t so that we can more easily utilize the big-bit-endian
5595 definitions we extract from the Principals of Operation. */
5596
5597static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
5598{
5599 uint32_t r, m;
5600
5601 if (f->size == 0) {
5602 return;
5603 }
5604
5605 /* Zero extract the field from the insn. */
5606 r = (insn << f->beg) >> (64 - f->size);
5607
5608 /* Sign-extend, or un-swap the field as necessary. */
5609 switch (f->type) {
5610 case 0: /* unsigned */
5611 break;
5612 case 1: /* signed */
5613 assert(f->size <= 32);
5614 m = 1u << (f->size - 1);
5615 r = (r ^ m) - m;
5616 break;
5617 case 2: /* dl+dh split, signed 20 bit. */
5618 r = ((int8_t)r << 12) | (r >> 8);
5619 break;
5620 default:
5621 abort();
5622 }
5623
5624 /* Validate that the "compressed" encoding we selected above is valid.
5625 I.e. we havn't make two different original fields overlap. */
5626 assert(((o->presentC >> f->indexC) & 1) == 0);
5627 o->presentC |= 1 << f->indexC;
5628 o->presentO |= 1 << f->indexO;
5629
5630 o->c[f->indexC] = r;
5631}
5632
5633/* Lookup the insn at the current PC, extracting the operands into O and
5634 returning the info struct for the insn. Returns NULL for invalid insn. */
5635
5636static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
5637 DisasFields *f)
5638{
5639 uint64_t insn, pc = s->pc;
d5a103cd 5640 int op, op2, ilen;
ad044d09
RH
5641 const DisasInsn *info;
5642
303c681a
RH
5643 if (unlikely(s->ex_value)) {
5644 /* Drop the EX data now, so that it's clear on exception paths. */
5645 TCGv_i64 zero = tcg_const_i64(0);
5646 tcg_gen_st_i64(zero, cpu_env, offsetof(CPUS390XState, ex_value));
5647 tcg_temp_free_i64(zero);
d5a103cd 5648
303c681a
RH
5649 /* Extract the values saved by EXECUTE. */
5650 insn = s->ex_value & 0xffffffffffff0000ull;
5651 ilen = s->ex_value & 0xf;
5652 op = insn >> 56;
5653 } else {
5654 insn = ld_code2(env, pc);
5655 op = (insn >> 8) & 0xff;
5656 ilen = get_ilen(op);
5657 switch (ilen) {
5658 case 2:
5659 insn = insn << 48;
5660 break;
5661 case 4:
5662 insn = ld_code4(env, pc) << 32;
5663 break;
5664 case 6:
5665 insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
5666 break;
5667 default:
5668 g_assert_not_reached();
5669 }
ad044d09 5670 }
303c681a
RH
5671 s->next_pc = s->pc + ilen;
5672 s->ilen = ilen;
ad044d09
RH
5673
5674 /* We can't actually determine the insn format until we've looked up
5675 the full insn opcode. Which we can't do without locating the
5676 secondary opcode. Assume by default that OP2 is at bit 40; for
5677 those smaller insns that don't actually have a secondary opcode
5678 this will correctly result in OP2 = 0. */
5679 switch (op) {
5680 case 0x01: /* E */
5681 case 0x80: /* S */
5682 case 0x82: /* S */
5683 case 0x93: /* S */
6a68acd5 5684 case 0xb2: /* S, RRF, RRE, IE */
ad044d09
RH
5685 case 0xb3: /* RRE, RRD, RRF */
5686 case 0xb9: /* RRE, RRF */
5687 case 0xe5: /* SSE, SIL */
5688 op2 = (insn << 8) >> 56;
5689 break;
5690 case 0xa5: /* RI */
5691 case 0xa7: /* RI */
5692 case 0xc0: /* RIL */
5693 case 0xc2: /* RIL */
5694 case 0xc4: /* RIL */
5695 case 0xc6: /* RIL */
5696 case 0xc8: /* SSF */
5697 case 0xcc: /* RIL */
5698 op2 = (insn << 12) >> 60;
5699 break;
6a68acd5
RH
5700 case 0xc5: /* MII */
5701 case 0xc7: /* SMI */
ad044d09
RH
5702 case 0xd0 ... 0xdf: /* SS */
5703 case 0xe1: /* SS */
5704 case 0xe2: /* SS */
5705 case 0xe8: /* SS */
5706 case 0xe9: /* SS */
5707 case 0xea: /* SS */
5708 case 0xee ... 0xf3: /* SS */
5709 case 0xf8 ... 0xfd: /* SS */
5710 op2 = 0;
5711 break;
5712 default:
5713 op2 = (insn << 40) >> 56;
5714 break;
5715 }
5716
5717 memset(f, 0, sizeof(*f));
ad8a4570 5718 f->raw_insn = insn;
ad044d09
RH
5719 f->op = op;
5720 f->op2 = op2;
5721
5722 /* Lookup the instruction. */
5723 info = lookup_opc(op << 8 | op2);
5724
5725 /* If we found it, extract the operands. */
5726 if (info != NULL) {
5727 DisasFormat fmt = info->fmt;
5728 int i;
5729
5730 for (i = 0; i < NUM_C_FIELD; ++i) {
5731 extract_field(f, &format_info[fmt].op[i], insn);
5732 }
5733 }
5734 return info;
5735}
5736
5737static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
5738{
5739 const DisasInsn *insn;
5740 ExitStatus ret = NO_EXIT;
5741 DisasFields f;
5742 DisasOps o;
5743
4f3adfb2 5744 /* Search for the insn in the table. */
ad044d09 5745 insn = extract_insn(env, s, &f);
e023e832 5746
4f3adfb2 5747 /* Not found means unimplemented/illegal opcode. */
ad044d09 5748 if (insn == NULL) {
4f3adfb2
RH
5749 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
5750 f.op, f.op2);
5751 gen_illegal_opcode(s);
5752 return EXIT_NORETURN;
ad044d09
RH
5753 }
5754
f0e0d817
AJ
5755#ifndef CONFIG_USER_ONLY
5756 if (s->tb->flags & FLAG_MASK_PER) {
5757 TCGv_i64 addr = tcg_const_i64(s->pc);
5758 gen_helper_per_ifetch(cpu_env, addr);
5759 tcg_temp_free_i64(addr);
5760 }
5761#endif
5762
49f7ee80
RH
5763 /* Check for insn specification exceptions. */
5764 if (insn->spec) {
5765 int spec = insn->spec, excp = 0, r;
5766
5767 if (spec & SPEC_r1_even) {
5768 r = get_field(&f, r1);
5769 if (r & 1) {
5770 excp = PGM_SPECIFICATION;
5771 }
5772 }
5773 if (spec & SPEC_r2_even) {
5774 r = get_field(&f, r2);
5775 if (r & 1) {
b7886de3
RH
5776 excp = PGM_SPECIFICATION;
5777 }
5778 }
5779 if (spec & SPEC_r3_even) {
5780 r = get_field(&f, r3);
5781 if (r & 1) {
49f7ee80
RH
5782 excp = PGM_SPECIFICATION;
5783 }
5784 }
5785 if (spec & SPEC_r1_f128) {
5786 r = get_field(&f, r1);
5787 if (r > 13) {
5788 excp = PGM_SPECIFICATION;
5789 }
5790 }
5791 if (spec & SPEC_r2_f128) {
5792 r = get_field(&f, r2);
5793 if (r > 13) {
5794 excp = PGM_SPECIFICATION;
5795 }
5796 }
5797 if (excp) {
5798 gen_program_exception(s, excp);
5799 return EXIT_NORETURN;
5800 }
5801 }
5802
ad044d09
RH
5803 /* Set up the strutures we use to communicate with the helpers. */
5804 s->insn = insn;
5805 s->fields = &f;
5806 o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
5807 TCGV_UNUSED_I64(o.out);
5808 TCGV_UNUSED_I64(o.out2);
5809 TCGV_UNUSED_I64(o.in1);
5810 TCGV_UNUSED_I64(o.in2);
5811 TCGV_UNUSED_I64(o.addr1);
5812
5813 /* Implement the instruction. */
5814 if (insn->help_in1) {
5815 insn->help_in1(s, &f, &o);
5816 }
5817 if (insn->help_in2) {
5818 insn->help_in2(s, &f, &o);
5819 }
5820 if (insn->help_prep) {
5821 insn->help_prep(s, &f, &o);
5822 }
5823 if (insn->help_op) {
5824 ret = insn->help_op(s, &o);
5825 }
5826 if (insn->help_wout) {
5827 insn->help_wout(s, &f, &o);
5828 }
5829 if (insn->help_cout) {
5830 insn->help_cout(s, &o);
5831 }
5832
5833 /* Free any temporaries created by the helpers. */
5834 if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
5835 tcg_temp_free_i64(o.out);
5836 }
5837 if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
5838 tcg_temp_free_i64(o.out2);
5839 }
5840 if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
5841 tcg_temp_free_i64(o.in1);
5842 }
5843 if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
5844 tcg_temp_free_i64(o.in2);
5845 }
5846 if (!TCGV_IS_UNUSED_I64(o.addr1)) {
5847 tcg_temp_free_i64(o.addr1);
5848 }
5849
777c98c3
AJ
5850#ifndef CONFIG_USER_ONLY
5851 if (s->tb->flags & FLAG_MASK_PER) {
5852 /* An exception might be triggered, save PSW if not already done. */
5853 if (ret == NO_EXIT || ret == EXIT_PC_STALE) {
5854 tcg_gen_movi_i64(psw_addr, s->next_pc);
5855 }
5856
5857 /* Save off cc. */
5858 update_cc_op(s);
5859
5860 /* Call the helper to check for a possible PER exception. */
5861 gen_helper_per_check_exception(cpu_env);
5862 }
5863#endif
5864
ad044d09
RH
5865 /* Advance to the next instruction. */
5866 s->pc = s->next_pc;
5867 return ret;
e023e832
AG
5868}
5869
9c489ea6 5870void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
e023e832 5871{
9c489ea6 5872 CPUS390XState *env = cs->env_ptr;
e023e832
AG
5873 DisasContext dc;
5874 target_ulong pc_start;
5875 uint64_t next_page_start;
e023e832 5876 int num_insns, max_insns;
ad044d09 5877 ExitStatus status;
d5a103cd 5878 bool do_debug;
e023e832
AG
5879
5880 pc_start = tb->pc;
5881
5882 /* 31-bit mode */
5883 if (!(tb->flags & FLAG_MASK_64)) {
5884 pc_start &= 0x7fffffff;
5885 }
5886
e023e832 5887 dc.tb = tb;
ad044d09 5888 dc.pc = pc_start;
e023e832 5889 dc.cc_op = CC_OP_DYNAMIC;
303c681a 5890 dc.ex_value = tb->cs_base;
ed2803da 5891 do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
e023e832 5892
e023e832
AG
5893 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
5894
5895 num_insns = 0;
c5a49c63 5896 max_insns = tb_cflags(tb) & CF_COUNT_MASK;
e023e832
AG
5897 if (max_insns == 0) {
5898 max_insns = CF_COUNT_MASK;
5899 }
190ce7fb
RH
5900 if (max_insns > TCG_MAX_INSNS) {
5901 max_insns = TCG_MAX_INSNS;
5902 }
e023e832 5903
cd42d5b2 5904 gen_tb_start(tb);
e023e832
AG
5905
5906 do {
a3fd5220 5907 tcg_gen_insn_start(dc.pc, dc.cc_op);
959082fc 5908 num_insns++;
667b8e29 5909
b933066a
RH
5910 if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
5911 status = EXIT_PC_STALE;
5912 do_debug = true;
522a0d4e
RH
5913 /* The address covered by the breakpoint must be included in
5914 [tb->pc, tb->pc + tb->size) in order to for it to be
5915 properly cleared -- thus we increment the PC here so that
5916 the logic setting tb->size below does the right thing. */
5917 dc.pc += 2;
b933066a 5918 break;
e023e832 5919 }
7193b5f6 5920
c5a49c63 5921 if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
e023e832 5922 gen_io_start();
7193b5f6
RH
5923 }
5924
51a718bf 5925 status = translate_one(env, &dc);
ad044d09
RH
5926
5927 /* If we reach a page boundary, are single stepping,
5928 or exhaust instruction count, stop generation. */
5929 if (status == NO_EXIT
5930 && (dc.pc >= next_page_start
fe700adb 5931 || tcg_op_buf_full()
ad044d09
RH
5932 || num_insns >= max_insns
5933 || singlestep
303c681a
RH
5934 || cs->singlestep_enabled
5935 || dc.ex_value)) {
ad044d09 5936 status = EXIT_PC_STALE;
e023e832 5937 }
ad044d09 5938 } while (status == NO_EXIT);
e023e832 5939
c5a49c63 5940 if (tb_cflags(tb) & CF_LAST_IO) {
e023e832
AG
5941 gen_io_end();
5942 }
ad044d09
RH
5943
5944 switch (status) {
5945 case EXIT_GOTO_TB:
5946 case EXIT_NORETURN:
5947 break;
5948 case EXIT_PC_STALE:
542f70c2 5949 case EXIT_PC_STALE_NOCHAIN:
ad044d09
RH
5950 update_psw_addr(&dc);
5951 /* FALLTHRU */
5952 case EXIT_PC_UPDATED:
7a6c7067
RH
5953 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
5954 cc op type is in env */
5955 update_cc_op(&dc);
06fc0348
RH
5956 /* FALLTHRU */
5957 case EXIT_PC_CC_UPDATED:
7a6c7067 5958 /* Exit the TB, either by raising a debug exception or by return. */
d5a103cd
RH
5959 if (do_debug) {
5960 gen_exception(EXCP_DEBUG);
542f70c2 5961 } else if (use_exit_tb(&dc) || status == EXIT_PC_STALE_NOCHAIN) {
ad044d09 5962 tcg_gen_exit_tb(0);
6350001e 5963 } else {
7f11636d 5964 tcg_gen_lookup_and_goto_ptr();
ad044d09
RH
5965 }
5966 break;
5967 default:
542f70c2 5968 g_assert_not_reached();
e023e832 5969 }
ad044d09 5970
806f352d 5971 gen_tb_end(tb, num_insns);
0a7df5da 5972
4e5e1215
RH
5973 tb->size = dc.pc - pc_start;
5974 tb->icount = num_insns;
ad044d09 5975
e023e832 5976#if defined(S390X_DEBUG_DISAS)
4910e6e4
RH
5977 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
5978 && qemu_log_in_addr_range(pc_start)) {
1ee73216 5979 qemu_log_lock();
303c681a
RH
5980 if (unlikely(dc.ex_value)) {
5981 /* ??? Unfortunately log_target_disas can't use host memory. */
5982 qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value);
5983 } else {
5984 qemu_log("IN: %s\n", lookup_symbol(pc_start));
1d48474d 5985 log_target_disas(cs, pc_start, dc.pc - pc_start);
303c681a
RH
5986 qemu_log("\n");
5987 }
1ee73216 5988 qemu_log_unlock();
e023e832
AG
5989 }
5990#endif
5991}
5992
bad729e2
RH
5993void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
5994 target_ulong *data)
e023e832 5995{
bad729e2
RH
5996 int cc_op = data[1];
5997 env->psw.addr = data[0];
e023e832
AG
5998 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
5999 env->cc_op = cc_op;
6000 }
10ec5117 6001}