pseries: Add H_SET_MODE hcall to change guest exception endianness
[qemu/kevin.git] / target-s390x / translate.c
blob1fb76c5264d3dea69880c112ad195ebeebdb646b
1 /*
2 * S/390 translation
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2010 Alexander Graf
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 /* #define DEBUG_INLINE_BRANCHES */
22 #define S390X_DEBUG_DISAS
23 /* #define S390X_DEBUG_DISAS_VERBOSE */
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
31 #include "cpu.h"
32 #include "disas/disas.h"
33 #include "tcg-op.h"
34 #include "qemu/log.h"
35 #include "qemu/host-utils.h"
37 /* global register indexes */
38 static TCGv_ptr cpu_env;
40 #include "exec/gen-icount.h"
41 #include "helper.h"
42 #define GEN_HELPER 1
43 #include "helper.h"
46 /* Information that (most) every instruction needs to manipulate. */
47 typedef struct DisasContext DisasContext;
48 typedef struct DisasInsn DisasInsn;
49 typedef struct DisasFields DisasFields;
51 struct DisasContext {
52 struct TranslationBlock *tb;
53 const DisasInsn *insn;
54 DisasFields *fields;
55 uint64_t pc, next_pc;
56 enum cc_op cc_op;
57 bool singlestep_enabled;
60 /* Information carried about a condition to be evaluated. */
61 typedef struct {
62 TCGCond cond:8;
63 bool is_64;
64 bool g1;
65 bool g2;
66 union {
67 struct { TCGv_i64 a, b; } s64;
68 struct { TCGv_i32 a, b; } s32;
69 } u;
70 } DisasCompare;
72 #define DISAS_EXCP 4
74 #ifdef DEBUG_INLINE_BRANCHES
75 static uint64_t inline_branch_hit[CC_OP_MAX];
76 static uint64_t inline_branch_miss[CC_OP_MAX];
77 #endif
79 static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc)
81 if (!(s->tb->flags & FLAG_MASK_64)) {
82 if (s->tb->flags & FLAG_MASK_32) {
83 return pc | 0x80000000;
86 return pc;
89 void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
90 int flags)
92 S390CPU *cpu = S390_CPU(cs);
93 CPUS390XState *env = &cpu->env;
94 int i;
96 if (env->cc_op > 3) {
97 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %15s\n",
98 env->psw.mask, env->psw.addr, cc_name(env->cc_op));
99 } else {
100 cpu_fprintf(f, "PSW=mask %016" PRIx64 " addr %016" PRIx64 " cc %02x\n",
101 env->psw.mask, env->psw.addr, env->cc_op);
104 for (i = 0; i < 16; i++) {
105 cpu_fprintf(f, "R%02d=%016" PRIx64, i, env->regs[i]);
106 if ((i % 4) == 3) {
107 cpu_fprintf(f, "\n");
108 } else {
109 cpu_fprintf(f, " ");
113 for (i = 0; i < 16; i++) {
114 cpu_fprintf(f, "F%02d=%016" PRIx64, i, env->fregs[i].ll);
115 if ((i % 4) == 3) {
116 cpu_fprintf(f, "\n");
117 } else {
118 cpu_fprintf(f, " ");
122 #ifndef CONFIG_USER_ONLY
123 for (i = 0; i < 16; i++) {
124 cpu_fprintf(f, "C%02d=%016" PRIx64, i, env->cregs[i]);
125 if ((i % 4) == 3) {
126 cpu_fprintf(f, "\n");
127 } else {
128 cpu_fprintf(f, " ");
131 #endif
133 #ifdef DEBUG_INLINE_BRANCHES
134 for (i = 0; i < CC_OP_MAX; i++) {
135 cpu_fprintf(f, " %15s = %10ld\t%10ld\n", cc_name(i),
136 inline_branch_miss[i], inline_branch_hit[i]);
138 #endif
140 cpu_fprintf(f, "\n");
143 static TCGv_i64 psw_addr;
144 static TCGv_i64 psw_mask;
146 static TCGv_i32 cc_op;
147 static TCGv_i64 cc_src;
148 static TCGv_i64 cc_dst;
149 static TCGv_i64 cc_vr;
151 static char cpu_reg_names[32][4];
152 static TCGv_i64 regs[16];
153 static TCGv_i64 fregs[16];
155 static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
157 void s390x_translate_init(void)
159 int i;
161 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
162 psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
163 offsetof(CPUS390XState, psw.addr),
164 "psw_addr");
165 psw_mask = tcg_global_mem_new_i64(TCG_AREG0,
166 offsetof(CPUS390XState, psw.mask),
167 "psw_mask");
169 cc_op = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUS390XState, cc_op),
170 "cc_op");
171 cc_src = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_src),
172 "cc_src");
173 cc_dst = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_dst),
174 "cc_dst");
175 cc_vr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUS390XState, cc_vr),
176 "cc_vr");
178 for (i = 0; i < 16; i++) {
179 snprintf(cpu_reg_names[i], sizeof(cpu_reg_names[0]), "r%d", i);
180 regs[i] = tcg_global_mem_new(TCG_AREG0,
181 offsetof(CPUS390XState, regs[i]),
182 cpu_reg_names[i]);
185 for (i = 0; i < 16; i++) {
186 snprintf(cpu_reg_names[i + 16], sizeof(cpu_reg_names[0]), "f%d", i);
187 fregs[i] = tcg_global_mem_new(TCG_AREG0,
188 offsetof(CPUS390XState, fregs[i].d),
189 cpu_reg_names[i + 16]);
192 /* register helpers */
193 #define GEN_HELPER 2
194 #include "helper.h"
197 static TCGv_i64 load_reg(int reg)
199 TCGv_i64 r = tcg_temp_new_i64();
200 tcg_gen_mov_i64(r, regs[reg]);
201 return r;
204 static TCGv_i64 load_freg32_i64(int reg)
206 TCGv_i64 r = tcg_temp_new_i64();
207 tcg_gen_shri_i64(r, fregs[reg], 32);
208 return r;
211 static void store_reg(int reg, TCGv_i64 v)
213 tcg_gen_mov_i64(regs[reg], v);
216 static void store_freg(int reg, TCGv_i64 v)
218 tcg_gen_mov_i64(fregs[reg], v);
221 static void store_reg32_i64(int reg, TCGv_i64 v)
223 /* 32 bit register writes keep the upper half */
224 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 0, 32);
227 static void store_reg32h_i64(int reg, TCGv_i64 v)
229 tcg_gen_deposit_i64(regs[reg], regs[reg], v, 32, 32);
232 static void store_freg32_i64(int reg, TCGv_i64 v)
234 tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
237 static void return_low128(TCGv_i64 dest)
239 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
242 static void update_psw_addr(DisasContext *s)
244 /* psw.addr */
245 tcg_gen_movi_i64(psw_addr, s->pc);
248 static void update_cc_op(DisasContext *s)
250 if (s->cc_op != CC_OP_DYNAMIC && s->cc_op != CC_OP_STATIC) {
251 tcg_gen_movi_i32(cc_op, s->cc_op);
255 static void potential_page_fault(DisasContext *s)
257 update_psw_addr(s);
258 update_cc_op(s);
261 static inline uint64_t ld_code2(CPUS390XState *env, uint64_t pc)
263 return (uint64_t)cpu_lduw_code(env, pc);
266 static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
268 return (uint64_t)(uint32_t)cpu_ldl_code(env, pc);
271 static inline uint64_t ld_code6(CPUS390XState *env, uint64_t pc)
273 return (ld_code2(env, pc) << 32) | ld_code4(env, pc + 2);
276 static int get_mem_index(DisasContext *s)
278 switch (s->tb->flags & FLAG_MASK_ASC) {
279 case PSW_ASC_PRIMARY >> 32:
280 return 0;
281 case PSW_ASC_SECONDARY >> 32:
282 return 1;
283 case PSW_ASC_HOME >> 32:
284 return 2;
285 default:
286 tcg_abort();
287 break;
291 static void gen_exception(int excp)
293 TCGv_i32 tmp = tcg_const_i32(excp);
294 gen_helper_exception(cpu_env, tmp);
295 tcg_temp_free_i32(tmp);
298 static void gen_program_exception(DisasContext *s, int code)
300 TCGv_i32 tmp;
302 /* Remember what pgm exeption this was. */
303 tmp = tcg_const_i32(code);
304 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_code));
305 tcg_temp_free_i32(tmp);
307 tmp = tcg_const_i32(s->next_pc - s->pc);
308 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen));
309 tcg_temp_free_i32(tmp);
311 /* Advance past instruction. */
312 s->pc = s->next_pc;
313 update_psw_addr(s);
315 /* Save off cc. */
316 update_cc_op(s);
318 /* Trigger exception. */
319 gen_exception(EXCP_PGM);
322 static inline void gen_illegal_opcode(DisasContext *s)
324 gen_program_exception(s, PGM_SPECIFICATION);
327 static inline void check_privileged(DisasContext *s)
329 if (s->tb->flags & (PSW_MASK_PSTATE >> 32)) {
330 gen_program_exception(s, PGM_PRIVILEGED);
334 static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2)
336 TCGv_i64 tmp = tcg_temp_new_i64();
337 bool need_31 = !(s->tb->flags & FLAG_MASK_64);
339 /* Note that d2 is limited to 20 bits, signed. If we crop negative
340 displacements early we create larger immedate addends. */
342 /* Note that addi optimizes the imm==0 case. */
343 if (b2 && x2) {
344 tcg_gen_add_i64(tmp, regs[b2], regs[x2]);
345 tcg_gen_addi_i64(tmp, tmp, d2);
346 } else if (b2) {
347 tcg_gen_addi_i64(tmp, regs[b2], d2);
348 } else if (x2) {
349 tcg_gen_addi_i64(tmp, regs[x2], d2);
350 } else {
351 if (need_31) {
352 d2 &= 0x7fffffff;
353 need_31 = false;
355 tcg_gen_movi_i64(tmp, d2);
357 if (need_31) {
358 tcg_gen_andi_i64(tmp, tmp, 0x7fffffff);
361 return tmp;
364 static inline bool live_cc_data(DisasContext *s)
366 return (s->cc_op != CC_OP_DYNAMIC
367 && s->cc_op != CC_OP_STATIC
368 && s->cc_op > 3);
371 static inline void gen_op_movi_cc(DisasContext *s, uint32_t val)
373 if (live_cc_data(s)) {
374 tcg_gen_discard_i64(cc_src);
375 tcg_gen_discard_i64(cc_dst);
376 tcg_gen_discard_i64(cc_vr);
378 s->cc_op = CC_OP_CONST0 + val;
381 static void gen_op_update1_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 dst)
383 if (live_cc_data(s)) {
384 tcg_gen_discard_i64(cc_src);
385 tcg_gen_discard_i64(cc_vr);
387 tcg_gen_mov_i64(cc_dst, dst);
388 s->cc_op = op;
391 static void gen_op_update2_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
392 TCGv_i64 dst)
394 if (live_cc_data(s)) {
395 tcg_gen_discard_i64(cc_vr);
397 tcg_gen_mov_i64(cc_src, src);
398 tcg_gen_mov_i64(cc_dst, dst);
399 s->cc_op = op;
402 static void gen_op_update3_cc_i64(DisasContext *s, enum cc_op op, TCGv_i64 src,
403 TCGv_i64 dst, TCGv_i64 vr)
405 tcg_gen_mov_i64(cc_src, src);
406 tcg_gen_mov_i64(cc_dst, dst);
407 tcg_gen_mov_i64(cc_vr, vr);
408 s->cc_op = op;
411 static void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
413 gen_op_update1_cc_i64(s, CC_OP_NZ, val);
416 static void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
418 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
421 static void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
423 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
426 static void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
428 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
431 /* CC value is in env->cc_op */
432 static void set_cc_static(DisasContext *s)
434 if (live_cc_data(s)) {
435 tcg_gen_discard_i64(cc_src);
436 tcg_gen_discard_i64(cc_dst);
437 tcg_gen_discard_i64(cc_vr);
439 s->cc_op = CC_OP_STATIC;
442 /* calculates cc into cc_op */
443 static void gen_op_calc_cc(DisasContext *s)
445 TCGv_i32 local_cc_op;
446 TCGv_i64 dummy;
448 TCGV_UNUSED_I32(local_cc_op);
449 TCGV_UNUSED_I64(dummy);
450 switch (s->cc_op) {
451 default:
452 dummy = tcg_const_i64(0);
453 /* FALLTHRU */
454 case CC_OP_ADD_64:
455 case CC_OP_ADDU_64:
456 case CC_OP_ADDC_64:
457 case CC_OP_SUB_64:
458 case CC_OP_SUBU_64:
459 case CC_OP_SUBB_64:
460 case CC_OP_ADD_32:
461 case CC_OP_ADDU_32:
462 case CC_OP_ADDC_32:
463 case CC_OP_SUB_32:
464 case CC_OP_SUBU_32:
465 case CC_OP_SUBB_32:
466 local_cc_op = tcg_const_i32(s->cc_op);
467 break;
468 case CC_OP_CONST0:
469 case CC_OP_CONST1:
470 case CC_OP_CONST2:
471 case CC_OP_CONST3:
472 case CC_OP_STATIC:
473 case CC_OP_DYNAMIC:
474 break;
477 switch (s->cc_op) {
478 case CC_OP_CONST0:
479 case CC_OP_CONST1:
480 case CC_OP_CONST2:
481 case CC_OP_CONST3:
482 /* s->cc_op is the cc value */
483 tcg_gen_movi_i32(cc_op, s->cc_op - CC_OP_CONST0);
484 break;
485 case CC_OP_STATIC:
486 /* env->cc_op already is the cc value */
487 break;
488 case CC_OP_NZ:
489 case CC_OP_ABS_64:
490 case CC_OP_NABS_64:
491 case CC_OP_ABS_32:
492 case CC_OP_NABS_32:
493 case CC_OP_LTGT0_32:
494 case CC_OP_LTGT0_64:
495 case CC_OP_COMP_32:
496 case CC_OP_COMP_64:
497 case CC_OP_NZ_F32:
498 case CC_OP_NZ_F64:
499 case CC_OP_FLOGR:
500 /* 1 argument */
501 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, dummy, cc_dst, dummy);
502 break;
503 case CC_OP_ICM:
504 case CC_OP_LTGT_32:
505 case CC_OP_LTGT_64:
506 case CC_OP_LTUGTU_32:
507 case CC_OP_LTUGTU_64:
508 case CC_OP_TM_32:
509 case CC_OP_TM_64:
510 case CC_OP_SLA_32:
511 case CC_OP_SLA_64:
512 case CC_OP_NZ_F128:
513 /* 2 arguments */
514 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, dummy);
515 break;
516 case CC_OP_ADD_64:
517 case CC_OP_ADDU_64:
518 case CC_OP_ADDC_64:
519 case CC_OP_SUB_64:
520 case CC_OP_SUBU_64:
521 case CC_OP_SUBB_64:
522 case CC_OP_ADD_32:
523 case CC_OP_ADDU_32:
524 case CC_OP_ADDC_32:
525 case CC_OP_SUB_32:
526 case CC_OP_SUBU_32:
527 case CC_OP_SUBB_32:
528 /* 3 arguments */
529 gen_helper_calc_cc(cc_op, cpu_env, local_cc_op, cc_src, cc_dst, cc_vr);
530 break;
531 case CC_OP_DYNAMIC:
532 /* unknown operation - assume 3 arguments and cc_op in env */
533 gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
534 break;
535 default:
536 tcg_abort();
539 if (!TCGV_IS_UNUSED_I32(local_cc_op)) {
540 tcg_temp_free_i32(local_cc_op);
542 if (!TCGV_IS_UNUSED_I64(dummy)) {
543 tcg_temp_free_i64(dummy);
546 /* We now have cc in cc_op as constant */
547 set_cc_static(s);
550 static int use_goto_tb(DisasContext *s, uint64_t dest)
552 /* NOTE: we handle the case where the TB spans two pages here */
553 return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
554 || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
555 && !s->singlestep_enabled
556 && !(s->tb->cflags & CF_LAST_IO));
559 static void account_noninline_branch(DisasContext *s, int cc_op)
561 #ifdef DEBUG_INLINE_BRANCHES
562 inline_branch_miss[cc_op]++;
563 #endif
566 static void account_inline_branch(DisasContext *s, int cc_op)
568 #ifdef DEBUG_INLINE_BRANCHES
569 inline_branch_hit[cc_op]++;
570 #endif
573 /* Table of mask values to comparison codes, given a comparison as input.
574 For such, CC=3 should not be possible. */
575 static const TCGCond ltgt_cond[16] = {
576 TCG_COND_NEVER, TCG_COND_NEVER, /* | | | x */
577 TCG_COND_GT, TCG_COND_GT, /* | | GT | x */
578 TCG_COND_LT, TCG_COND_LT, /* | LT | | x */
579 TCG_COND_NE, TCG_COND_NE, /* | LT | GT | x */
580 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | | x */
581 TCG_COND_GE, TCG_COND_GE, /* EQ | | GT | x */
582 TCG_COND_LE, TCG_COND_LE, /* EQ | LT | | x */
583 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | LT | GT | x */
586 /* Table of mask values to comparison codes, given a logic op as input.
587 For such, only CC=0 and CC=1 should be possible. */
588 static const TCGCond nz_cond[16] = {
589 TCG_COND_NEVER, TCG_COND_NEVER, /* | | x | x */
590 TCG_COND_NEVER, TCG_COND_NEVER,
591 TCG_COND_NE, TCG_COND_NE, /* | NE | x | x */
592 TCG_COND_NE, TCG_COND_NE,
593 TCG_COND_EQ, TCG_COND_EQ, /* EQ | | x | x */
594 TCG_COND_EQ, TCG_COND_EQ,
595 TCG_COND_ALWAYS, TCG_COND_ALWAYS, /* EQ | NE | x | x */
596 TCG_COND_ALWAYS, TCG_COND_ALWAYS,
599 /* Interpret MASK in terms of S->CC_OP, and fill in C with all the
600 details required to generate a TCG comparison. */
601 static void disas_jcc(DisasContext *s, DisasCompare *c, uint32_t mask)
603 TCGCond cond;
604 enum cc_op old_cc_op = s->cc_op;
606 if (mask == 15 || mask == 0) {
607 c->cond = (mask ? TCG_COND_ALWAYS : TCG_COND_NEVER);
608 c->u.s32.a = cc_op;
609 c->u.s32.b = cc_op;
610 c->g1 = c->g2 = true;
611 c->is_64 = false;
612 return;
615 /* Find the TCG condition for the mask + cc op. */
616 switch (old_cc_op) {
617 case CC_OP_LTGT0_32:
618 case CC_OP_LTGT0_64:
619 case CC_OP_LTGT_32:
620 case CC_OP_LTGT_64:
621 cond = ltgt_cond[mask];
622 if (cond == TCG_COND_NEVER) {
623 goto do_dynamic;
625 account_inline_branch(s, old_cc_op);
626 break;
628 case CC_OP_LTUGTU_32:
629 case CC_OP_LTUGTU_64:
630 cond = tcg_unsigned_cond(ltgt_cond[mask]);
631 if (cond == TCG_COND_NEVER) {
632 goto do_dynamic;
634 account_inline_branch(s, old_cc_op);
635 break;
637 case CC_OP_NZ:
638 cond = nz_cond[mask];
639 if (cond == TCG_COND_NEVER) {
640 goto do_dynamic;
642 account_inline_branch(s, old_cc_op);
643 break;
645 case CC_OP_TM_32:
646 case CC_OP_TM_64:
647 switch (mask) {
648 case 8:
649 cond = TCG_COND_EQ;
650 break;
651 case 4 | 2 | 1:
652 cond = TCG_COND_NE;
653 break;
654 default:
655 goto do_dynamic;
657 account_inline_branch(s, old_cc_op);
658 break;
660 case CC_OP_ICM:
661 switch (mask) {
662 case 8:
663 cond = TCG_COND_EQ;
664 break;
665 case 4 | 2 | 1:
666 case 4 | 2:
667 cond = TCG_COND_NE;
668 break;
669 default:
670 goto do_dynamic;
672 account_inline_branch(s, old_cc_op);
673 break;
675 case CC_OP_FLOGR:
676 switch (mask & 0xa) {
677 case 8: /* src == 0 -> no one bit found */
678 cond = TCG_COND_EQ;
679 break;
680 case 2: /* src != 0 -> one bit found */
681 cond = TCG_COND_NE;
682 break;
683 default:
684 goto do_dynamic;
686 account_inline_branch(s, old_cc_op);
687 break;
689 case CC_OP_ADDU_32:
690 case CC_OP_ADDU_64:
691 switch (mask) {
692 case 8 | 2: /* vr == 0 */
693 cond = TCG_COND_EQ;
694 break;
695 case 4 | 1: /* vr != 0 */
696 cond = TCG_COND_NE;
697 break;
698 case 8 | 4: /* no carry -> vr >= src */
699 cond = TCG_COND_GEU;
700 break;
701 case 2 | 1: /* carry -> vr < src */
702 cond = TCG_COND_LTU;
703 break;
704 default:
705 goto do_dynamic;
707 account_inline_branch(s, old_cc_op);
708 break;
710 case CC_OP_SUBU_32:
711 case CC_OP_SUBU_64:
712 /* Note that CC=0 is impossible; treat it as dont-care. */
713 switch (mask & 7) {
714 case 2: /* zero -> op1 == op2 */
715 cond = TCG_COND_EQ;
716 break;
717 case 4 | 1: /* !zero -> op1 != op2 */
718 cond = TCG_COND_NE;
719 break;
720 case 4: /* borrow (!carry) -> op1 < op2 */
721 cond = TCG_COND_LTU;
722 break;
723 case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
724 cond = TCG_COND_GEU;
725 break;
726 default:
727 goto do_dynamic;
729 account_inline_branch(s, old_cc_op);
730 break;
732 default:
733 do_dynamic:
734 /* Calculate cc value. */
735 gen_op_calc_cc(s);
736 /* FALLTHRU */
738 case CC_OP_STATIC:
739 /* Jump based on CC. We'll load up the real cond below;
740 the assignment here merely avoids a compiler warning. */
741 account_noninline_branch(s, old_cc_op);
742 old_cc_op = CC_OP_STATIC;
743 cond = TCG_COND_NEVER;
744 break;
747 /* Load up the arguments of the comparison. */
748 c->is_64 = true;
749 c->g1 = c->g2 = false;
750 switch (old_cc_op) {
751 case CC_OP_LTGT0_32:
752 c->is_64 = false;
753 c->u.s32.a = tcg_temp_new_i32();
754 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_dst);
755 c->u.s32.b = tcg_const_i32(0);
756 break;
757 case CC_OP_LTGT_32:
758 case CC_OP_LTUGTU_32:
759 case CC_OP_SUBU_32:
760 c->is_64 = false;
761 c->u.s32.a = tcg_temp_new_i32();
762 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_src);
763 c->u.s32.b = tcg_temp_new_i32();
764 tcg_gen_trunc_i64_i32(c->u.s32.b, cc_dst);
765 break;
767 case CC_OP_LTGT0_64:
768 case CC_OP_NZ:
769 case CC_OP_FLOGR:
770 c->u.s64.a = cc_dst;
771 c->u.s64.b = tcg_const_i64(0);
772 c->g1 = true;
773 break;
774 case CC_OP_LTGT_64:
775 case CC_OP_LTUGTU_64:
776 case CC_OP_SUBU_64:
777 c->u.s64.a = cc_src;
778 c->u.s64.b = cc_dst;
779 c->g1 = c->g2 = true;
780 break;
782 case CC_OP_TM_32:
783 case CC_OP_TM_64:
784 case CC_OP_ICM:
785 c->u.s64.a = tcg_temp_new_i64();
786 c->u.s64.b = tcg_const_i64(0);
787 tcg_gen_and_i64(c->u.s64.a, cc_src, cc_dst);
788 break;
790 case CC_OP_ADDU_32:
791 c->is_64 = false;
792 c->u.s32.a = tcg_temp_new_i32();
793 c->u.s32.b = tcg_temp_new_i32();
794 tcg_gen_trunc_i64_i32(c->u.s32.a, cc_vr);
795 if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
796 tcg_gen_movi_i32(c->u.s32.b, 0);
797 } else {
798 tcg_gen_trunc_i64_i32(c->u.s32.b, cc_src);
800 break;
802 case CC_OP_ADDU_64:
803 c->u.s64.a = cc_vr;
804 c->g1 = true;
805 if (cond == TCG_COND_EQ || cond == TCG_COND_NE) {
806 c->u.s64.b = tcg_const_i64(0);
807 } else {
808 c->u.s64.b = cc_src;
809 c->g2 = true;
811 break;
813 case CC_OP_STATIC:
814 c->is_64 = false;
815 c->u.s32.a = cc_op;
816 c->g1 = true;
817 switch (mask) {
818 case 0x8 | 0x4 | 0x2: /* cc != 3 */
819 cond = TCG_COND_NE;
820 c->u.s32.b = tcg_const_i32(3);
821 break;
822 case 0x8 | 0x4 | 0x1: /* cc != 2 */
823 cond = TCG_COND_NE;
824 c->u.s32.b = tcg_const_i32(2);
825 break;
826 case 0x8 | 0x2 | 0x1: /* cc != 1 */
827 cond = TCG_COND_NE;
828 c->u.s32.b = tcg_const_i32(1);
829 break;
830 case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
831 cond = TCG_COND_EQ;
832 c->g1 = false;
833 c->u.s32.a = tcg_temp_new_i32();
834 c->u.s32.b = tcg_const_i32(0);
835 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
836 break;
837 case 0x8 | 0x4: /* cc < 2 */
838 cond = TCG_COND_LTU;
839 c->u.s32.b = tcg_const_i32(2);
840 break;
841 case 0x8: /* cc == 0 */
842 cond = TCG_COND_EQ;
843 c->u.s32.b = tcg_const_i32(0);
844 break;
845 case 0x4 | 0x2 | 0x1: /* cc != 0 */
846 cond = TCG_COND_NE;
847 c->u.s32.b = tcg_const_i32(0);
848 break;
849 case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
850 cond = TCG_COND_NE;
851 c->g1 = false;
852 c->u.s32.a = tcg_temp_new_i32();
853 c->u.s32.b = tcg_const_i32(0);
854 tcg_gen_andi_i32(c->u.s32.a, cc_op, 1);
855 break;
856 case 0x4: /* cc == 1 */
857 cond = TCG_COND_EQ;
858 c->u.s32.b = tcg_const_i32(1);
859 break;
860 case 0x2 | 0x1: /* cc > 1 */
861 cond = TCG_COND_GTU;
862 c->u.s32.b = tcg_const_i32(1);
863 break;
864 case 0x2: /* cc == 2 */
865 cond = TCG_COND_EQ;
866 c->u.s32.b = tcg_const_i32(2);
867 break;
868 case 0x1: /* cc == 3 */
869 cond = TCG_COND_EQ;
870 c->u.s32.b = tcg_const_i32(3);
871 break;
872 default:
873 /* CC is masked by something else: (8 >> cc) & mask. */
874 cond = TCG_COND_NE;
875 c->g1 = false;
876 c->u.s32.a = tcg_const_i32(8);
877 c->u.s32.b = tcg_const_i32(0);
878 tcg_gen_shr_i32(c->u.s32.a, c->u.s32.a, cc_op);
879 tcg_gen_andi_i32(c->u.s32.a, c->u.s32.a, mask);
880 break;
882 break;
884 default:
885 abort();
887 c->cond = cond;
890 static void free_compare(DisasCompare *c)
892 if (!c->g1) {
893 if (c->is_64) {
894 tcg_temp_free_i64(c->u.s64.a);
895 } else {
896 tcg_temp_free_i32(c->u.s32.a);
899 if (!c->g2) {
900 if (c->is_64) {
901 tcg_temp_free_i64(c->u.s64.b);
902 } else {
903 tcg_temp_free_i32(c->u.s32.b);
908 /* ====================================================================== */
909 /* Define the insn format enumeration. */
910 #define F0(N) FMT_##N,
911 #define F1(N, X1) F0(N)
912 #define F2(N, X1, X2) F0(N)
913 #define F3(N, X1, X2, X3) F0(N)
914 #define F4(N, X1, X2, X3, X4) F0(N)
915 #define F5(N, X1, X2, X3, X4, X5) F0(N)
917 typedef enum {
918 #include "insn-format.def"
919 } DisasFormat;
921 #undef F0
922 #undef F1
923 #undef F2
924 #undef F3
925 #undef F4
926 #undef F5
928 /* Define a structure to hold the decoded fields. We'll store each inside
929 an array indexed by an enum. In order to conserve memory, we'll arrange
930 for fields that do not exist at the same time to overlap, thus the "C"
931 for compact. For checking purposes there is an "O" for original index
932 as well that will be applied to availability bitmaps. */
934 enum DisasFieldIndexO {
935 FLD_O_r1,
936 FLD_O_r2,
937 FLD_O_r3,
938 FLD_O_m1,
939 FLD_O_m3,
940 FLD_O_m4,
941 FLD_O_b1,
942 FLD_O_b2,
943 FLD_O_b4,
944 FLD_O_d1,
945 FLD_O_d2,
946 FLD_O_d4,
947 FLD_O_x2,
948 FLD_O_l1,
949 FLD_O_l2,
950 FLD_O_i1,
951 FLD_O_i2,
952 FLD_O_i3,
953 FLD_O_i4,
954 FLD_O_i5
957 enum DisasFieldIndexC {
958 FLD_C_r1 = 0,
959 FLD_C_m1 = 0,
960 FLD_C_b1 = 0,
961 FLD_C_i1 = 0,
963 FLD_C_r2 = 1,
964 FLD_C_b2 = 1,
965 FLD_C_i2 = 1,
967 FLD_C_r3 = 2,
968 FLD_C_m3 = 2,
969 FLD_C_i3 = 2,
971 FLD_C_m4 = 3,
972 FLD_C_b4 = 3,
973 FLD_C_i4 = 3,
974 FLD_C_l1 = 3,
976 FLD_C_i5 = 4,
977 FLD_C_d1 = 4,
979 FLD_C_d2 = 5,
981 FLD_C_d4 = 6,
982 FLD_C_x2 = 6,
983 FLD_C_l2 = 6,
985 NUM_C_FIELD = 7
988 struct DisasFields {
989 unsigned op:8;
990 unsigned op2:8;
991 unsigned presentC:16;
992 unsigned int presentO;
993 int c[NUM_C_FIELD];
996 /* This is the way fields are to be accessed out of DisasFields. */
997 #define have_field(S, F) have_field1((S), FLD_O_##F)
998 #define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
1000 static bool have_field1(const DisasFields *f, enum DisasFieldIndexO c)
1002 return (f->presentO >> c) & 1;
1005 static int get_field1(const DisasFields *f, enum DisasFieldIndexO o,
1006 enum DisasFieldIndexC c)
1008 assert(have_field1(f, o));
1009 return f->c[c];
1012 /* Describe the layout of each field in each format. */
1013 typedef struct DisasField {
1014 unsigned int beg:8;
1015 unsigned int size:8;
1016 unsigned int type:2;
1017 unsigned int indexC:6;
1018 enum DisasFieldIndexO indexO:8;
1019 } DisasField;
1021 typedef struct DisasFormatInfo {
1022 DisasField op[NUM_C_FIELD];
1023 } DisasFormatInfo;
1025 #define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
1026 #define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
1027 #define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1028 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
1029 #define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1030 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1031 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
1032 #define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1033 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1034 #define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1035 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1036 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1037 #define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
1038 #define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
1040 #define F0(N) { { } },
1041 #define F1(N, X1) { { X1 } },
1042 #define F2(N, X1, X2) { { X1, X2 } },
1043 #define F3(N, X1, X2, X3) { { X1, X2, X3 } },
1044 #define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
1045 #define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
1047 static const DisasFormatInfo format_info[] = {
1048 #include "insn-format.def"
1051 #undef F0
1052 #undef F1
1053 #undef F2
1054 #undef F3
1055 #undef F4
1056 #undef F5
1057 #undef R
1058 #undef M
1059 #undef BD
1060 #undef BXD
1061 #undef BDL
1062 #undef BXDL
1063 #undef I
1064 #undef L
1066 /* Generally, we'll extract operands into this structures, operate upon
1067 them, and store them back. See the "in1", "in2", "prep", "wout" sets
1068 of routines below for more details. */
1069 typedef struct {
1070 bool g_out, g_out2, g_in1, g_in2;
1071 TCGv_i64 out, out2, in1, in2;
1072 TCGv_i64 addr1;
1073 } DisasOps;
1075 /* Instructions can place constraints on their operands, raising specification
1076 exceptions if they are violated. To make this easy to automate, each "in1",
1077 "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
1078 of the following, or 0. To make this easy to document, we'll put the
1079 SPEC_<name> defines next to <name>. */
1081 #define SPEC_r1_even 1
1082 #define SPEC_r2_even 2
1083 #define SPEC_r3_even 4
1084 #define SPEC_r1_f128 8
1085 #define SPEC_r2_f128 16
1087 /* Return values from translate_one, indicating the state of the TB. */
1088 typedef enum {
1089 /* Continue the TB. */
1090 NO_EXIT,
1091 /* We have emitted one or more goto_tb. No fixup required. */
1092 EXIT_GOTO_TB,
1093 /* We are not using a goto_tb (for whatever reason), but have updated
1094 the PC (for whatever reason), so there's no need to do it again on
1095 exiting the TB. */
1096 EXIT_PC_UPDATED,
1097 /* We are exiting the TB, but have neither emitted a goto_tb, nor
1098 updated the PC for the next instruction to be executed. */
1099 EXIT_PC_STALE,
1100 /* We are ending the TB with a noreturn function call, e.g. longjmp.
1101 No following code will be executed. */
1102 EXIT_NORETURN,
1103 } ExitStatus;
1105 typedef enum DisasFacility {
1106 FAC_Z, /* zarch (default) */
1107 FAC_CASS, /* compare and swap and store */
1108 FAC_CASS2, /* compare and swap and store 2*/
1109 FAC_DFP, /* decimal floating point */
1110 FAC_DFPR, /* decimal floating point rounding */
1111 FAC_DO, /* distinct operands */
1112 FAC_EE, /* execute extensions */
1113 FAC_EI, /* extended immediate */
1114 FAC_FPE, /* floating point extension */
1115 FAC_FPSSH, /* floating point support sign handling */
1116 FAC_FPRGR, /* FPR-GR transfer */
1117 FAC_GIE, /* general instructions extension */
1118 FAC_HFP_MA, /* HFP multiply-and-add/subtract */
1119 FAC_HW, /* high-word */
1120 FAC_IEEEE_SIM, /* IEEE exception sumilation */
1121 FAC_LOC, /* load/store on condition */
1122 FAC_LD, /* long displacement */
1123 FAC_PC, /* population count */
1124 FAC_SCF, /* store clock fast */
1125 FAC_SFLE, /* store facility list extended */
1126 } DisasFacility;
1128 struct DisasInsn {
1129 unsigned opc:16;
1130 DisasFormat fmt:8;
1131 DisasFacility fac:8;
1132 unsigned spec:8;
1134 const char *name;
1136 void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
1137 void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
1138 void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
1139 void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
1140 void (*help_cout)(DisasContext *, DisasOps *);
1141 ExitStatus (*help_op)(DisasContext *, DisasOps *);
1143 uint64_t data;
1146 /* ====================================================================== */
1147 /* Miscellaneous helpers, used by several operations. */
1149 static void help_l2_shift(DisasContext *s, DisasFields *f,
1150 DisasOps *o, int mask)
1152 int b2 = get_field(f, b2);
1153 int d2 = get_field(f, d2);
1155 if (b2 == 0) {
1156 o->in2 = tcg_const_i64(d2 & mask);
1157 } else {
1158 o->in2 = get_address(s, 0, b2, d2);
1159 tcg_gen_andi_i64(o->in2, o->in2, mask);
1163 static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest)
1165 if (dest == s->next_pc) {
1166 return NO_EXIT;
1168 if (use_goto_tb(s, dest)) {
1169 update_cc_op(s);
1170 tcg_gen_goto_tb(0);
1171 tcg_gen_movi_i64(psw_addr, dest);
1172 tcg_gen_exit_tb((tcg_target_long)s->tb);
1173 return EXIT_GOTO_TB;
1174 } else {
1175 tcg_gen_movi_i64(psw_addr, dest);
1176 return EXIT_PC_UPDATED;
1180 static ExitStatus help_branch(DisasContext *s, DisasCompare *c,
1181 bool is_imm, int imm, TCGv_i64 cdest)
1183 ExitStatus ret;
1184 uint64_t dest = s->pc + 2 * imm;
1185 int lab;
1187 /* Take care of the special cases first. */
1188 if (c->cond == TCG_COND_NEVER) {
1189 ret = NO_EXIT;
1190 goto egress;
1192 if (is_imm) {
1193 if (dest == s->next_pc) {
1194 /* Branch to next. */
1195 ret = NO_EXIT;
1196 goto egress;
1198 if (c->cond == TCG_COND_ALWAYS) {
1199 ret = help_goto_direct(s, dest);
1200 goto egress;
1202 } else {
1203 if (TCGV_IS_UNUSED_I64(cdest)) {
1204 /* E.g. bcr %r0 -> no branch. */
1205 ret = NO_EXIT;
1206 goto egress;
1208 if (c->cond == TCG_COND_ALWAYS) {
1209 tcg_gen_mov_i64(psw_addr, cdest);
1210 ret = EXIT_PC_UPDATED;
1211 goto egress;
1215 if (use_goto_tb(s, s->next_pc)) {
1216 if (is_imm && use_goto_tb(s, dest)) {
1217 /* Both exits can use goto_tb. */
1218 update_cc_op(s);
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);
1227 /* Branch not taken. */
1228 tcg_gen_goto_tb(0);
1229 tcg_gen_movi_i64(psw_addr, s->next_pc);
1230 tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
1232 /* Branch taken. */
1233 gen_set_label(lab);
1234 tcg_gen_goto_tb(1);
1235 tcg_gen_movi_i64(psw_addr, dest);
1236 tcg_gen_exit_tb((tcg_target_long)s->tb + 1);
1238 ret = EXIT_GOTO_TB;
1239 } else {
1240 /* Fallthru can use goto_tb, but taken branch cannot. */
1241 /* Store taken branch destination before the brcond. This
1242 avoids having to allocate a new local temp to hold it.
1243 We'll overwrite this in the not taken case anyway. */
1244 if (!is_imm) {
1245 tcg_gen_mov_i64(psw_addr, cdest);
1248 lab = gen_new_label();
1249 if (c->is_64) {
1250 tcg_gen_brcond_i64(c->cond, c->u.s64.a, c->u.s64.b, lab);
1251 } else {
1252 tcg_gen_brcond_i32(c->cond, c->u.s32.a, c->u.s32.b, lab);
1255 /* Branch not taken. */
1256 update_cc_op(s);
1257 tcg_gen_goto_tb(0);
1258 tcg_gen_movi_i64(psw_addr, s->next_pc);
1259 tcg_gen_exit_tb((tcg_target_long)s->tb + 0);
1261 gen_set_label(lab);
1262 if (is_imm) {
1263 tcg_gen_movi_i64(psw_addr, dest);
1265 ret = EXIT_PC_UPDATED;
1267 } else {
1268 /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
1269 Most commonly we're single-stepping or some other condition that
1270 disables all use of goto_tb. Just update the PC and exit. */
1272 TCGv_i64 next = tcg_const_i64(s->next_pc);
1273 if (is_imm) {
1274 cdest = tcg_const_i64(dest);
1277 if (c->is_64) {
1278 tcg_gen_movcond_i64(c->cond, psw_addr, c->u.s64.a, c->u.s64.b,
1279 cdest, next);
1280 } else {
1281 TCGv_i32 t0 = tcg_temp_new_i32();
1282 TCGv_i64 t1 = tcg_temp_new_i64();
1283 TCGv_i64 z = tcg_const_i64(0);
1284 tcg_gen_setcond_i32(c->cond, t0, c->u.s32.a, c->u.s32.b);
1285 tcg_gen_extu_i32_i64(t1, t0);
1286 tcg_temp_free_i32(t0);
1287 tcg_gen_movcond_i64(TCG_COND_NE, psw_addr, t1, z, cdest, next);
1288 tcg_temp_free_i64(t1);
1289 tcg_temp_free_i64(z);
1292 if (is_imm) {
1293 tcg_temp_free_i64(cdest);
1295 tcg_temp_free_i64(next);
1297 ret = EXIT_PC_UPDATED;
1300 egress:
1301 free_compare(c);
1302 return ret;
1305 /* ====================================================================== */
1306 /* The operations. These perform the bulk of the work for any insn,
1307 usually after the operands have been loaded and output initialized. */
1309 static ExitStatus op_abs(DisasContext *s, DisasOps *o)
1311 gen_helper_abs_i64(o->out, o->in2);
1312 return NO_EXIT;
1315 static ExitStatus op_absf32(DisasContext *s, DisasOps *o)
1317 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull);
1318 return NO_EXIT;
1321 static ExitStatus op_absf64(DisasContext *s, DisasOps *o)
1323 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
1324 return NO_EXIT;
1327 static ExitStatus op_absf128(DisasContext *s, DisasOps *o)
1329 tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull);
1330 tcg_gen_mov_i64(o->out2, o->in2);
1331 return NO_EXIT;
1334 static ExitStatus op_add(DisasContext *s, DisasOps *o)
1336 tcg_gen_add_i64(o->out, o->in1, o->in2);
1337 return NO_EXIT;
1340 static ExitStatus op_addc(DisasContext *s, DisasOps *o)
1342 DisasCompare cmp;
1343 TCGv_i64 carry;
1345 tcg_gen_add_i64(o->out, o->in1, o->in2);
1347 /* The carry flag is the msb of CC, therefore the branch mask that would
1348 create that comparison is 3. Feeding the generated comparison to
1349 setcond produces the carry flag that we desire. */
1350 disas_jcc(s, &cmp, 3);
1351 carry = tcg_temp_new_i64();
1352 if (cmp.is_64) {
1353 tcg_gen_setcond_i64(cmp.cond, carry, cmp.u.s64.a, cmp.u.s64.b);
1354 } else {
1355 TCGv_i32 t = tcg_temp_new_i32();
1356 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
1357 tcg_gen_extu_i32_i64(carry, t);
1358 tcg_temp_free_i32(t);
1360 free_compare(&cmp);
1362 tcg_gen_add_i64(o->out, o->out, carry);
1363 tcg_temp_free_i64(carry);
1364 return NO_EXIT;
1367 static ExitStatus op_aeb(DisasContext *s, DisasOps *o)
1369 gen_helper_aeb(o->out, cpu_env, o->in1, o->in2);
1370 return NO_EXIT;
1373 static ExitStatus op_adb(DisasContext *s, DisasOps *o)
1375 gen_helper_adb(o->out, cpu_env, o->in1, o->in2);
1376 return NO_EXIT;
1379 static ExitStatus op_axb(DisasContext *s, DisasOps *o)
1381 gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
1382 return_low128(o->out2);
1383 return NO_EXIT;
1386 static ExitStatus op_and(DisasContext *s, DisasOps *o)
1388 tcg_gen_and_i64(o->out, o->in1, o->in2);
1389 return NO_EXIT;
1392 static ExitStatus op_andi(DisasContext *s, DisasOps *o)
1394 int shift = s->insn->data & 0xff;
1395 int size = s->insn->data >> 8;
1396 uint64_t mask = ((1ull << size) - 1) << shift;
1398 assert(!o->g_in2);
1399 tcg_gen_shli_i64(o->in2, o->in2, shift);
1400 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
1401 tcg_gen_and_i64(o->out, o->in1, o->in2);
1403 /* Produce the CC from only the bits manipulated. */
1404 tcg_gen_andi_i64(cc_dst, o->out, mask);
1405 set_cc_nz_u64(s, cc_dst);
1406 return NO_EXIT;
1409 static ExitStatus op_bas(DisasContext *s, DisasOps *o)
1411 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
1412 if (!TCGV_IS_UNUSED_I64(o->in2)) {
1413 tcg_gen_mov_i64(psw_addr, o->in2);
1414 return EXIT_PC_UPDATED;
1415 } else {
1416 return NO_EXIT;
1420 static ExitStatus op_basi(DisasContext *s, DisasOps *o)
1422 tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc));
1423 return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2));
1426 static ExitStatus op_bc(DisasContext *s, DisasOps *o)
1428 int m1 = get_field(s->fields, m1);
1429 bool is_imm = have_field(s->fields, i2);
1430 int imm = is_imm ? get_field(s->fields, i2) : 0;
1431 DisasCompare c;
1433 disas_jcc(s, &c, m1);
1434 return help_branch(s, &c, is_imm, imm, o->in2);
1437 static ExitStatus op_bct32(DisasContext *s, DisasOps *o)
1439 int r1 = get_field(s->fields, r1);
1440 bool is_imm = have_field(s->fields, i2);
1441 int imm = is_imm ? get_field(s->fields, i2) : 0;
1442 DisasCompare c;
1443 TCGv_i64 t;
1445 c.cond = TCG_COND_NE;
1446 c.is_64 = false;
1447 c.g1 = false;
1448 c.g2 = false;
1450 t = tcg_temp_new_i64();
1451 tcg_gen_subi_i64(t, regs[r1], 1);
1452 store_reg32_i64(r1, t);
1453 c.u.s32.a = tcg_temp_new_i32();
1454 c.u.s32.b = tcg_const_i32(0);
1455 tcg_gen_trunc_i64_i32(c.u.s32.a, t);
1456 tcg_temp_free_i64(t);
1458 return help_branch(s, &c, is_imm, imm, o->in2);
1461 static ExitStatus op_bct64(DisasContext *s, DisasOps *o)
1463 int r1 = get_field(s->fields, r1);
1464 bool is_imm = have_field(s->fields, i2);
1465 int imm = is_imm ? get_field(s->fields, i2) : 0;
1466 DisasCompare c;
1468 c.cond = TCG_COND_NE;
1469 c.is_64 = true;
1470 c.g1 = true;
1471 c.g2 = false;
1473 tcg_gen_subi_i64(regs[r1], regs[r1], 1);
1474 c.u.s64.a = regs[r1];
1475 c.u.s64.b = tcg_const_i64(0);
1477 return help_branch(s, &c, is_imm, imm, o->in2);
1480 static ExitStatus op_bx32(DisasContext *s, DisasOps *o)
1482 int r1 = get_field(s->fields, r1);
1483 int r3 = get_field(s->fields, r3);
1484 bool is_imm = have_field(s->fields, i2);
1485 int imm = is_imm ? get_field(s->fields, i2) : 0;
1486 DisasCompare c;
1487 TCGv_i64 t;
1489 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
1490 c.is_64 = false;
1491 c.g1 = false;
1492 c.g2 = false;
1494 t = tcg_temp_new_i64();
1495 tcg_gen_add_i64(t, regs[r1], regs[r3]);
1496 c.u.s32.a = tcg_temp_new_i32();
1497 c.u.s32.b = tcg_temp_new_i32();
1498 tcg_gen_trunc_i64_i32(c.u.s32.a, t);
1499 tcg_gen_trunc_i64_i32(c.u.s32.b, regs[r3 | 1]);
1500 store_reg32_i64(r1, t);
1501 tcg_temp_free_i64(t);
1503 return help_branch(s, &c, is_imm, imm, o->in2);
1506 static ExitStatus op_bx64(DisasContext *s, DisasOps *o)
1508 int r1 = get_field(s->fields, r1);
1509 int r3 = get_field(s->fields, r3);
1510 bool is_imm = have_field(s->fields, i2);
1511 int imm = is_imm ? get_field(s->fields, i2) : 0;
1512 DisasCompare c;
1514 c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
1515 c.is_64 = true;
1517 if (r1 == (r3 | 1)) {
1518 c.u.s64.b = load_reg(r3 | 1);
1519 c.g2 = false;
1520 } else {
1521 c.u.s64.b = regs[r3 | 1];
1522 c.g2 = true;
1525 tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
1526 c.u.s64.a = regs[r1];
1527 c.g1 = true;
1529 return help_branch(s, &c, is_imm, imm, o->in2);
1532 static ExitStatus op_cj(DisasContext *s, DisasOps *o)
1534 int imm, m3 = get_field(s->fields, m3);
1535 bool is_imm;
1536 DisasCompare c;
1538 c.cond = ltgt_cond[m3];
1539 if (s->insn->data) {
1540 c.cond = tcg_unsigned_cond(c.cond);
1542 c.is_64 = c.g1 = c.g2 = true;
1543 c.u.s64.a = o->in1;
1544 c.u.s64.b = o->in2;
1546 is_imm = have_field(s->fields, i4);
1547 if (is_imm) {
1548 imm = get_field(s->fields, i4);
1549 } else {
1550 imm = 0;
1551 o->out = get_address(s, 0, get_field(s->fields, b4),
1552 get_field(s->fields, d4));
1555 return help_branch(s, &c, is_imm, imm, o->out);
1558 static ExitStatus op_ceb(DisasContext *s, DisasOps *o)
1560 gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2);
1561 set_cc_static(s);
1562 return NO_EXIT;
1565 static ExitStatus op_cdb(DisasContext *s, DisasOps *o)
1567 gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2);
1568 set_cc_static(s);
1569 return NO_EXIT;
1572 static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
1574 gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2);
1575 set_cc_static(s);
1576 return NO_EXIT;
1579 static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
1581 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1582 gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
1583 tcg_temp_free_i32(m3);
1584 gen_set_cc_nz_f32(s, o->in2);
1585 return NO_EXIT;
1588 static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
1590 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1591 gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
1592 tcg_temp_free_i32(m3);
1593 gen_set_cc_nz_f64(s, o->in2);
1594 return NO_EXIT;
1597 static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
1599 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1600 gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
1601 tcg_temp_free_i32(m3);
1602 gen_set_cc_nz_f128(s, o->in1, o->in2);
1603 return NO_EXIT;
1606 static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
1608 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1609 gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
1610 tcg_temp_free_i32(m3);
1611 gen_set_cc_nz_f32(s, o->in2);
1612 return NO_EXIT;
1615 static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
1617 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1618 gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
1619 tcg_temp_free_i32(m3);
1620 gen_set_cc_nz_f64(s, o->in2);
1621 return NO_EXIT;
1624 static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
1626 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1627 gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
1628 tcg_temp_free_i32(m3);
1629 gen_set_cc_nz_f128(s, o->in1, o->in2);
1630 return NO_EXIT;
1633 static ExitStatus op_clfeb(DisasContext *s, DisasOps *o)
1635 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1636 gen_helper_clfeb(o->out, cpu_env, o->in2, m3);
1637 tcg_temp_free_i32(m3);
1638 gen_set_cc_nz_f32(s, o->in2);
1639 return NO_EXIT;
1642 static ExitStatus op_clfdb(DisasContext *s, DisasOps *o)
1644 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1645 gen_helper_clfdb(o->out, cpu_env, o->in2, m3);
1646 tcg_temp_free_i32(m3);
1647 gen_set_cc_nz_f64(s, o->in2);
1648 return NO_EXIT;
1651 static ExitStatus op_clfxb(DisasContext *s, DisasOps *o)
1653 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1654 gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3);
1655 tcg_temp_free_i32(m3);
1656 gen_set_cc_nz_f128(s, o->in1, o->in2);
1657 return NO_EXIT;
1660 static ExitStatus op_clgeb(DisasContext *s, DisasOps *o)
1662 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1663 gen_helper_clgeb(o->out, cpu_env, o->in2, m3);
1664 tcg_temp_free_i32(m3);
1665 gen_set_cc_nz_f32(s, o->in2);
1666 return NO_EXIT;
1669 static ExitStatus op_clgdb(DisasContext *s, DisasOps *o)
1671 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1672 gen_helper_clgdb(o->out, cpu_env, o->in2, m3);
1673 tcg_temp_free_i32(m3);
1674 gen_set_cc_nz_f64(s, o->in2);
1675 return NO_EXIT;
1678 static ExitStatus op_clgxb(DisasContext *s, DisasOps *o)
1680 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1681 gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3);
1682 tcg_temp_free_i32(m3);
1683 gen_set_cc_nz_f128(s, o->in1, o->in2);
1684 return NO_EXIT;
1687 static ExitStatus op_cegb(DisasContext *s, DisasOps *o)
1689 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1690 gen_helper_cegb(o->out, cpu_env, o->in2, m3);
1691 tcg_temp_free_i32(m3);
1692 return NO_EXIT;
1695 static ExitStatus op_cdgb(DisasContext *s, DisasOps *o)
1697 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1698 gen_helper_cdgb(o->out, cpu_env, o->in2, m3);
1699 tcg_temp_free_i32(m3);
1700 return NO_EXIT;
1703 static ExitStatus op_cxgb(DisasContext *s, DisasOps *o)
1705 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1706 gen_helper_cxgb(o->out, cpu_env, o->in2, m3);
1707 tcg_temp_free_i32(m3);
1708 return_low128(o->out2);
1709 return NO_EXIT;
1712 static ExitStatus op_celgb(DisasContext *s, DisasOps *o)
1714 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1715 gen_helper_celgb(o->out, cpu_env, o->in2, m3);
1716 tcg_temp_free_i32(m3);
1717 return NO_EXIT;
1720 static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o)
1722 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1723 gen_helper_cdlgb(o->out, cpu_env, o->in2, m3);
1724 tcg_temp_free_i32(m3);
1725 return NO_EXIT;
1728 static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o)
1730 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1731 gen_helper_cxlgb(o->out, cpu_env, o->in2, m3);
1732 tcg_temp_free_i32(m3);
1733 return_low128(o->out2);
1734 return NO_EXIT;
1737 static ExitStatus op_cksm(DisasContext *s, DisasOps *o)
1739 int r2 = get_field(s->fields, r2);
1740 TCGv_i64 len = tcg_temp_new_i64();
1742 potential_page_fault(s);
1743 gen_helper_cksm(len, cpu_env, o->in1, o->in2, regs[r2 + 1]);
1744 set_cc_static(s);
1745 return_low128(o->out);
1747 tcg_gen_add_i64(regs[r2], regs[r2], len);
1748 tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len);
1749 tcg_temp_free_i64(len);
1751 return NO_EXIT;
1754 static ExitStatus op_clc(DisasContext *s, DisasOps *o)
1756 int l = get_field(s->fields, l1);
1757 TCGv_i32 vl;
1759 switch (l + 1) {
1760 case 1:
1761 tcg_gen_qemu_ld8u(cc_src, o->addr1, get_mem_index(s));
1762 tcg_gen_qemu_ld8u(cc_dst, o->in2, get_mem_index(s));
1763 break;
1764 case 2:
1765 tcg_gen_qemu_ld16u(cc_src, o->addr1, get_mem_index(s));
1766 tcg_gen_qemu_ld16u(cc_dst, o->in2, get_mem_index(s));
1767 break;
1768 case 4:
1769 tcg_gen_qemu_ld32u(cc_src, o->addr1, get_mem_index(s));
1770 tcg_gen_qemu_ld32u(cc_dst, o->in2, get_mem_index(s));
1771 break;
1772 case 8:
1773 tcg_gen_qemu_ld64(cc_src, o->addr1, get_mem_index(s));
1774 tcg_gen_qemu_ld64(cc_dst, o->in2, get_mem_index(s));
1775 break;
1776 default:
1777 potential_page_fault(s);
1778 vl = tcg_const_i32(l);
1779 gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2);
1780 tcg_temp_free_i32(vl);
1781 set_cc_static(s);
1782 return NO_EXIT;
1784 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst);
1785 return NO_EXIT;
1788 static ExitStatus op_clcle(DisasContext *s, DisasOps *o)
1790 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
1791 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
1792 potential_page_fault(s);
1793 gen_helper_clcle(cc_op, cpu_env, r1, o->in2, r3);
1794 tcg_temp_free_i32(r1);
1795 tcg_temp_free_i32(r3);
1796 set_cc_static(s);
1797 return NO_EXIT;
1800 static ExitStatus op_clm(DisasContext *s, DisasOps *o)
1802 TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
1803 TCGv_i32 t1 = tcg_temp_new_i32();
1804 tcg_gen_trunc_i64_i32(t1, o->in1);
1805 potential_page_fault(s);
1806 gen_helper_clm(cc_op, cpu_env, t1, m3, o->in2);
1807 set_cc_static(s);
1808 tcg_temp_free_i32(t1);
1809 tcg_temp_free_i32(m3);
1810 return NO_EXIT;
1813 static ExitStatus op_clst(DisasContext *s, DisasOps *o)
1815 potential_page_fault(s);
1816 gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2);
1817 set_cc_static(s);
1818 return_low128(o->in2);
1819 return NO_EXIT;
1822 static ExitStatus op_cps(DisasContext *s, DisasOps *o)
1824 TCGv_i64 t = tcg_temp_new_i64();
1825 tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull);
1826 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull);
1827 tcg_gen_or_i64(o->out, o->out, t);
1828 tcg_temp_free_i64(t);
1829 return NO_EXIT;
1832 static ExitStatus op_cs(DisasContext *s, DisasOps *o)
1834 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1835 int d2 = get_field(s->fields, d2);
1836 int b2 = get_field(s->fields, b2);
1837 int is_64 = s->insn->data;
1838 TCGv_i64 addr, mem, cc, z;
1840 /* Note that in1 = R3 (new value) and
1841 in2 = (zero-extended) R1 (expected value). */
1843 /* Load the memory into the (temporary) output. While the PoO only talks
1844 about moving the memory to R1 on inequality, if we include equality it
1845 means that R1 is equal to the memory in all conditions. */
1846 addr = get_address(s, 0, b2, d2);
1847 if (is_64) {
1848 tcg_gen_qemu_ld64(o->out, addr, get_mem_index(s));
1849 } else {
1850 tcg_gen_qemu_ld32u(o->out, addr, get_mem_index(s));
1853 /* Are the memory and expected values (un)equal? Note that this setcond
1854 produces the output CC value, thus the NE sense of the test. */
1855 cc = tcg_temp_new_i64();
1856 tcg_gen_setcond_i64(TCG_COND_NE, cc, o->in2, o->out);
1858 /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
1859 Recall that we are allowed to unconditionally issue the store (and
1860 thus any possible write trap), so (re-)store the original contents
1861 of MEM in case of inequality. */
1862 z = tcg_const_i64(0);
1863 mem = tcg_temp_new_i64();
1864 tcg_gen_movcond_i64(TCG_COND_EQ, mem, cc, z, o->in1, o->out);
1865 if (is_64) {
1866 tcg_gen_qemu_st64(mem, addr, get_mem_index(s));
1867 } else {
1868 tcg_gen_qemu_st32(mem, addr, get_mem_index(s));
1870 tcg_temp_free_i64(z);
1871 tcg_temp_free_i64(mem);
1872 tcg_temp_free_i64(addr);
1874 /* Store CC back to cc_op. Wait until after the store so that any
1875 exception gets the old cc_op value. */
1876 tcg_gen_trunc_i64_i32(cc_op, cc);
1877 tcg_temp_free_i64(cc);
1878 set_cc_static(s);
1879 return NO_EXIT;
1882 static ExitStatus op_cdsg(DisasContext *s, DisasOps *o)
1884 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1885 int r1 = get_field(s->fields, r1);
1886 int r3 = get_field(s->fields, r3);
1887 int d2 = get_field(s->fields, d2);
1888 int b2 = get_field(s->fields, b2);
1889 TCGv_i64 addrh, addrl, memh, meml, outh, outl, cc, z;
1891 /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
1893 addrh = get_address(s, 0, b2, d2);
1894 addrl = get_address(s, 0, b2, d2 + 8);
1895 outh = tcg_temp_new_i64();
1896 outl = tcg_temp_new_i64();
1898 tcg_gen_qemu_ld64(outh, addrh, get_mem_index(s));
1899 tcg_gen_qemu_ld64(outl, addrl, get_mem_index(s));
1901 /* Fold the double-word compare with arithmetic. */
1902 cc = tcg_temp_new_i64();
1903 z = tcg_temp_new_i64();
1904 tcg_gen_xor_i64(cc, outh, regs[r1]);
1905 tcg_gen_xor_i64(z, outl, regs[r1 + 1]);
1906 tcg_gen_or_i64(cc, cc, z);
1907 tcg_gen_movi_i64(z, 0);
1908 tcg_gen_setcond_i64(TCG_COND_NE, cc, cc, z);
1910 memh = tcg_temp_new_i64();
1911 meml = tcg_temp_new_i64();
1912 tcg_gen_movcond_i64(TCG_COND_EQ, memh, cc, z, regs[r3], outh);
1913 tcg_gen_movcond_i64(TCG_COND_EQ, meml, cc, z, regs[r3 + 1], outl);
1914 tcg_temp_free_i64(z);
1916 tcg_gen_qemu_st64(memh, addrh, get_mem_index(s));
1917 tcg_gen_qemu_st64(meml, addrl, get_mem_index(s));
1918 tcg_temp_free_i64(memh);
1919 tcg_temp_free_i64(meml);
1920 tcg_temp_free_i64(addrh);
1921 tcg_temp_free_i64(addrl);
1923 /* Save back state now that we've passed all exceptions. */
1924 tcg_gen_mov_i64(regs[r1], outh);
1925 tcg_gen_mov_i64(regs[r1 + 1], outl);
1926 tcg_gen_trunc_i64_i32(cc_op, cc);
1927 tcg_temp_free_i64(outh);
1928 tcg_temp_free_i64(outl);
1929 tcg_temp_free_i64(cc);
1930 set_cc_static(s);
1931 return NO_EXIT;
1934 #ifndef CONFIG_USER_ONLY
1935 static ExitStatus op_csp(DisasContext *s, DisasOps *o)
1937 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
1938 check_privileged(s);
1939 gen_helper_csp(cc_op, cpu_env, r1, o->in2);
1940 tcg_temp_free_i32(r1);
1941 set_cc_static(s);
1942 return NO_EXIT;
1944 #endif
1946 static ExitStatus op_cvd(DisasContext *s, DisasOps *o)
1948 TCGv_i64 t1 = tcg_temp_new_i64();
1949 TCGv_i32 t2 = tcg_temp_new_i32();
1950 tcg_gen_trunc_i64_i32(t2, o->in1);
1951 gen_helper_cvd(t1, t2);
1952 tcg_temp_free_i32(t2);
1953 tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s));
1954 tcg_temp_free_i64(t1);
1955 return NO_EXIT;
1958 static ExitStatus op_ct(DisasContext *s, DisasOps *o)
1960 int m3 = get_field(s->fields, m3);
1961 int lab = gen_new_label();
1962 TCGv_i32 t;
1963 TCGCond c;
1965 c = tcg_invert_cond(ltgt_cond[m3]);
1966 if (s->insn->data) {
1967 c = tcg_unsigned_cond(c);
1969 tcg_gen_brcond_i64(c, o->in1, o->in2, lab);
1971 /* Set DXC to 0xff. */
1972 t = tcg_temp_new_i32();
1973 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
1974 tcg_gen_ori_i32(t, t, 0xff00);
1975 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, fpc));
1976 tcg_temp_free_i32(t);
1978 /* Trap. */
1979 gen_program_exception(s, PGM_DATA);
1981 gen_set_label(lab);
1982 return NO_EXIT;
1985 #ifndef CONFIG_USER_ONLY
1986 static ExitStatus op_diag(DisasContext *s, DisasOps *o)
1988 TCGv_i32 tmp;
1990 check_privileged(s);
1991 potential_page_fault(s);
1993 /* We pretend the format is RX_a so that D2 is the field we want. */
1994 tmp = tcg_const_i32(get_field(s->fields, d2) & 0xfff);
1995 gen_helper_diag(regs[2], cpu_env, tmp, regs[2], regs[1]);
1996 tcg_temp_free_i32(tmp);
1997 return NO_EXIT;
1999 #endif
2001 static ExitStatus op_divs32(DisasContext *s, DisasOps *o)
2003 gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2);
2004 return_low128(o->out);
2005 return NO_EXIT;
2008 static ExitStatus op_divu32(DisasContext *s, DisasOps *o)
2010 gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2);
2011 return_low128(o->out);
2012 return NO_EXIT;
2015 static ExitStatus op_divs64(DisasContext *s, DisasOps *o)
2017 gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2);
2018 return_low128(o->out);
2019 return NO_EXIT;
2022 static ExitStatus op_divu64(DisasContext *s, DisasOps *o)
2024 gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2);
2025 return_low128(o->out);
2026 return NO_EXIT;
2029 static ExitStatus op_deb(DisasContext *s, DisasOps *o)
2031 gen_helper_deb(o->out, cpu_env, o->in1, o->in2);
2032 return NO_EXIT;
2035 static ExitStatus op_ddb(DisasContext *s, DisasOps *o)
2037 gen_helper_ddb(o->out, cpu_env, o->in1, o->in2);
2038 return NO_EXIT;
2041 static ExitStatus op_dxb(DisasContext *s, DisasOps *o)
2043 gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2044 return_low128(o->out2);
2045 return NO_EXIT;
2048 static ExitStatus op_ear(DisasContext *s, DisasOps *o)
2050 int r2 = get_field(s->fields, r2);
2051 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2]));
2052 return NO_EXIT;
2055 static ExitStatus op_efpc(DisasContext *s, DisasOps *o)
2057 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc));
2058 return NO_EXIT;
2061 static ExitStatus op_ex(DisasContext *s, DisasOps *o)
2063 /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
2064 tb->flags, (ab)use the tb->cs_base field as the address of
2065 the template in memory, and grab 8 bits of tb->flags/cflags for
2066 the contents of the register. We would then recognize all this
2067 in gen_intermediate_code_internal, generating code for exactly
2068 one instruction. This new TB then gets executed normally.
2070 On the other hand, this seems to be mostly used for modifying
2071 MVC inside of memcpy, which needs a helper call anyway. So
2072 perhaps this doesn't bear thinking about any further. */
2074 TCGv_i64 tmp;
2076 update_psw_addr(s);
2077 update_cc_op(s);
2079 tmp = tcg_const_i64(s->next_pc);
2080 gen_helper_ex(cc_op, cpu_env, cc_op, o->in1, o->in2, tmp);
2081 tcg_temp_free_i64(tmp);
2083 set_cc_static(s);
2084 return NO_EXIT;
2087 static ExitStatus op_flogr(DisasContext *s, DisasOps *o)
2089 /* We'll use the original input for cc computation, since we get to
2090 compare that against 0, which ought to be better than comparing
2091 the real output against 64. It also lets cc_dst be a convenient
2092 temporary during our computation. */
2093 gen_op_update1_cc_i64(s, CC_OP_FLOGR, o->in2);
2095 /* R1 = IN ? CLZ(IN) : 64. */
2096 gen_helper_clz(o->out, o->in2);
2098 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2099 value by 64, which is undefined. But since the shift is 64 iff the
2100 input is zero, we still get the correct result after and'ing. */
2101 tcg_gen_movi_i64(o->out2, 0x8000000000000000ull);
2102 tcg_gen_shr_i64(o->out2, o->out2, o->out);
2103 tcg_gen_andc_i64(o->out2, cc_dst, o->out2);
2104 return NO_EXIT;
2107 static ExitStatus op_icm(DisasContext *s, DisasOps *o)
2109 int m3 = get_field(s->fields, m3);
2110 int pos, len, base = s->insn->data;
2111 TCGv_i64 tmp = tcg_temp_new_i64();
2112 uint64_t ccm;
2114 switch (m3) {
2115 case 0xf:
2116 /* Effectively a 32-bit load. */
2117 tcg_gen_qemu_ld32u(tmp, o->in2, get_mem_index(s));
2118 len = 32;
2119 goto one_insert;
2121 case 0xc:
2122 case 0x6:
2123 case 0x3:
2124 /* Effectively a 16-bit load. */
2125 tcg_gen_qemu_ld16u(tmp, o->in2, get_mem_index(s));
2126 len = 16;
2127 goto one_insert;
2129 case 0x8:
2130 case 0x4:
2131 case 0x2:
2132 case 0x1:
2133 /* Effectively an 8-bit load. */
2134 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2135 len = 8;
2136 goto one_insert;
2138 one_insert:
2139 pos = base + ctz32(m3) * 8;
2140 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, len);
2141 ccm = ((1ull << len) - 1) << pos;
2142 break;
2144 default:
2145 /* This is going to be a sequence of loads and inserts. */
2146 pos = base + 32 - 8;
2147 ccm = 0;
2148 while (m3) {
2149 if (m3 & 0x8) {
2150 tcg_gen_qemu_ld8u(tmp, o->in2, get_mem_index(s));
2151 tcg_gen_addi_i64(o->in2, o->in2, 1);
2152 tcg_gen_deposit_i64(o->out, o->out, tmp, pos, 8);
2153 ccm |= 0xff << pos;
2155 m3 = (m3 << 1) & 0xf;
2156 pos -= 8;
2158 break;
2161 tcg_gen_movi_i64(tmp, ccm);
2162 gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out);
2163 tcg_temp_free_i64(tmp);
2164 return NO_EXIT;
2167 static ExitStatus op_insi(DisasContext *s, DisasOps *o)
2169 int shift = s->insn->data & 0xff;
2170 int size = s->insn->data >> 8;
2171 tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size);
2172 return NO_EXIT;
2175 static ExitStatus op_ipm(DisasContext *s, DisasOps *o)
2177 TCGv_i64 t1;
2179 gen_op_calc_cc(s);
2180 tcg_gen_andi_i64(o->out, o->out, ~0xff000000ull);
2182 t1 = tcg_temp_new_i64();
2183 tcg_gen_shli_i64(t1, psw_mask, 20);
2184 tcg_gen_shri_i64(t1, t1, 36);
2185 tcg_gen_or_i64(o->out, o->out, t1);
2187 tcg_gen_extu_i32_i64(t1, cc_op);
2188 tcg_gen_shli_i64(t1, t1, 28);
2189 tcg_gen_or_i64(o->out, o->out, t1);
2190 tcg_temp_free_i64(t1);
2191 return NO_EXIT;
2194 #ifndef CONFIG_USER_ONLY
2195 static ExitStatus op_ipte(DisasContext *s, DisasOps *o)
2197 check_privileged(s);
2198 gen_helper_ipte(cpu_env, o->in1, o->in2);
2199 return NO_EXIT;
2202 static ExitStatus op_iske(DisasContext *s, DisasOps *o)
2204 check_privileged(s);
2205 gen_helper_iske(o->out, cpu_env, o->in2);
2206 return NO_EXIT;
2208 #endif
2210 static ExitStatus op_ldeb(DisasContext *s, DisasOps *o)
2212 gen_helper_ldeb(o->out, cpu_env, o->in2);
2213 return NO_EXIT;
2216 static ExitStatus op_ledb(DisasContext *s, DisasOps *o)
2218 gen_helper_ledb(o->out, cpu_env, o->in2);
2219 return NO_EXIT;
2222 static ExitStatus op_ldxb(DisasContext *s, DisasOps *o)
2224 gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2);
2225 return NO_EXIT;
2228 static ExitStatus op_lexb(DisasContext *s, DisasOps *o)
2230 gen_helper_lexb(o->out, cpu_env, o->in1, o->in2);
2231 return NO_EXIT;
2234 static ExitStatus op_lxdb(DisasContext *s, DisasOps *o)
2236 gen_helper_lxdb(o->out, cpu_env, o->in2);
2237 return_low128(o->out2);
2238 return NO_EXIT;
2241 static ExitStatus op_lxeb(DisasContext *s, DisasOps *o)
2243 gen_helper_lxeb(o->out, cpu_env, o->in2);
2244 return_low128(o->out2);
2245 return NO_EXIT;
2248 static ExitStatus op_llgt(DisasContext *s, DisasOps *o)
2250 tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff);
2251 return NO_EXIT;
2254 static ExitStatus op_ld8s(DisasContext *s, DisasOps *o)
2256 tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s));
2257 return NO_EXIT;
2260 static ExitStatus op_ld8u(DisasContext *s, DisasOps *o)
2262 tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s));
2263 return NO_EXIT;
2266 static ExitStatus op_ld16s(DisasContext *s, DisasOps *o)
2268 tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s));
2269 return NO_EXIT;
2272 static ExitStatus op_ld16u(DisasContext *s, DisasOps *o)
2274 tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s));
2275 return NO_EXIT;
2278 static ExitStatus op_ld32s(DisasContext *s, DisasOps *o)
2280 tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s));
2281 return NO_EXIT;
2284 static ExitStatus op_ld32u(DisasContext *s, DisasOps *o)
2286 tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s));
2287 return NO_EXIT;
2290 static ExitStatus op_ld64(DisasContext *s, DisasOps *o)
2292 tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s));
2293 return NO_EXIT;
2296 static ExitStatus op_loc(DisasContext *s, DisasOps *o)
2298 DisasCompare c;
2300 disas_jcc(s, &c, get_field(s->fields, m3));
2302 if (c.is_64) {
2303 tcg_gen_movcond_i64(c.cond, o->out, c.u.s64.a, c.u.s64.b,
2304 o->in2, o->in1);
2305 free_compare(&c);
2306 } else {
2307 TCGv_i32 t32 = tcg_temp_new_i32();
2308 TCGv_i64 t, z;
2310 tcg_gen_setcond_i32(c.cond, t32, c.u.s32.a, c.u.s32.b);
2311 free_compare(&c);
2313 t = tcg_temp_new_i64();
2314 tcg_gen_extu_i32_i64(t, t32);
2315 tcg_temp_free_i32(t32);
2317 z = tcg_const_i64(0);
2318 tcg_gen_movcond_i64(TCG_COND_NE, o->out, t, z, o->in2, o->in1);
2319 tcg_temp_free_i64(t);
2320 tcg_temp_free_i64(z);
2323 return NO_EXIT;
2326 #ifndef CONFIG_USER_ONLY
2327 static ExitStatus op_lctl(DisasContext *s, DisasOps *o)
2329 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2330 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2331 check_privileged(s);
2332 potential_page_fault(s);
2333 gen_helper_lctl(cpu_env, r1, o->in2, r3);
2334 tcg_temp_free_i32(r1);
2335 tcg_temp_free_i32(r3);
2336 return NO_EXIT;
2339 static ExitStatus op_lctlg(DisasContext *s, DisasOps *o)
2341 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2342 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2343 check_privileged(s);
2344 potential_page_fault(s);
2345 gen_helper_lctlg(cpu_env, r1, o->in2, r3);
2346 tcg_temp_free_i32(r1);
2347 tcg_temp_free_i32(r3);
2348 return NO_EXIT;
2350 static ExitStatus op_lra(DisasContext *s, DisasOps *o)
2352 check_privileged(s);
2353 potential_page_fault(s);
2354 gen_helper_lra(o->out, cpu_env, o->in2);
2355 set_cc_static(s);
2356 return NO_EXIT;
2359 static ExitStatus op_lpsw(DisasContext *s, DisasOps *o)
2361 TCGv_i64 t1, t2;
2363 check_privileged(s);
2365 t1 = tcg_temp_new_i64();
2366 t2 = tcg_temp_new_i64();
2367 tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s));
2368 tcg_gen_addi_i64(o->in2, o->in2, 4);
2369 tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s));
2370 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2371 tcg_gen_shli_i64(t1, t1, 32);
2372 gen_helper_load_psw(cpu_env, t1, t2);
2373 tcg_temp_free_i64(t1);
2374 tcg_temp_free_i64(t2);
2375 return EXIT_NORETURN;
2378 static ExitStatus op_lpswe(DisasContext *s, DisasOps *o)
2380 TCGv_i64 t1, t2;
2382 check_privileged(s);
2384 t1 = tcg_temp_new_i64();
2385 t2 = tcg_temp_new_i64();
2386 tcg_gen_qemu_ld64(t1, o->in2, get_mem_index(s));
2387 tcg_gen_addi_i64(o->in2, o->in2, 8);
2388 tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s));
2389 gen_helper_load_psw(cpu_env, t1, t2);
2390 tcg_temp_free_i64(t1);
2391 tcg_temp_free_i64(t2);
2392 return EXIT_NORETURN;
2394 #endif
2396 static ExitStatus op_lam(DisasContext *s, DisasOps *o)
2398 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2399 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2400 potential_page_fault(s);
2401 gen_helper_lam(cpu_env, r1, o->in2, r3);
2402 tcg_temp_free_i32(r1);
2403 tcg_temp_free_i32(r3);
2404 return NO_EXIT;
2407 static ExitStatus op_lm32(DisasContext *s, DisasOps *o)
2409 int r1 = get_field(s->fields, r1);
2410 int r3 = get_field(s->fields, r3);
2411 TCGv_i64 t = tcg_temp_new_i64();
2412 TCGv_i64 t4 = tcg_const_i64(4);
2414 while (1) {
2415 tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
2416 store_reg32_i64(r1, t);
2417 if (r1 == r3) {
2418 break;
2420 tcg_gen_add_i64(o->in2, o->in2, t4);
2421 r1 = (r1 + 1) & 15;
2424 tcg_temp_free_i64(t);
2425 tcg_temp_free_i64(t4);
2426 return NO_EXIT;
2429 static ExitStatus op_lmh(DisasContext *s, DisasOps *o)
2431 int r1 = get_field(s->fields, r1);
2432 int r3 = get_field(s->fields, r3);
2433 TCGv_i64 t = tcg_temp_new_i64();
2434 TCGv_i64 t4 = tcg_const_i64(4);
2436 while (1) {
2437 tcg_gen_qemu_ld32u(t, o->in2, get_mem_index(s));
2438 store_reg32h_i64(r1, t);
2439 if (r1 == r3) {
2440 break;
2442 tcg_gen_add_i64(o->in2, o->in2, t4);
2443 r1 = (r1 + 1) & 15;
2446 tcg_temp_free_i64(t);
2447 tcg_temp_free_i64(t4);
2448 return NO_EXIT;
2451 static ExitStatus op_lm64(DisasContext *s, DisasOps *o)
2453 int r1 = get_field(s->fields, r1);
2454 int r3 = get_field(s->fields, r3);
2455 TCGv_i64 t8 = tcg_const_i64(8);
2457 while (1) {
2458 tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s));
2459 if (r1 == r3) {
2460 break;
2462 tcg_gen_add_i64(o->in2, o->in2, t8);
2463 r1 = (r1 + 1) & 15;
2466 tcg_temp_free_i64(t8);
2467 return NO_EXIT;
2470 static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
2472 o->out = o->in2;
2473 o->g_out = o->g_in2;
2474 TCGV_UNUSED_I64(o->in2);
2475 o->g_in2 = false;
2476 return NO_EXIT;
2479 static ExitStatus op_movx(DisasContext *s, DisasOps *o)
2481 o->out = o->in1;
2482 o->out2 = o->in2;
2483 o->g_out = o->g_in1;
2484 o->g_out2 = o->g_in2;
2485 TCGV_UNUSED_I64(o->in1);
2486 TCGV_UNUSED_I64(o->in2);
2487 o->g_in1 = o->g_in2 = false;
2488 return NO_EXIT;
2491 static ExitStatus op_mvc(DisasContext *s, DisasOps *o)
2493 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2494 potential_page_fault(s);
2495 gen_helper_mvc(cpu_env, l, o->addr1, o->in2);
2496 tcg_temp_free_i32(l);
2497 return NO_EXIT;
2500 static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
2502 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2503 TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2));
2504 potential_page_fault(s);
2505 gen_helper_mvcl(cc_op, cpu_env, r1, r2);
2506 tcg_temp_free_i32(r1);
2507 tcg_temp_free_i32(r2);
2508 set_cc_static(s);
2509 return NO_EXIT;
2512 static ExitStatus op_mvcle(DisasContext *s, DisasOps *o)
2514 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2515 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
2516 potential_page_fault(s);
2517 gen_helper_mvcle(cc_op, cpu_env, r1, o->in2, r3);
2518 tcg_temp_free_i32(r1);
2519 tcg_temp_free_i32(r3);
2520 set_cc_static(s);
2521 return NO_EXIT;
2524 #ifndef CONFIG_USER_ONLY
2525 static ExitStatus op_mvcp(DisasContext *s, DisasOps *o)
2527 int r1 = get_field(s->fields, l1);
2528 check_privileged(s);
2529 potential_page_fault(s);
2530 gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2531 set_cc_static(s);
2532 return NO_EXIT;
2535 static ExitStatus op_mvcs(DisasContext *s, DisasOps *o)
2537 int r1 = get_field(s->fields, l1);
2538 check_privileged(s);
2539 potential_page_fault(s);
2540 gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2);
2541 set_cc_static(s);
2542 return NO_EXIT;
2544 #endif
2546 static ExitStatus op_mvpg(DisasContext *s, DisasOps *o)
2548 potential_page_fault(s);
2549 gen_helper_mvpg(cpu_env, regs[0], o->in1, o->in2);
2550 set_cc_static(s);
2551 return NO_EXIT;
2554 static ExitStatus op_mvst(DisasContext *s, DisasOps *o)
2556 potential_page_fault(s);
2557 gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
2558 set_cc_static(s);
2559 return_low128(o->in2);
2560 return NO_EXIT;
2563 static ExitStatus op_mul(DisasContext *s, DisasOps *o)
2565 tcg_gen_mul_i64(o->out, o->in1, o->in2);
2566 return NO_EXIT;
2569 static ExitStatus op_mul128(DisasContext *s, DisasOps *o)
2571 tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2);
2572 return NO_EXIT;
2575 static ExitStatus op_meeb(DisasContext *s, DisasOps *o)
2577 gen_helper_meeb(o->out, cpu_env, o->in1, o->in2);
2578 return NO_EXIT;
2581 static ExitStatus op_mdeb(DisasContext *s, DisasOps *o)
2583 gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2);
2584 return NO_EXIT;
2587 static ExitStatus op_mdb(DisasContext *s, DisasOps *o)
2589 gen_helper_mdb(o->out, cpu_env, o->in1, o->in2);
2590 return NO_EXIT;
2593 static ExitStatus op_mxb(DisasContext *s, DisasOps *o)
2595 gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2596 return_low128(o->out2);
2597 return NO_EXIT;
2600 static ExitStatus op_mxdb(DisasContext *s, DisasOps *o)
2602 gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2);
2603 return_low128(o->out2);
2604 return NO_EXIT;
2607 static ExitStatus op_maeb(DisasContext *s, DisasOps *o)
2609 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2610 gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3);
2611 tcg_temp_free_i64(r3);
2612 return NO_EXIT;
2615 static ExitStatus op_madb(DisasContext *s, DisasOps *o)
2617 int r3 = get_field(s->fields, r3);
2618 gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2619 return NO_EXIT;
2622 static ExitStatus op_mseb(DisasContext *s, DisasOps *o)
2624 TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3));
2625 gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3);
2626 tcg_temp_free_i64(r3);
2627 return NO_EXIT;
2630 static ExitStatus op_msdb(DisasContext *s, DisasOps *o)
2632 int r3 = get_field(s->fields, r3);
2633 gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]);
2634 return NO_EXIT;
2637 static ExitStatus op_nabs(DisasContext *s, DisasOps *o)
2639 gen_helper_nabs_i64(o->out, o->in2);
2640 return NO_EXIT;
2643 static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o)
2645 tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull);
2646 return NO_EXIT;
2649 static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o)
2651 tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull);
2652 return NO_EXIT;
2655 static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o)
2657 tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull);
2658 tcg_gen_mov_i64(o->out2, o->in2);
2659 return NO_EXIT;
2662 static ExitStatus op_nc(DisasContext *s, DisasOps *o)
2664 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2665 potential_page_fault(s);
2666 gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2);
2667 tcg_temp_free_i32(l);
2668 set_cc_static(s);
2669 return NO_EXIT;
2672 static ExitStatus op_neg(DisasContext *s, DisasOps *o)
2674 tcg_gen_neg_i64(o->out, o->in2);
2675 return NO_EXIT;
2678 static ExitStatus op_negf32(DisasContext *s, DisasOps *o)
2680 tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull);
2681 return NO_EXIT;
2684 static ExitStatus op_negf64(DisasContext *s, DisasOps *o)
2686 tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull);
2687 return NO_EXIT;
2690 static ExitStatus op_negf128(DisasContext *s, DisasOps *o)
2692 tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull);
2693 tcg_gen_mov_i64(o->out2, o->in2);
2694 return NO_EXIT;
2697 static ExitStatus op_oc(DisasContext *s, DisasOps *o)
2699 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
2700 potential_page_fault(s);
2701 gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2);
2702 tcg_temp_free_i32(l);
2703 set_cc_static(s);
2704 return NO_EXIT;
2707 static ExitStatus op_or(DisasContext *s, DisasOps *o)
2709 tcg_gen_or_i64(o->out, o->in1, o->in2);
2710 return NO_EXIT;
2713 static ExitStatus op_ori(DisasContext *s, DisasOps *o)
2715 int shift = s->insn->data & 0xff;
2716 int size = s->insn->data >> 8;
2717 uint64_t mask = ((1ull << size) - 1) << shift;
2719 assert(!o->g_in2);
2720 tcg_gen_shli_i64(o->in2, o->in2, shift);
2721 tcg_gen_or_i64(o->out, o->in1, o->in2);
2723 /* Produce the CC from only the bits manipulated. */
2724 tcg_gen_andi_i64(cc_dst, o->out, mask);
2725 set_cc_nz_u64(s, cc_dst);
2726 return NO_EXIT;
2729 static ExitStatus op_popcnt(DisasContext *s, DisasOps *o)
2731 gen_helper_popcnt(o->out, o->in2);
2732 return NO_EXIT;
2735 #ifndef CONFIG_USER_ONLY
2736 static ExitStatus op_ptlb(DisasContext *s, DisasOps *o)
2738 check_privileged(s);
2739 gen_helper_ptlb(cpu_env);
2740 return NO_EXIT;
2742 #endif
2744 static ExitStatus op_risbg(DisasContext *s, DisasOps *o)
2746 int i3 = get_field(s->fields, i3);
2747 int i4 = get_field(s->fields, i4);
2748 int i5 = get_field(s->fields, i5);
2749 int do_zero = i4 & 0x80;
2750 uint64_t mask, imask, pmask;
2751 int pos, len, rot;
2753 /* Adjust the arguments for the specific insn. */
2754 switch (s->fields->op2) {
2755 case 0x55: /* risbg */
2756 i3 &= 63;
2757 i4 &= 63;
2758 pmask = ~0;
2759 break;
2760 case 0x5d: /* risbhg */
2761 i3 &= 31;
2762 i4 &= 31;
2763 pmask = 0xffffffff00000000ull;
2764 break;
2765 case 0x51: /* risblg */
2766 i3 &= 31;
2767 i4 &= 31;
2768 pmask = 0x00000000ffffffffull;
2769 break;
2770 default:
2771 abort();
2774 /* MASK is the set of bits to be inserted from R2.
2775 Take care for I3/I4 wraparound. */
2776 mask = pmask >> i3;
2777 if (i3 <= i4) {
2778 mask ^= pmask >> i4 >> 1;
2779 } else {
2780 mask |= ~(pmask >> i4 >> 1);
2782 mask &= pmask;
2784 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
2785 insns, we need to keep the other half of the register. */
2786 imask = ~mask | ~pmask;
2787 if (do_zero) {
2788 if (s->fields->op2 == 0x55) {
2789 imask = 0;
2790 } else {
2791 imask = ~pmask;
2795 /* In some cases we can implement this with deposit, which can be more
2796 efficient on some hosts. */
2797 if (~mask == imask && i3 <= i4) {
2798 if (s->fields->op2 == 0x5d) {
2799 i3 += 32, i4 += 32;
2801 /* Note that we rotate the bits to be inserted to the lsb, not to
2802 the position as described in the PoO. */
2803 len = i4 - i3 + 1;
2804 pos = 63 - i4;
2805 rot = (i5 - pos) & 63;
2806 } else {
2807 pos = len = -1;
2808 rot = i5 & 63;
2811 /* Rotate the input as necessary. */
2812 tcg_gen_rotli_i64(o->in2, o->in2, rot);
2814 /* Insert the selected bits into the output. */
2815 if (pos >= 0) {
2816 tcg_gen_deposit_i64(o->out, o->out, o->in2, pos, len);
2817 } else if (imask == 0) {
2818 tcg_gen_andi_i64(o->out, o->in2, mask);
2819 } else {
2820 tcg_gen_andi_i64(o->in2, o->in2, mask);
2821 tcg_gen_andi_i64(o->out, o->out, imask);
2822 tcg_gen_or_i64(o->out, o->out, o->in2);
2824 return NO_EXIT;
2827 static ExitStatus op_rosbg(DisasContext *s, DisasOps *o)
2829 int i3 = get_field(s->fields, i3);
2830 int i4 = get_field(s->fields, i4);
2831 int i5 = get_field(s->fields, i5);
2832 uint64_t mask;
2834 /* If this is a test-only form, arrange to discard the result. */
2835 if (i3 & 0x80) {
2836 o->out = tcg_temp_new_i64();
2837 o->g_out = false;
2840 i3 &= 63;
2841 i4 &= 63;
2842 i5 &= 63;
2844 /* MASK is the set of bits to be operated on from R2.
2845 Take care for I3/I4 wraparound. */
2846 mask = ~0ull >> i3;
2847 if (i3 <= i4) {
2848 mask ^= ~0ull >> i4 >> 1;
2849 } else {
2850 mask |= ~(~0ull >> i4 >> 1);
2853 /* Rotate the input as necessary. */
2854 tcg_gen_rotli_i64(o->in2, o->in2, i5);
2856 /* Operate. */
2857 switch (s->fields->op2) {
2858 case 0x55: /* AND */
2859 tcg_gen_ori_i64(o->in2, o->in2, ~mask);
2860 tcg_gen_and_i64(o->out, o->out, o->in2);
2861 break;
2862 case 0x56: /* OR */
2863 tcg_gen_andi_i64(o->in2, o->in2, mask);
2864 tcg_gen_or_i64(o->out, o->out, o->in2);
2865 break;
2866 case 0x57: /* XOR */
2867 tcg_gen_andi_i64(o->in2, o->in2, mask);
2868 tcg_gen_xor_i64(o->out, o->out, o->in2);
2869 break;
2870 default:
2871 abort();
2874 /* Set the CC. */
2875 tcg_gen_andi_i64(cc_dst, o->out, mask);
2876 set_cc_nz_u64(s, cc_dst);
2877 return NO_EXIT;
2880 static ExitStatus op_rev16(DisasContext *s, DisasOps *o)
2882 tcg_gen_bswap16_i64(o->out, o->in2);
2883 return NO_EXIT;
2886 static ExitStatus op_rev32(DisasContext *s, DisasOps *o)
2888 tcg_gen_bswap32_i64(o->out, o->in2);
2889 return NO_EXIT;
2892 static ExitStatus op_rev64(DisasContext *s, DisasOps *o)
2894 tcg_gen_bswap64_i64(o->out, o->in2);
2895 return NO_EXIT;
2898 static ExitStatus op_rll32(DisasContext *s, DisasOps *o)
2900 TCGv_i32 t1 = tcg_temp_new_i32();
2901 TCGv_i32 t2 = tcg_temp_new_i32();
2902 TCGv_i32 to = tcg_temp_new_i32();
2903 tcg_gen_trunc_i64_i32(t1, o->in1);
2904 tcg_gen_trunc_i64_i32(t2, o->in2);
2905 tcg_gen_rotl_i32(to, t1, t2);
2906 tcg_gen_extu_i32_i64(o->out, to);
2907 tcg_temp_free_i32(t1);
2908 tcg_temp_free_i32(t2);
2909 tcg_temp_free_i32(to);
2910 return NO_EXIT;
2913 static ExitStatus op_rll64(DisasContext *s, DisasOps *o)
2915 tcg_gen_rotl_i64(o->out, o->in1, o->in2);
2916 return NO_EXIT;
2919 #ifndef CONFIG_USER_ONLY
2920 static ExitStatus op_rrbe(DisasContext *s, DisasOps *o)
2922 check_privileged(s);
2923 gen_helper_rrbe(cc_op, cpu_env, o->in2);
2924 set_cc_static(s);
2925 return NO_EXIT;
2928 static ExitStatus op_sacf(DisasContext *s, DisasOps *o)
2930 check_privileged(s);
2931 gen_helper_sacf(cpu_env, o->in2);
2932 /* Addressing mode has changed, so end the block. */
2933 return EXIT_PC_STALE;
2935 #endif
2937 static ExitStatus op_sar(DisasContext *s, DisasOps *o)
2939 int r1 = get_field(s->fields, r1);
2940 tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1]));
2941 return NO_EXIT;
2944 static ExitStatus op_seb(DisasContext *s, DisasOps *o)
2946 gen_helper_seb(o->out, cpu_env, o->in1, o->in2);
2947 return NO_EXIT;
2950 static ExitStatus op_sdb(DisasContext *s, DisasOps *o)
2952 gen_helper_sdb(o->out, cpu_env, o->in1, o->in2);
2953 return NO_EXIT;
2956 static ExitStatus op_sxb(DisasContext *s, DisasOps *o)
2958 gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2);
2959 return_low128(o->out2);
2960 return NO_EXIT;
2963 static ExitStatus op_sqeb(DisasContext *s, DisasOps *o)
2965 gen_helper_sqeb(o->out, cpu_env, o->in2);
2966 return NO_EXIT;
2969 static ExitStatus op_sqdb(DisasContext *s, DisasOps *o)
2971 gen_helper_sqdb(o->out, cpu_env, o->in2);
2972 return NO_EXIT;
2975 static ExitStatus op_sqxb(DisasContext *s, DisasOps *o)
2977 gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2);
2978 return_low128(o->out2);
2979 return NO_EXIT;
2982 #ifndef CONFIG_USER_ONLY
2983 static ExitStatus op_servc(DisasContext *s, DisasOps *o)
2985 check_privileged(s);
2986 potential_page_fault(s);
2987 gen_helper_servc(cc_op, cpu_env, o->in2, o->in1);
2988 set_cc_static(s);
2989 return NO_EXIT;
2992 static ExitStatus op_sigp(DisasContext *s, DisasOps *o)
2994 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
2995 check_privileged(s);
2996 potential_page_fault(s);
2997 gen_helper_sigp(cc_op, cpu_env, o->in2, r1, o->in1);
2998 tcg_temp_free_i32(r1);
2999 return NO_EXIT;
3001 #endif
3003 static ExitStatus op_soc(DisasContext *s, DisasOps *o)
3005 DisasCompare c;
3006 TCGv_i64 a;
3007 int lab, r1;
3009 disas_jcc(s, &c, get_field(s->fields, m3));
3011 lab = gen_new_label();
3012 if (c.is_64) {
3013 tcg_gen_brcond_i64(c.cond, c.u.s64.a, c.u.s64.b, lab);
3014 } else {
3015 tcg_gen_brcond_i32(c.cond, c.u.s32.a, c.u.s32.b, lab);
3017 free_compare(&c);
3019 r1 = get_field(s->fields, r1);
3020 a = get_address(s, 0, get_field(s->fields, b2), get_field(s->fields, d2));
3021 if (s->insn->data) {
3022 tcg_gen_qemu_st64(regs[r1], a, get_mem_index(s));
3023 } else {
3024 tcg_gen_qemu_st32(regs[r1], a, get_mem_index(s));
3026 tcg_temp_free_i64(a);
3028 gen_set_label(lab);
3029 return NO_EXIT;
3032 static ExitStatus op_sla(DisasContext *s, DisasOps *o)
3034 uint64_t sign = 1ull << s->insn->data;
3035 enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64;
3036 gen_op_update2_cc_i64(s, cco, o->in1, o->in2);
3037 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3038 /* The arithmetic left shift is curious in that it does not affect
3039 the sign bit. Copy that over from the source unchanged. */
3040 tcg_gen_andi_i64(o->out, o->out, ~sign);
3041 tcg_gen_andi_i64(o->in1, o->in1, sign);
3042 tcg_gen_or_i64(o->out, o->out, o->in1);
3043 return NO_EXIT;
3046 static ExitStatus op_sll(DisasContext *s, DisasOps *o)
3048 tcg_gen_shl_i64(o->out, o->in1, o->in2);
3049 return NO_EXIT;
3052 static ExitStatus op_sra(DisasContext *s, DisasOps *o)
3054 tcg_gen_sar_i64(o->out, o->in1, o->in2);
3055 return NO_EXIT;
3058 static ExitStatus op_srl(DisasContext *s, DisasOps *o)
3060 tcg_gen_shr_i64(o->out, o->in1, o->in2);
3061 return NO_EXIT;
3064 static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
3066 gen_helper_sfpc(cpu_env, o->in2);
3067 return NO_EXIT;
3070 static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
3072 gen_helper_sfas(cpu_env, o->in2);
3073 return NO_EXIT;
3076 static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
3078 int b2 = get_field(s->fields, b2);
3079 int d2 = get_field(s->fields, d2);
3080 TCGv_i64 t1 = tcg_temp_new_i64();
3081 TCGv_i64 t2 = tcg_temp_new_i64();
3082 int mask, pos, len;
3084 switch (s->fields->op2) {
3085 case 0x99: /* SRNM */
3086 pos = 0, len = 2;
3087 break;
3088 case 0xb8: /* SRNMB */
3089 pos = 0, len = 3;
3090 break;
3091 case 0xb9: /* SRNMT */
3092 pos = 4, len = 3;
3093 break;
3094 default:
3095 tcg_abort();
3097 mask = (1 << len) - 1;
3099 /* Insert the value into the appropriate field of the FPC. */
3100 if (b2 == 0) {
3101 tcg_gen_movi_i64(t1, d2 & mask);
3102 } else {
3103 tcg_gen_addi_i64(t1, regs[b2], d2);
3104 tcg_gen_andi_i64(t1, t1, mask);
3106 tcg_gen_ld32u_i64(t2, cpu_env, offsetof(CPUS390XState, fpc));
3107 tcg_gen_deposit_i64(t2, t2, t1, pos, len);
3108 tcg_temp_free_i64(t1);
3110 /* Then install the new FPC to set the rounding mode in fpu_status. */
3111 gen_helper_sfpc(cpu_env, t2);
3112 tcg_temp_free_i64(t2);
3113 return NO_EXIT;
3116 #ifndef CONFIG_USER_ONLY
3117 static ExitStatus op_spka(DisasContext *s, DisasOps *o)
3119 check_privileged(s);
3120 tcg_gen_shri_i64(o->in2, o->in2, 4);
3121 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY - 4, 4);
3122 return NO_EXIT;
3125 static ExitStatus op_sske(DisasContext *s, DisasOps *o)
3127 check_privileged(s);
3128 gen_helper_sske(cpu_env, o->in1, o->in2);
3129 return NO_EXIT;
3132 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
3134 check_privileged(s);
3135 tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
3136 return NO_EXIT;
3139 static ExitStatus op_stap(DisasContext *s, DisasOps *o)
3141 check_privileged(s);
3142 /* ??? Surely cpu address != cpu number. In any case the previous
3143 version of this stored more than the required half-word, so it
3144 is unlikely this has ever been tested. */
3145 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
3146 return NO_EXIT;
3149 static ExitStatus op_stck(DisasContext *s, DisasOps *o)
3151 gen_helper_stck(o->out, cpu_env);
3152 /* ??? We don't implement clock states. */
3153 gen_op_movi_cc(s, 0);
3154 return NO_EXIT;
3157 static ExitStatus op_stcke(DisasContext *s, DisasOps *o)
3159 TCGv_i64 c1 = tcg_temp_new_i64();
3160 TCGv_i64 c2 = tcg_temp_new_i64();
3161 gen_helper_stck(c1, cpu_env);
3162 /* Shift the 64-bit value into its place as a zero-extended
3163 104-bit value. Note that "bit positions 64-103 are always
3164 non-zero so that they compare differently to STCK"; we set
3165 the least significant bit to 1. */
3166 tcg_gen_shli_i64(c2, c1, 56);
3167 tcg_gen_shri_i64(c1, c1, 8);
3168 tcg_gen_ori_i64(c2, c2, 0x10000);
3169 tcg_gen_qemu_st64(c1, o->in2, get_mem_index(s));
3170 tcg_gen_addi_i64(o->in2, o->in2, 8);
3171 tcg_gen_qemu_st64(c2, o->in2, get_mem_index(s));
3172 tcg_temp_free_i64(c1);
3173 tcg_temp_free_i64(c2);
3174 /* ??? We don't implement clock states. */
3175 gen_op_movi_cc(s, 0);
3176 return NO_EXIT;
3179 static ExitStatus op_sckc(DisasContext *s, DisasOps *o)
3181 check_privileged(s);
3182 gen_helper_sckc(cpu_env, o->in2);
3183 return NO_EXIT;
3186 static ExitStatus op_stckc(DisasContext *s, DisasOps *o)
3188 check_privileged(s);
3189 gen_helper_stckc(o->out, cpu_env);
3190 return NO_EXIT;
3193 static ExitStatus op_stctg(DisasContext *s, DisasOps *o)
3195 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3196 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3197 check_privileged(s);
3198 potential_page_fault(s);
3199 gen_helper_stctg(cpu_env, r1, o->in2, r3);
3200 tcg_temp_free_i32(r1);
3201 tcg_temp_free_i32(r3);
3202 return NO_EXIT;
3205 static ExitStatus op_stctl(DisasContext *s, DisasOps *o)
3207 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3208 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3209 check_privileged(s);
3210 potential_page_fault(s);
3211 gen_helper_stctl(cpu_env, r1, o->in2, r3);
3212 tcg_temp_free_i32(r1);
3213 tcg_temp_free_i32(r3);
3214 return NO_EXIT;
3217 static ExitStatus op_stidp(DisasContext *s, DisasOps *o)
3219 check_privileged(s);
3220 tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num));
3221 return NO_EXIT;
3224 static ExitStatus op_spt(DisasContext *s, DisasOps *o)
3226 check_privileged(s);
3227 gen_helper_spt(cpu_env, o->in2);
3228 return NO_EXIT;
3231 static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
3233 TCGv_i64 f, a;
3234 /* We really ought to have more complete indication of facilities
3235 that we implement. Address this when STFLE is implemented. */
3236 check_privileged(s);
3237 f = tcg_const_i64(0xc0000000);
3238 a = tcg_const_i64(200);
3239 tcg_gen_qemu_st32(f, a, get_mem_index(s));
3240 tcg_temp_free_i64(f);
3241 tcg_temp_free_i64(a);
3242 return NO_EXIT;
3245 static ExitStatus op_stpt(DisasContext *s, DisasOps *o)
3247 check_privileged(s);
3248 gen_helper_stpt(o->out, cpu_env);
3249 return NO_EXIT;
3252 static ExitStatus op_stsi(DisasContext *s, DisasOps *o)
3254 check_privileged(s);
3255 potential_page_fault(s);
3256 gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]);
3257 set_cc_static(s);
3258 return NO_EXIT;
3261 static ExitStatus op_spx(DisasContext *s, DisasOps *o)
3263 check_privileged(s);
3264 gen_helper_spx(cpu_env, o->in2);
3265 return NO_EXIT;
3268 static ExitStatus op_subchannel(DisasContext *s, DisasOps *o)
3270 check_privileged(s);
3271 /* Not operational. */
3272 gen_op_movi_cc(s, 3);
3273 return NO_EXIT;
3276 static ExitStatus op_stpx(DisasContext *s, DisasOps *o)
3278 check_privileged(s);
3279 tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa));
3280 tcg_gen_andi_i64(o->out, o->out, 0x7fffe000);
3281 return NO_EXIT;
3284 static ExitStatus op_stnosm(DisasContext *s, DisasOps *o)
3286 uint64_t i2 = get_field(s->fields, i2);
3287 TCGv_i64 t;
3289 check_privileged(s);
3291 /* It is important to do what the instruction name says: STORE THEN.
3292 If we let the output hook perform the store then if we fault and
3293 restart, we'll have the wrong SYSTEM MASK in place. */
3294 t = tcg_temp_new_i64();
3295 tcg_gen_shri_i64(t, psw_mask, 56);
3296 tcg_gen_qemu_st8(t, o->addr1, get_mem_index(s));
3297 tcg_temp_free_i64(t);
3299 if (s->fields->op == 0xac) {
3300 tcg_gen_andi_i64(psw_mask, psw_mask,
3301 (i2 << 56) | 0x00ffffffffffffffull);
3302 } else {
3303 tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
3305 return NO_EXIT;
3308 static ExitStatus op_stura(DisasContext *s, DisasOps *o)
3310 check_privileged(s);
3311 potential_page_fault(s);
3312 gen_helper_stura(cpu_env, o->in2, o->in1);
3313 return NO_EXIT;
3315 #endif
3317 static ExitStatus op_st8(DisasContext *s, DisasOps *o)
3319 tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s));
3320 return NO_EXIT;
3323 static ExitStatus op_st16(DisasContext *s, DisasOps *o)
3325 tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s));
3326 return NO_EXIT;
3329 static ExitStatus op_st32(DisasContext *s, DisasOps *o)
3331 tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s));
3332 return NO_EXIT;
3335 static ExitStatus op_st64(DisasContext *s, DisasOps *o)
3337 tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s));
3338 return NO_EXIT;
3341 static ExitStatus op_stam(DisasContext *s, DisasOps *o)
3343 TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
3344 TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3));
3345 potential_page_fault(s);
3346 gen_helper_stam(cpu_env, r1, o->in2, r3);
3347 tcg_temp_free_i32(r1);
3348 tcg_temp_free_i32(r3);
3349 return NO_EXIT;
3352 static ExitStatus op_stcm(DisasContext *s, DisasOps *o)
3354 int m3 = get_field(s->fields, m3);
3355 int pos, base = s->insn->data;
3356 TCGv_i64 tmp = tcg_temp_new_i64();
3358 pos = base + ctz32(m3) * 8;
3359 switch (m3) {
3360 case 0xf:
3361 /* Effectively a 32-bit store. */
3362 tcg_gen_shri_i64(tmp, o->in1, pos);
3363 tcg_gen_qemu_st32(tmp, o->in2, get_mem_index(s));
3364 break;
3366 case 0xc:
3367 case 0x6:
3368 case 0x3:
3369 /* Effectively a 16-bit store. */
3370 tcg_gen_shri_i64(tmp, o->in1, pos);
3371 tcg_gen_qemu_st16(tmp, o->in2, get_mem_index(s));
3372 break;
3374 case 0x8:
3375 case 0x4:
3376 case 0x2:
3377 case 0x1:
3378 /* Effectively an 8-bit store. */
3379 tcg_gen_shri_i64(tmp, o->in1, pos);
3380 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3381 break;
3383 default:
3384 /* This is going to be a sequence of shifts and stores. */
3385 pos = base + 32 - 8;
3386 while (m3) {
3387 if (m3 & 0x8) {
3388 tcg_gen_shri_i64(tmp, o->in1, pos);
3389 tcg_gen_qemu_st8(tmp, o->in2, get_mem_index(s));
3390 tcg_gen_addi_i64(o->in2, o->in2, 1);
3392 m3 = (m3 << 1) & 0xf;
3393 pos -= 8;
3395 break;
3397 tcg_temp_free_i64(tmp);
3398 return NO_EXIT;
3401 static ExitStatus op_stm(DisasContext *s, DisasOps *o)
3403 int r1 = get_field(s->fields, r1);
3404 int r3 = get_field(s->fields, r3);
3405 int size = s->insn->data;
3406 TCGv_i64 tsize = tcg_const_i64(size);
3408 while (1) {
3409 if (size == 8) {
3410 tcg_gen_qemu_st64(regs[r1], o->in2, get_mem_index(s));
3411 } else {
3412 tcg_gen_qemu_st32(regs[r1], o->in2, get_mem_index(s));
3414 if (r1 == r3) {
3415 break;
3417 tcg_gen_add_i64(o->in2, o->in2, tsize);
3418 r1 = (r1 + 1) & 15;
3421 tcg_temp_free_i64(tsize);
3422 return NO_EXIT;
3425 static ExitStatus op_stmh(DisasContext *s, DisasOps *o)
3427 int r1 = get_field(s->fields, r1);
3428 int r3 = get_field(s->fields, r3);
3429 TCGv_i64 t = tcg_temp_new_i64();
3430 TCGv_i64 t4 = tcg_const_i64(4);
3431 TCGv_i64 t32 = tcg_const_i64(32);
3433 while (1) {
3434 tcg_gen_shl_i64(t, regs[r1], t32);
3435 tcg_gen_qemu_st32(t, o->in2, get_mem_index(s));
3436 if (r1 == r3) {
3437 break;
3439 tcg_gen_add_i64(o->in2, o->in2, t4);
3440 r1 = (r1 + 1) & 15;
3443 tcg_temp_free_i64(t);
3444 tcg_temp_free_i64(t4);
3445 tcg_temp_free_i64(t32);
3446 return NO_EXIT;
3449 static ExitStatus op_srst(DisasContext *s, DisasOps *o)
3451 potential_page_fault(s);
3452 gen_helper_srst(o->in1, cpu_env, regs[0], o->in1, o->in2);
3453 set_cc_static(s);
3454 return_low128(o->in2);
3455 return NO_EXIT;
3458 static ExitStatus op_sub(DisasContext *s, DisasOps *o)
3460 tcg_gen_sub_i64(o->out, o->in1, o->in2);
3461 return NO_EXIT;
3464 static ExitStatus op_subb(DisasContext *s, DisasOps *o)
3466 DisasCompare cmp;
3467 TCGv_i64 borrow;
3469 tcg_gen_sub_i64(o->out, o->in1, o->in2);
3471 /* The !borrow flag is the msb of CC. Since we want the inverse of
3472 that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
3473 disas_jcc(s, &cmp, 8 | 4);
3474 borrow = tcg_temp_new_i64();
3475 if (cmp.is_64) {
3476 tcg_gen_setcond_i64(cmp.cond, borrow, cmp.u.s64.a, cmp.u.s64.b);
3477 } else {
3478 TCGv_i32 t = tcg_temp_new_i32();
3479 tcg_gen_setcond_i32(cmp.cond, t, cmp.u.s32.a, cmp.u.s32.b);
3480 tcg_gen_extu_i32_i64(borrow, t);
3481 tcg_temp_free_i32(t);
3483 free_compare(&cmp);
3485 tcg_gen_sub_i64(o->out, o->out, borrow);
3486 tcg_temp_free_i64(borrow);
3487 return NO_EXIT;
3490 static ExitStatus op_svc(DisasContext *s, DisasOps *o)
3492 TCGv_i32 t;
3494 update_psw_addr(s);
3495 update_cc_op(s);
3497 t = tcg_const_i32(get_field(s->fields, i1) & 0xff);
3498 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_code));
3499 tcg_temp_free_i32(t);
3501 t = tcg_const_i32(s->next_pc - s->pc);
3502 tcg_gen_st_i32(t, cpu_env, offsetof(CPUS390XState, int_svc_ilen));
3503 tcg_temp_free_i32(t);
3505 gen_exception(EXCP_SVC);
3506 return EXIT_NORETURN;
3509 static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
3511 gen_helper_tceb(cc_op, o->in1, o->in2);
3512 set_cc_static(s);
3513 return NO_EXIT;
3516 static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
3518 gen_helper_tcdb(cc_op, o->in1, o->in2);
3519 set_cc_static(s);
3520 return NO_EXIT;
3523 static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
3525 gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
3526 set_cc_static(s);
3527 return NO_EXIT;
3530 #ifndef CONFIG_USER_ONLY
3531 static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
3533 potential_page_fault(s);
3534 gen_helper_tprot(cc_op, o->addr1, o->in2);
3535 set_cc_static(s);
3536 return NO_EXIT;
3538 #endif
3540 static ExitStatus op_tr(DisasContext *s, DisasOps *o)
3542 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3543 potential_page_fault(s);
3544 gen_helper_tr(cpu_env, l, o->addr1, o->in2);
3545 tcg_temp_free_i32(l);
3546 set_cc_static(s);
3547 return NO_EXIT;
3550 static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
3552 TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
3553 potential_page_fault(s);
3554 gen_helper_unpk(cpu_env, l, o->addr1, o->in2);
3555 tcg_temp_free_i32(l);
3556 return NO_EXIT;
3559 static ExitStatus op_xc(DisasContext *s, DisasOps *o)
3561 int d1 = get_field(s->fields, d1);
3562 int d2 = get_field(s->fields, d2);
3563 int b1 = get_field(s->fields, b1);
3564 int b2 = get_field(s->fields, b2);
3565 int l = get_field(s->fields, l1);
3566 TCGv_i32 t32;
3568 o->addr1 = get_address(s, 0, b1, d1);
3570 /* If the addresses are identical, this is a store/memset of zero. */
3571 if (b1 == b2 && d1 == d2 && (l + 1) <= 32) {
3572 o->in2 = tcg_const_i64(0);
3574 l++;
3575 while (l >= 8) {
3576 tcg_gen_qemu_st64(o->in2, o->addr1, get_mem_index(s));
3577 l -= 8;
3578 if (l > 0) {
3579 tcg_gen_addi_i64(o->addr1, o->addr1, 8);
3582 if (l >= 4) {
3583 tcg_gen_qemu_st32(o->in2, o->addr1, get_mem_index(s));
3584 l -= 4;
3585 if (l > 0) {
3586 tcg_gen_addi_i64(o->addr1, o->addr1, 4);
3589 if (l >= 2) {
3590 tcg_gen_qemu_st16(o->in2, o->addr1, get_mem_index(s));
3591 l -= 2;
3592 if (l > 0) {
3593 tcg_gen_addi_i64(o->addr1, o->addr1, 2);
3596 if (l) {
3597 tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s));
3599 gen_op_movi_cc(s, 0);
3600 return NO_EXIT;
3603 /* But in general we'll defer to a helper. */
3604 o->in2 = get_address(s, 0, b2, d2);
3605 t32 = tcg_const_i32(l);
3606 potential_page_fault(s);
3607 gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2);
3608 tcg_temp_free_i32(t32);
3609 set_cc_static(s);
3610 return NO_EXIT;
3613 static ExitStatus op_xor(DisasContext *s, DisasOps *o)
3615 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3616 return NO_EXIT;
3619 static ExitStatus op_xori(DisasContext *s, DisasOps *o)
3621 int shift = s->insn->data & 0xff;
3622 int size = s->insn->data >> 8;
3623 uint64_t mask = ((1ull << size) - 1) << shift;
3625 assert(!o->g_in2);
3626 tcg_gen_shli_i64(o->in2, o->in2, shift);
3627 tcg_gen_xor_i64(o->out, o->in1, o->in2);
3629 /* Produce the CC from only the bits manipulated. */
3630 tcg_gen_andi_i64(cc_dst, o->out, mask);
3631 set_cc_nz_u64(s, cc_dst);
3632 return NO_EXIT;
3635 static ExitStatus op_zero(DisasContext *s, DisasOps *o)
3637 o->out = tcg_const_i64(0);
3638 return NO_EXIT;
3641 static ExitStatus op_zero2(DisasContext *s, DisasOps *o)
3643 o->out = tcg_const_i64(0);
3644 o->out2 = o->out;
3645 o->g_out2 = true;
3646 return NO_EXIT;
3649 /* ====================================================================== */
3650 /* The "Cc OUTput" generators. Given the generated output (and in some cases
3651 the original inputs), update the various cc data structures in order to
3652 be able to compute the new condition code. */
3654 static void cout_abs32(DisasContext *s, DisasOps *o)
3656 gen_op_update1_cc_i64(s, CC_OP_ABS_32, o->out);
3659 static void cout_abs64(DisasContext *s, DisasOps *o)
3661 gen_op_update1_cc_i64(s, CC_OP_ABS_64, o->out);
3664 static void cout_adds32(DisasContext *s, DisasOps *o)
3666 gen_op_update3_cc_i64(s, CC_OP_ADD_32, o->in1, o->in2, o->out);
3669 static void cout_adds64(DisasContext *s, DisasOps *o)
3671 gen_op_update3_cc_i64(s, CC_OP_ADD_64, o->in1, o->in2, o->out);
3674 static void cout_addu32(DisasContext *s, DisasOps *o)
3676 gen_op_update3_cc_i64(s, CC_OP_ADDU_32, o->in1, o->in2, o->out);
3679 static void cout_addu64(DisasContext *s, DisasOps *o)
3681 gen_op_update3_cc_i64(s, CC_OP_ADDU_64, o->in1, o->in2, o->out);
3684 static void cout_addc32(DisasContext *s, DisasOps *o)
3686 gen_op_update3_cc_i64(s, CC_OP_ADDC_32, o->in1, o->in2, o->out);
3689 static void cout_addc64(DisasContext *s, DisasOps *o)
3691 gen_op_update3_cc_i64(s, CC_OP_ADDC_64, o->in1, o->in2, o->out);
3694 static void cout_cmps32(DisasContext *s, DisasOps *o)
3696 gen_op_update2_cc_i64(s, CC_OP_LTGT_32, o->in1, o->in2);
3699 static void cout_cmps64(DisasContext *s, DisasOps *o)
3701 gen_op_update2_cc_i64(s, CC_OP_LTGT_64, o->in1, o->in2);
3704 static void cout_cmpu32(DisasContext *s, DisasOps *o)
3706 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_32, o->in1, o->in2);
3709 static void cout_cmpu64(DisasContext *s, DisasOps *o)
3711 gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, o->in1, o->in2);
3714 static void cout_f32(DisasContext *s, DisasOps *o)
3716 gen_op_update1_cc_i64(s, CC_OP_NZ_F32, o->out);
3719 static void cout_f64(DisasContext *s, DisasOps *o)
3721 gen_op_update1_cc_i64(s, CC_OP_NZ_F64, o->out);
3724 static void cout_f128(DisasContext *s, DisasOps *o)
3726 gen_op_update2_cc_i64(s, CC_OP_NZ_F128, o->out, o->out2);
3729 static void cout_nabs32(DisasContext *s, DisasOps *o)
3731 gen_op_update1_cc_i64(s, CC_OP_NABS_32, o->out);
3734 static void cout_nabs64(DisasContext *s, DisasOps *o)
3736 gen_op_update1_cc_i64(s, CC_OP_NABS_64, o->out);
3739 static void cout_neg32(DisasContext *s, DisasOps *o)
3741 gen_op_update1_cc_i64(s, CC_OP_COMP_32, o->out);
3744 static void cout_neg64(DisasContext *s, DisasOps *o)
3746 gen_op_update1_cc_i64(s, CC_OP_COMP_64, o->out);
3749 static void cout_nz32(DisasContext *s, DisasOps *o)
3751 tcg_gen_ext32u_i64(cc_dst, o->out);
3752 gen_op_update1_cc_i64(s, CC_OP_NZ, cc_dst);
3755 static void cout_nz64(DisasContext *s, DisasOps *o)
3757 gen_op_update1_cc_i64(s, CC_OP_NZ, o->out);
3760 static void cout_s32(DisasContext *s, DisasOps *o)
3762 gen_op_update1_cc_i64(s, CC_OP_LTGT0_32, o->out);
3765 static void cout_s64(DisasContext *s, DisasOps *o)
3767 gen_op_update1_cc_i64(s, CC_OP_LTGT0_64, o->out);
3770 static void cout_subs32(DisasContext *s, DisasOps *o)
3772 gen_op_update3_cc_i64(s, CC_OP_SUB_32, o->in1, o->in2, o->out);
3775 static void cout_subs64(DisasContext *s, DisasOps *o)
3777 gen_op_update3_cc_i64(s, CC_OP_SUB_64, o->in1, o->in2, o->out);
3780 static void cout_subu32(DisasContext *s, DisasOps *o)
3782 gen_op_update3_cc_i64(s, CC_OP_SUBU_32, o->in1, o->in2, o->out);
3785 static void cout_subu64(DisasContext *s, DisasOps *o)
3787 gen_op_update3_cc_i64(s, CC_OP_SUBU_64, o->in1, o->in2, o->out);
3790 static void cout_subb32(DisasContext *s, DisasOps *o)
3792 gen_op_update3_cc_i64(s, CC_OP_SUBB_32, o->in1, o->in2, o->out);
3795 static void cout_subb64(DisasContext *s, DisasOps *o)
3797 gen_op_update3_cc_i64(s, CC_OP_SUBB_64, o->in1, o->in2, o->out);
3800 static void cout_tm32(DisasContext *s, DisasOps *o)
3802 gen_op_update2_cc_i64(s, CC_OP_TM_32, o->in1, o->in2);
3805 static void cout_tm64(DisasContext *s, DisasOps *o)
3807 gen_op_update2_cc_i64(s, CC_OP_TM_64, o->in1, o->in2);
3810 /* ====================================================================== */
3811 /* The "PREParation" generators. These initialize the DisasOps.OUT fields
3812 with the TCG register to which we will write. Used in combination with
3813 the "wout" generators, in some cases we need a new temporary, and in
3814 some cases we can write to a TCG global. */
3816 static void prep_new(DisasContext *s, DisasFields *f, DisasOps *o)
3818 o->out = tcg_temp_new_i64();
3820 #define SPEC_prep_new 0
3822 static void prep_new_P(DisasContext *s, DisasFields *f, DisasOps *o)
3824 o->out = tcg_temp_new_i64();
3825 o->out2 = tcg_temp_new_i64();
3827 #define SPEC_prep_new_P 0
3829 static void prep_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3831 o->out = regs[get_field(f, r1)];
3832 o->g_out = true;
3834 #define SPEC_prep_r1 0
3836 static void prep_r1_P(DisasContext *s, DisasFields *f, DisasOps *o)
3838 int r1 = get_field(f, r1);
3839 o->out = regs[r1];
3840 o->out2 = regs[r1 + 1];
3841 o->g_out = o->g_out2 = true;
3843 #define SPEC_prep_r1_P SPEC_r1_even
3845 static void prep_f1(DisasContext *s, DisasFields *f, DisasOps *o)
3847 o->out = fregs[get_field(f, r1)];
3848 o->g_out = true;
3850 #define SPEC_prep_f1 0
3852 static void prep_x1(DisasContext *s, DisasFields *f, DisasOps *o)
3854 int r1 = get_field(f, r1);
3855 o->out = fregs[r1];
3856 o->out2 = fregs[r1 + 2];
3857 o->g_out = o->g_out2 = true;
3859 #define SPEC_prep_x1 SPEC_r1_f128
3861 /* ====================================================================== */
3862 /* The "Write OUTput" generators. These generally perform some non-trivial
3863 copy of data to TCG globals, or to main memory. The trivial cases are
3864 generally handled by having a "prep" generator install the TCG global
3865 as the destination of the operation. */
3867 static void wout_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3869 store_reg(get_field(f, r1), o->out);
3871 #define SPEC_wout_r1 0
3873 static void wout_r1_8(DisasContext *s, DisasFields *f, DisasOps *o)
3875 int r1 = get_field(f, r1);
3876 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 8);
3878 #define SPEC_wout_r1_8 0
3880 static void wout_r1_16(DisasContext *s, DisasFields *f, DisasOps *o)
3882 int r1 = get_field(f, r1);
3883 tcg_gen_deposit_i64(regs[r1], regs[r1], o->out, 0, 16);
3885 #define SPEC_wout_r1_16 0
3887 static void wout_r1_32(DisasContext *s, DisasFields *f, DisasOps *o)
3889 store_reg32_i64(get_field(f, r1), o->out);
3891 #define SPEC_wout_r1_32 0
3893 static void wout_r1_P32(DisasContext *s, DisasFields *f, DisasOps *o)
3895 int r1 = get_field(f, r1);
3896 store_reg32_i64(r1, o->out);
3897 store_reg32_i64(r1 + 1, o->out2);
3899 #define SPEC_wout_r1_P32 SPEC_r1_even
3901 static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
3903 int r1 = get_field(f, r1);
3904 store_reg32_i64(r1 + 1, o->out);
3905 tcg_gen_shri_i64(o->out, o->out, 32);
3906 store_reg32_i64(r1, o->out);
3908 #define SPEC_wout_r1_D32 SPEC_r1_even
3910 static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
3912 store_freg32_i64(get_field(f, r1), o->out);
3914 #define SPEC_wout_e1 0
3916 static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
3918 store_freg(get_field(f, r1), o->out);
3920 #define SPEC_wout_f1 0
3922 static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
3924 int f1 = get_field(s->fields, r1);
3925 store_freg(f1, o->out);
3926 store_freg(f1 + 2, o->out2);
3928 #define SPEC_wout_x1 SPEC_r1_f128
3930 static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
3932 if (get_field(f, r1) != get_field(f, r2)) {
3933 store_reg32_i64(get_field(f, r1), o->out);
3936 #define SPEC_wout_cond_r1r2_32 0
3938 static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
3940 if (get_field(f, r1) != get_field(f, r2)) {
3941 store_freg32_i64(get_field(f, r1), o->out);
3944 #define SPEC_wout_cond_e1e2 0
3946 static void wout_m1_8(DisasContext *s, DisasFields *f, DisasOps *o)
3948 tcg_gen_qemu_st8(o->out, o->addr1, get_mem_index(s));
3950 #define SPEC_wout_m1_8 0
3952 static void wout_m1_16(DisasContext *s, DisasFields *f, DisasOps *o)
3954 tcg_gen_qemu_st16(o->out, o->addr1, get_mem_index(s));
3956 #define SPEC_wout_m1_16 0
3958 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
3960 tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
3962 #define SPEC_wout_m1_32 0
3964 static void wout_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
3966 tcg_gen_qemu_st64(o->out, o->addr1, get_mem_index(s));
3968 #define SPEC_wout_m1_64 0
3970 static void wout_m2_32(DisasContext *s, DisasFields *f, DisasOps *o)
3972 tcg_gen_qemu_st32(o->out, o->in2, get_mem_index(s));
3974 #define SPEC_wout_m2_32 0
3976 /* ====================================================================== */
3977 /* The "INput 1" generators. These load the first operand to an insn. */
3979 static void in1_r1(DisasContext *s, DisasFields *f, DisasOps *o)
3981 o->in1 = load_reg(get_field(f, r1));
3983 #define SPEC_in1_r1 0
3985 static void in1_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
3987 o->in1 = regs[get_field(f, r1)];
3988 o->g_in1 = true;
3990 #define SPEC_in1_r1_o 0
3992 static void in1_r1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
3994 o->in1 = tcg_temp_new_i64();
3995 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1)]);
3997 #define SPEC_in1_r1_32s 0
3999 static void in1_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4001 o->in1 = tcg_temp_new_i64();
4002 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1)]);
4004 #define SPEC_in1_r1_32u 0
4006 static void in1_r1_sr32(DisasContext *s, DisasFields *f, DisasOps *o)
4008 o->in1 = tcg_temp_new_i64();
4009 tcg_gen_shri_i64(o->in1, regs[get_field(f, r1)], 32);
4011 #define SPEC_in1_r1_sr32 0
4013 static void in1_r1p1(DisasContext *s, DisasFields *f, DisasOps *o)
4015 o->in1 = load_reg(get_field(f, r1) + 1);
4017 #define SPEC_in1_r1p1 SPEC_r1_even
4019 static void in1_r1p1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4021 o->in1 = tcg_temp_new_i64();
4022 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r1) + 1]);
4024 #define SPEC_in1_r1p1_32s SPEC_r1_even
4026 static void in1_r1p1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4028 o->in1 = tcg_temp_new_i64();
4029 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r1) + 1]);
4031 #define SPEC_in1_r1p1_32u SPEC_r1_even
4033 static void in1_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4035 int r1 = get_field(f, r1);
4036 o->in1 = tcg_temp_new_i64();
4037 tcg_gen_concat32_i64(o->in1, regs[r1 + 1], regs[r1]);
4039 #define SPEC_in1_r1_D32 SPEC_r1_even
4041 static void in1_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4043 o->in1 = load_reg(get_field(f, r2));
4045 #define SPEC_in1_r2 0
4047 static void in1_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4049 o->in1 = load_reg(get_field(f, r3));
4051 #define SPEC_in1_r3 0
4053 static void in1_r3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4055 o->in1 = regs[get_field(f, r3)];
4056 o->g_in1 = true;
4058 #define SPEC_in1_r3_o 0
4060 static void in1_r3_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4062 o->in1 = tcg_temp_new_i64();
4063 tcg_gen_ext32s_i64(o->in1, regs[get_field(f, r3)]);
4065 #define SPEC_in1_r3_32s 0
4067 static void in1_r3_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4069 o->in1 = tcg_temp_new_i64();
4070 tcg_gen_ext32u_i64(o->in1, regs[get_field(f, r3)]);
4072 #define SPEC_in1_r3_32u 0
4074 static void in1_r3_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4076 int r3 = get_field(f, r3);
4077 o->in1 = tcg_temp_new_i64();
4078 tcg_gen_concat32_i64(o->in1, regs[r3 + 1], regs[r3]);
4080 #define SPEC_in1_r3_D32 SPEC_r3_even
4082 static void in1_e1(DisasContext *s, DisasFields *f, DisasOps *o)
4084 o->in1 = load_freg32_i64(get_field(f, r1));
4086 #define SPEC_in1_e1 0
4088 static void in1_f1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4090 o->in1 = fregs[get_field(f, r1)];
4091 o->g_in1 = true;
4093 #define SPEC_in1_f1_o 0
4095 static void in1_x1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4097 int r1 = get_field(f, r1);
4098 o->out = fregs[r1];
4099 o->out2 = fregs[r1 + 2];
4100 o->g_out = o->g_out2 = true;
4102 #define SPEC_in1_x1_o SPEC_r1_f128
4104 static void in1_f3_o(DisasContext *s, DisasFields *f, DisasOps *o)
4106 o->in1 = fregs[get_field(f, r3)];
4107 o->g_in1 = true;
4109 #define SPEC_in1_f3_o 0
4111 static void in1_la1(DisasContext *s, DisasFields *f, DisasOps *o)
4113 o->addr1 = get_address(s, 0, get_field(f, b1), get_field(f, d1));
4115 #define SPEC_in1_la1 0
4117 static void in1_la2(DisasContext *s, DisasFields *f, DisasOps *o)
4119 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4120 o->addr1 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4122 #define SPEC_in1_la2 0
4124 static void in1_m1_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4126 in1_la1(s, f, o);
4127 o->in1 = tcg_temp_new_i64();
4128 tcg_gen_qemu_ld8u(o->in1, o->addr1, get_mem_index(s));
4130 #define SPEC_in1_m1_8u 0
4132 static void in1_m1_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4134 in1_la1(s, f, o);
4135 o->in1 = tcg_temp_new_i64();
4136 tcg_gen_qemu_ld16s(o->in1, o->addr1, get_mem_index(s));
4138 #define SPEC_in1_m1_16s 0
4140 static void in1_m1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4142 in1_la1(s, f, o);
4143 o->in1 = tcg_temp_new_i64();
4144 tcg_gen_qemu_ld16u(o->in1, o->addr1, get_mem_index(s));
4146 #define SPEC_in1_m1_16u 0
4148 static void in1_m1_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4150 in1_la1(s, f, o);
4151 o->in1 = tcg_temp_new_i64();
4152 tcg_gen_qemu_ld32s(o->in1, o->addr1, get_mem_index(s));
4154 #define SPEC_in1_m1_32s 0
4156 static void in1_m1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4158 in1_la1(s, f, o);
4159 o->in1 = tcg_temp_new_i64();
4160 tcg_gen_qemu_ld32u(o->in1, o->addr1, get_mem_index(s));
4162 #define SPEC_in1_m1_32u 0
4164 static void in1_m1_64(DisasContext *s, DisasFields *f, DisasOps *o)
4166 in1_la1(s, f, o);
4167 o->in1 = tcg_temp_new_i64();
4168 tcg_gen_qemu_ld64(o->in1, o->addr1, get_mem_index(s));
4170 #define SPEC_in1_m1_64 0
4172 /* ====================================================================== */
4173 /* The "INput 2" generators. These load the second operand to an insn. */
4175 static void in2_r1_o(DisasContext *s, DisasFields *f, DisasOps *o)
4177 o->in2 = regs[get_field(f, r1)];
4178 o->g_in2 = true;
4180 #define SPEC_in2_r1_o 0
4182 static void in2_r1_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4184 o->in2 = tcg_temp_new_i64();
4185 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r1)]);
4187 #define SPEC_in2_r1_16u 0
4189 static void in2_r1_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4191 o->in2 = tcg_temp_new_i64();
4192 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r1)]);
4194 #define SPEC_in2_r1_32u 0
4196 static void in2_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
4198 int r1 = get_field(f, r1);
4199 o->in2 = tcg_temp_new_i64();
4200 tcg_gen_concat32_i64(o->in2, regs[r1 + 1], regs[r1]);
4202 #define SPEC_in2_r1_D32 SPEC_r1_even
4204 static void in2_r2(DisasContext *s, DisasFields *f, DisasOps *o)
4206 o->in2 = load_reg(get_field(f, r2));
4208 #define SPEC_in2_r2 0
4210 static void in2_r2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4212 o->in2 = regs[get_field(f, r2)];
4213 o->g_in2 = true;
4215 #define SPEC_in2_r2_o 0
4217 static void in2_r2_nz(DisasContext *s, DisasFields *f, DisasOps *o)
4219 int r2 = get_field(f, r2);
4220 if (r2 != 0) {
4221 o->in2 = load_reg(r2);
4224 #define SPEC_in2_r2_nz 0
4226 static void in2_r2_8s(DisasContext *s, DisasFields *f, DisasOps *o)
4228 o->in2 = tcg_temp_new_i64();
4229 tcg_gen_ext8s_i64(o->in2, regs[get_field(f, r2)]);
4231 #define SPEC_in2_r2_8s 0
4233 static void in2_r2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4235 o->in2 = tcg_temp_new_i64();
4236 tcg_gen_ext8u_i64(o->in2, regs[get_field(f, r2)]);
4238 #define SPEC_in2_r2_8u 0
4240 static void in2_r2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4242 o->in2 = tcg_temp_new_i64();
4243 tcg_gen_ext16s_i64(o->in2, regs[get_field(f, r2)]);
4245 #define SPEC_in2_r2_16s 0
4247 static void in2_r2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4249 o->in2 = tcg_temp_new_i64();
4250 tcg_gen_ext16u_i64(o->in2, regs[get_field(f, r2)]);
4252 #define SPEC_in2_r2_16u 0
4254 static void in2_r3(DisasContext *s, DisasFields *f, DisasOps *o)
4256 o->in2 = load_reg(get_field(f, r3));
4258 #define SPEC_in2_r3 0
4260 static void in2_r2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4262 o->in2 = tcg_temp_new_i64();
4263 tcg_gen_ext32s_i64(o->in2, regs[get_field(f, r2)]);
4265 #define SPEC_in2_r2_32s 0
4267 static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4269 o->in2 = tcg_temp_new_i64();
4270 tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
4272 #define SPEC_in2_r2_32u 0
4274 static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
4276 o->in2 = load_freg32_i64(get_field(f, r2));
4278 #define SPEC_in2_e2 0
4280 static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4282 o->in2 = fregs[get_field(f, r2)];
4283 o->g_in2 = true;
4285 #define SPEC_in2_f2_o 0
4287 static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
4289 int r2 = get_field(f, r2);
4290 o->in1 = fregs[r2];
4291 o->in2 = fregs[r2 + 2];
4292 o->g_in1 = o->g_in2 = true;
4294 #define SPEC_in2_x2_o SPEC_r2_f128
4296 static void in2_ra2(DisasContext *s, DisasFields *f, DisasOps *o)
4298 o->in2 = get_address(s, 0, get_field(f, r2), 0);
4300 #define SPEC_in2_ra2 0
4302 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
4304 int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
4305 o->in2 = get_address(s, x2, get_field(f, b2), get_field(f, d2));
4307 #define SPEC_in2_a2 0
4309 static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o)
4311 o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2);
4313 #define SPEC_in2_ri2 0
4315 static void in2_sh32(DisasContext *s, DisasFields *f, DisasOps *o)
4317 help_l2_shift(s, f, o, 31);
4319 #define SPEC_in2_sh32 0
4321 static void in2_sh64(DisasContext *s, DisasFields *f, DisasOps *o)
4323 help_l2_shift(s, f, o, 63);
4325 #define SPEC_in2_sh64 0
4327 static void in2_m2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4329 in2_a2(s, f, o);
4330 tcg_gen_qemu_ld8u(o->in2, o->in2, get_mem_index(s));
4332 #define SPEC_in2_m2_8u 0
4334 static void in2_m2_16s(DisasContext *s, DisasFields *f, DisasOps *o)
4336 in2_a2(s, f, o);
4337 tcg_gen_qemu_ld16s(o->in2, o->in2, get_mem_index(s));
4339 #define SPEC_in2_m2_16s 0
4341 static void in2_m2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4343 in2_a2(s, f, o);
4344 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4346 #define SPEC_in2_m2_16u 0
4348 static void in2_m2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4350 in2_a2(s, f, o);
4351 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4353 #define SPEC_in2_m2_32s 0
4355 static void in2_m2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4357 in2_a2(s, f, o);
4358 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4360 #define SPEC_in2_m2_32u 0
4362 static void in2_m2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4364 in2_a2(s, f, o);
4365 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4367 #define SPEC_in2_m2_64 0
4369 static void in2_mri2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4371 in2_ri2(s, f, o);
4372 tcg_gen_qemu_ld16u(o->in2, o->in2, get_mem_index(s));
4374 #define SPEC_in2_mri2_16u 0
4376 static void in2_mri2_32s(DisasContext *s, DisasFields *f, DisasOps *o)
4378 in2_ri2(s, f, o);
4379 tcg_gen_qemu_ld32s(o->in2, o->in2, get_mem_index(s));
4381 #define SPEC_in2_mri2_32s 0
4383 static void in2_mri2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4385 in2_ri2(s, f, o);
4386 tcg_gen_qemu_ld32u(o->in2, o->in2, get_mem_index(s));
4388 #define SPEC_in2_mri2_32u 0
4390 static void in2_mri2_64(DisasContext *s, DisasFields *f, DisasOps *o)
4392 in2_ri2(s, f, o);
4393 tcg_gen_qemu_ld64(o->in2, o->in2, get_mem_index(s));
4395 #define SPEC_in2_mri2_64 0
4397 static void in2_i2(DisasContext *s, DisasFields *f, DisasOps *o)
4399 o->in2 = tcg_const_i64(get_field(f, i2));
4401 #define SPEC_in2_i2 0
4403 static void in2_i2_8u(DisasContext *s, DisasFields *f, DisasOps *o)
4405 o->in2 = tcg_const_i64((uint8_t)get_field(f, i2));
4407 #define SPEC_in2_i2_8u 0
4409 static void in2_i2_16u(DisasContext *s, DisasFields *f, DisasOps *o)
4411 o->in2 = tcg_const_i64((uint16_t)get_field(f, i2));
4413 #define SPEC_in2_i2_16u 0
4415 static void in2_i2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
4417 o->in2 = tcg_const_i64((uint32_t)get_field(f, i2));
4419 #define SPEC_in2_i2_32u 0
4421 static void in2_i2_16u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4423 uint64_t i2 = (uint16_t)get_field(f, i2);
4424 o->in2 = tcg_const_i64(i2 << s->insn->data);
4426 #define SPEC_in2_i2_16u_shl 0
4428 static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
4430 uint64_t i2 = (uint32_t)get_field(f, i2);
4431 o->in2 = tcg_const_i64(i2 << s->insn->data);
4433 #define SPEC_in2_i2_32u_shl 0
4435 /* ====================================================================== */
4437 /* Find opc within the table of insns. This is formulated as a switch
4438 statement so that (1) we get compile-time notice of cut-paste errors
4439 for duplicated opcodes, and (2) the compiler generates the binary
4440 search tree, rather than us having to post-process the table. */
4442 #define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
4443 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
4445 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
4447 enum DisasInsnEnum {
4448 #include "insn-data.def"
4451 #undef D
4452 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4453 .opc = OPC, \
4454 .fmt = FMT_##FT, \
4455 .fac = FAC_##FC, \
4456 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
4457 .name = #NM, \
4458 .help_in1 = in1_##I1, \
4459 .help_in2 = in2_##I2, \
4460 .help_prep = prep_##P, \
4461 .help_wout = wout_##W, \
4462 .help_cout = cout_##CC, \
4463 .help_op = op_##OP, \
4464 .data = D \
4467 /* Allow 0 to be used for NULL in the table below. */
4468 #define in1_0 NULL
4469 #define in2_0 NULL
4470 #define prep_0 NULL
4471 #define wout_0 NULL
4472 #define cout_0 NULL
4473 #define op_0 NULL
4475 #define SPEC_in1_0 0
4476 #define SPEC_in2_0 0
4477 #define SPEC_prep_0 0
4478 #define SPEC_wout_0 0
4480 static const DisasInsn insn_info[] = {
4481 #include "insn-data.def"
4484 #undef D
4485 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
4486 case OPC: return &insn_info[insn_ ## NM];
4488 static const DisasInsn *lookup_opc(uint16_t opc)
4490 switch (opc) {
4491 #include "insn-data.def"
4492 default:
4493 return NULL;
4497 #undef D
4498 #undef C
4500 /* Extract a field from the insn. The INSN should be left-aligned in
4501 the uint64_t so that we can more easily utilize the big-bit-endian
4502 definitions we extract from the Principals of Operation. */
4504 static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn)
4506 uint32_t r, m;
4508 if (f->size == 0) {
4509 return;
4512 /* Zero extract the field from the insn. */
4513 r = (insn << f->beg) >> (64 - f->size);
4515 /* Sign-extend, or un-swap the field as necessary. */
4516 switch (f->type) {
4517 case 0: /* unsigned */
4518 break;
4519 case 1: /* signed */
4520 assert(f->size <= 32);
4521 m = 1u << (f->size - 1);
4522 r = (r ^ m) - m;
4523 break;
4524 case 2: /* dl+dh split, signed 20 bit. */
4525 r = ((int8_t)r << 12) | (r >> 8);
4526 break;
4527 default:
4528 abort();
4531 /* Validate that the "compressed" encoding we selected above is valid.
4532 I.e. we havn't make two different original fields overlap. */
4533 assert(((o->presentC >> f->indexC) & 1) == 0);
4534 o->presentC |= 1 << f->indexC;
4535 o->presentO |= 1 << f->indexO;
4537 o->c[f->indexC] = r;
4540 /* Lookup the insn at the current PC, extracting the operands into O and
4541 returning the info struct for the insn. Returns NULL for invalid insn. */
4543 static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s,
4544 DisasFields *f)
4546 uint64_t insn, pc = s->pc;
4547 int op, op2, ilen;
4548 const DisasInsn *info;
4550 insn = ld_code2(env, pc);
4551 op = (insn >> 8) & 0xff;
4552 ilen = get_ilen(op);
4553 s->next_pc = s->pc + ilen;
4555 switch (ilen) {
4556 case 2:
4557 insn = insn << 48;
4558 break;
4559 case 4:
4560 insn = ld_code4(env, pc) << 32;
4561 break;
4562 case 6:
4563 insn = (insn << 48) | (ld_code4(env, pc + 2) << 16);
4564 break;
4565 default:
4566 abort();
4569 /* We can't actually determine the insn format until we've looked up
4570 the full insn opcode. Which we can't do without locating the
4571 secondary opcode. Assume by default that OP2 is at bit 40; for
4572 those smaller insns that don't actually have a secondary opcode
4573 this will correctly result in OP2 = 0. */
4574 switch (op) {
4575 case 0x01: /* E */
4576 case 0x80: /* S */
4577 case 0x82: /* S */
4578 case 0x93: /* S */
4579 case 0xb2: /* S, RRF, RRE */
4580 case 0xb3: /* RRE, RRD, RRF */
4581 case 0xb9: /* RRE, RRF */
4582 case 0xe5: /* SSE, SIL */
4583 op2 = (insn << 8) >> 56;
4584 break;
4585 case 0xa5: /* RI */
4586 case 0xa7: /* RI */
4587 case 0xc0: /* RIL */
4588 case 0xc2: /* RIL */
4589 case 0xc4: /* RIL */
4590 case 0xc6: /* RIL */
4591 case 0xc8: /* SSF */
4592 case 0xcc: /* RIL */
4593 op2 = (insn << 12) >> 60;
4594 break;
4595 case 0xd0 ... 0xdf: /* SS */
4596 case 0xe1: /* SS */
4597 case 0xe2: /* SS */
4598 case 0xe8: /* SS */
4599 case 0xe9: /* SS */
4600 case 0xea: /* SS */
4601 case 0xee ... 0xf3: /* SS */
4602 case 0xf8 ... 0xfd: /* SS */
4603 op2 = 0;
4604 break;
4605 default:
4606 op2 = (insn << 40) >> 56;
4607 break;
4610 memset(f, 0, sizeof(*f));
4611 f->op = op;
4612 f->op2 = op2;
4614 /* Lookup the instruction. */
4615 info = lookup_opc(op << 8 | op2);
4617 /* If we found it, extract the operands. */
4618 if (info != NULL) {
4619 DisasFormat fmt = info->fmt;
4620 int i;
4622 for (i = 0; i < NUM_C_FIELD; ++i) {
4623 extract_field(f, &format_info[fmt].op[i], insn);
4626 return info;
4629 static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
4631 const DisasInsn *insn;
4632 ExitStatus ret = NO_EXIT;
4633 DisasFields f;
4634 DisasOps o;
4636 /* Search for the insn in the table. */
4637 insn = extract_insn(env, s, &f);
4639 /* Not found means unimplemented/illegal opcode. */
4640 if (insn == NULL) {
4641 qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n",
4642 f.op, f.op2);
4643 gen_illegal_opcode(s);
4644 return EXIT_NORETURN;
4647 /* Check for insn specification exceptions. */
4648 if (insn->spec) {
4649 int spec = insn->spec, excp = 0, r;
4651 if (spec & SPEC_r1_even) {
4652 r = get_field(&f, r1);
4653 if (r & 1) {
4654 excp = PGM_SPECIFICATION;
4657 if (spec & SPEC_r2_even) {
4658 r = get_field(&f, r2);
4659 if (r & 1) {
4660 excp = PGM_SPECIFICATION;
4663 if (spec & SPEC_r3_even) {
4664 r = get_field(&f, r3);
4665 if (r & 1) {
4666 excp = PGM_SPECIFICATION;
4669 if (spec & SPEC_r1_f128) {
4670 r = get_field(&f, r1);
4671 if (r > 13) {
4672 excp = PGM_SPECIFICATION;
4675 if (spec & SPEC_r2_f128) {
4676 r = get_field(&f, r2);
4677 if (r > 13) {
4678 excp = PGM_SPECIFICATION;
4681 if (excp) {
4682 gen_program_exception(s, excp);
4683 return EXIT_NORETURN;
4687 /* Set up the strutures we use to communicate with the helpers. */
4688 s->insn = insn;
4689 s->fields = &f;
4690 o.g_out = o.g_out2 = o.g_in1 = o.g_in2 = false;
4691 TCGV_UNUSED_I64(o.out);
4692 TCGV_UNUSED_I64(o.out2);
4693 TCGV_UNUSED_I64(o.in1);
4694 TCGV_UNUSED_I64(o.in2);
4695 TCGV_UNUSED_I64(o.addr1);
4697 /* Implement the instruction. */
4698 if (insn->help_in1) {
4699 insn->help_in1(s, &f, &o);
4701 if (insn->help_in2) {
4702 insn->help_in2(s, &f, &o);
4704 if (insn->help_prep) {
4705 insn->help_prep(s, &f, &o);
4707 if (insn->help_op) {
4708 ret = insn->help_op(s, &o);
4710 if (insn->help_wout) {
4711 insn->help_wout(s, &f, &o);
4713 if (insn->help_cout) {
4714 insn->help_cout(s, &o);
4717 /* Free any temporaries created by the helpers. */
4718 if (!TCGV_IS_UNUSED_I64(o.out) && !o.g_out) {
4719 tcg_temp_free_i64(o.out);
4721 if (!TCGV_IS_UNUSED_I64(o.out2) && !o.g_out2) {
4722 tcg_temp_free_i64(o.out2);
4724 if (!TCGV_IS_UNUSED_I64(o.in1) && !o.g_in1) {
4725 tcg_temp_free_i64(o.in1);
4727 if (!TCGV_IS_UNUSED_I64(o.in2) && !o.g_in2) {
4728 tcg_temp_free_i64(o.in2);
4730 if (!TCGV_IS_UNUSED_I64(o.addr1)) {
4731 tcg_temp_free_i64(o.addr1);
4734 /* Advance to the next instruction. */
4735 s->pc = s->next_pc;
4736 return ret;
4739 static inline void gen_intermediate_code_internal(S390CPU *cpu,
4740 TranslationBlock *tb,
4741 bool search_pc)
4743 CPUState *cs = CPU(cpu);
4744 CPUS390XState *env = &cpu->env;
4745 DisasContext dc;
4746 target_ulong pc_start;
4747 uint64_t next_page_start;
4748 uint16_t *gen_opc_end;
4749 int j, lj = -1;
4750 int num_insns, max_insns;
4751 CPUBreakpoint *bp;
4752 ExitStatus status;
4753 bool do_debug;
4755 pc_start = tb->pc;
4757 /* 31-bit mode */
4758 if (!(tb->flags & FLAG_MASK_64)) {
4759 pc_start &= 0x7fffffff;
4762 dc.tb = tb;
4763 dc.pc = pc_start;
4764 dc.cc_op = CC_OP_DYNAMIC;
4765 do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
4767 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
4769 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
4771 num_insns = 0;
4772 max_insns = tb->cflags & CF_COUNT_MASK;
4773 if (max_insns == 0) {
4774 max_insns = CF_COUNT_MASK;
4777 gen_tb_start();
4779 do {
4780 if (search_pc) {
4781 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
4782 if (lj < j) {
4783 lj++;
4784 while (lj < j) {
4785 tcg_ctx.gen_opc_instr_start[lj++] = 0;
4788 tcg_ctx.gen_opc_pc[lj] = dc.pc;
4789 gen_opc_cc_op[lj] = dc.cc_op;
4790 tcg_ctx.gen_opc_instr_start[lj] = 1;
4791 tcg_ctx.gen_opc_icount[lj] = num_insns;
4793 if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
4794 gen_io_start();
4797 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
4798 tcg_gen_debug_insn_start(dc.pc);
4801 status = NO_EXIT;
4802 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
4803 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
4804 if (bp->pc == dc.pc) {
4805 status = EXIT_PC_STALE;
4806 do_debug = true;
4807 break;
4811 if (status == NO_EXIT) {
4812 status = translate_one(env, &dc);
4815 /* If we reach a page boundary, are single stepping,
4816 or exhaust instruction count, stop generation. */
4817 if (status == NO_EXIT
4818 && (dc.pc >= next_page_start
4819 || tcg_ctx.gen_opc_ptr >= gen_opc_end
4820 || num_insns >= max_insns
4821 || singlestep
4822 || cs->singlestep_enabled)) {
4823 status = EXIT_PC_STALE;
4825 } while (status == NO_EXIT);
4827 if (tb->cflags & CF_LAST_IO) {
4828 gen_io_end();
4831 switch (status) {
4832 case EXIT_GOTO_TB:
4833 case EXIT_NORETURN:
4834 break;
4835 case EXIT_PC_STALE:
4836 update_psw_addr(&dc);
4837 /* FALLTHRU */
4838 case EXIT_PC_UPDATED:
4839 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
4840 cc op type is in env */
4841 update_cc_op(&dc);
4842 /* Exit the TB, either by raising a debug exception or by return. */
4843 if (do_debug) {
4844 gen_exception(EXCP_DEBUG);
4845 } else {
4846 tcg_gen_exit_tb(0);
4848 break;
4849 default:
4850 abort();
4853 gen_tb_end(tb, num_insns);
4854 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
4855 if (search_pc) {
4856 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
4857 lj++;
4858 while (lj <= j) {
4859 tcg_ctx.gen_opc_instr_start[lj++] = 0;
4861 } else {
4862 tb->size = dc.pc - pc_start;
4863 tb->icount = num_insns;
4866 #if defined(S390X_DEBUG_DISAS)
4867 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
4868 qemu_log("IN: %s\n", lookup_symbol(pc_start));
4869 log_target_disas(env, pc_start, dc.pc - pc_start, 1);
4870 qemu_log("\n");
4872 #endif
4875 void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
4877 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
4880 void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
4882 gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
4885 void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
4887 int cc_op;
4888 env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
4889 cc_op = gen_opc_cc_op[pc_pos];
4890 if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
4891 env->cc_op = cc_op;