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