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