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