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