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__)
28 # define LOG_DISAS(...) do { } while (0)
32 #include "disas/disas.h"
35 #include "qemu/host-utils.h"
37 /* global register indexes */
38 static TCGv_ptr cpu_env
;
40 #include "exec/gen-icount.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
;
52 struct TranslationBlock
*tb
;
53 const DisasInsn
*insn
;
57 bool singlestep_enabled
;
60 /* Information carried about a condition to be evaluated. */
67 struct { TCGv_i64 a
, b
; } s64
;
68 struct { TCGv_i32 a
, b
; } s32
;
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
];
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;
89 void s390_cpu_dump_state(CPUState
*cs
, FILE *f
, fprintf_function cpu_fprintf
,
92 S390CPU
*cpu
= S390_CPU(cs
);
93 CPUS390XState
*env
= &cpu
->env
;
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
));
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
]);
107 cpu_fprintf(f
, "\n");
113 for (i
= 0; i
< 16; i
++) {
114 cpu_fprintf(f
, "F%02d=%016" PRIx64
, i
, env
->fregs
[i
].ll
);
116 cpu_fprintf(f
, "\n");
122 #ifndef CONFIG_USER_ONLY
123 for (i
= 0; i
< 16; i
++) {
124 cpu_fprintf(f
, "C%02d=%016" PRIx64
, i
, env
->cregs
[i
]);
126 cpu_fprintf(f
, "\n");
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
]);
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)
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
),
165 psw_mask
= tcg_global_mem_new_i64(TCG_AREG0
,
166 offsetof(CPUS390XState
, psw
.mask
),
169 cc_op
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUS390XState
, cc_op
),
171 cc_src
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, cc_src
),
173 cc_dst
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, cc_dst
),
175 cc_vr
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, 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
]),
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 */
197 static TCGv_i64
load_reg(int reg
)
199 TCGv_i64 r
= tcg_temp_new_i64();
200 tcg_gen_mov_i64(r
, regs
[reg
]);
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);
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
)
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
)
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:
281 case PSW_ASC_SECONDARY
>> 32:
283 case PSW_ASC_HOME
>> 32:
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
)
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. */
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. */
344 tcg_gen_add_i64(tmp
, regs
[b2
], regs
[x2
]);
345 tcg_gen_addi_i64(tmp
, tmp
, d2
);
347 tcg_gen_addi_i64(tmp
, regs
[b2
], d2
);
349 tcg_gen_addi_i64(tmp
, regs
[x2
], d2
);
355 tcg_gen_movi_i64(tmp
, d2
);
358 tcg_gen_andi_i64(tmp
, tmp
, 0x7fffffff);
364 static inline bool live_cc_data(DisasContext
*s
)
366 return (s
->cc_op
!= CC_OP_DYNAMIC
367 && s
->cc_op
!= CC_OP_STATIC
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
);
391 static void gen_op_update2_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 src
,
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
);
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
);
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
;
448 TCGV_UNUSED_I32(local_cc_op
);
449 TCGV_UNUSED_I64(dummy
);
452 dummy
= tcg_const_i64(0);
466 local_cc_op
= tcg_const_i32(s
->cc_op
);
482 /* s->cc_op is the cc value */
483 tcg_gen_movi_i32(cc_op
, s
->cc_op
- CC_OP_CONST0
);
486 /* env->cc_op already is the cc value */
501 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, dummy
, cc_dst
, dummy
);
506 case CC_OP_LTUGTU_32
:
507 case CC_OP_LTUGTU_64
:
514 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, dummy
);
529 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, cc_vr
);
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
);
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 */
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
]++;
566 static void account_inline_branch(DisasContext
*s
, int cc_op
)
568 #ifdef DEBUG_INLINE_BRANCHES
569 inline_branch_hit
[cc_op
]++;
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
)
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
);
610 c
->g1
= c
->g2
= true;
615 /* Find the TCG condition for the mask + cc op. */
621 cond
= ltgt_cond
[mask
];
622 if (cond
== TCG_COND_NEVER
) {
625 account_inline_branch(s
, old_cc_op
);
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
) {
634 account_inline_branch(s
, old_cc_op
);
638 cond
= nz_cond
[mask
];
639 if (cond
== TCG_COND_NEVER
) {
642 account_inline_branch(s
, old_cc_op
);
657 account_inline_branch(s
, old_cc_op
);
672 account_inline_branch(s
, old_cc_op
);
676 switch (mask
& 0xa) {
677 case 8: /* src == 0 -> no one bit found */
680 case 2: /* src != 0 -> one bit found */
686 account_inline_branch(s
, old_cc_op
);
692 case 8 | 2: /* vr == 0 */
695 case 4 | 1: /* vr != 0 */
698 case 8 | 4: /* no carry -> vr >= src */
701 case 2 | 1: /* carry -> vr < src */
707 account_inline_branch(s
, old_cc_op
);
712 /* Note that CC=0 is impossible; treat it as dont-care. */
714 case 2: /* zero -> op1 == op2 */
717 case 4 | 1: /* !zero -> op1 != op2 */
720 case 4: /* borrow (!carry) -> op1 < op2 */
723 case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
729 account_inline_branch(s
, old_cc_op
);
734 /* Calculate cc value. */
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
;
747 /* Load up the arguments of the comparison. */
749 c
->g1
= c
->g2
= 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);
758 case CC_OP_LTUGTU_32
:
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
);
771 c
->u
.s64
.b
= tcg_const_i64(0);
775 case CC_OP_LTUGTU_64
:
779 c
->g1
= c
->g2
= true;
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
);
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);
798 tcg_gen_trunc_i64_i32(c
->u
.s32
.b
, cc_src
);
805 if (cond
== TCG_COND_EQ
|| cond
== TCG_COND_NE
) {
806 c
->u
.s64
.b
= tcg_const_i64(0);
818 case 0x8 | 0x4 | 0x2: /* cc != 3 */
820 c
->u
.s32
.b
= tcg_const_i32(3);
822 case 0x8 | 0x4 | 0x1: /* cc != 2 */
824 c
->u
.s32
.b
= tcg_const_i32(2);
826 case 0x8 | 0x2 | 0x1: /* cc != 1 */
828 c
->u
.s32
.b
= tcg_const_i32(1);
830 case 0x8 | 0x2: /* cc == 0 ||Â cc == 2 => (cc & 1) == 0 */
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);
837 case 0x8 | 0x4: /* cc < 2 */
839 c
->u
.s32
.b
= tcg_const_i32(2);
841 case 0x8: /* cc == 0 */
843 c
->u
.s32
.b
= tcg_const_i32(0);
845 case 0x4 | 0x2 | 0x1: /* cc != 0 */
847 c
->u
.s32
.b
= tcg_const_i32(0);
849 case 0x4 | 0x1: /* cc == 1 ||Â cc == 3 => (cc & 1) != 0 */
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);
856 case 0x4: /* cc == 1 */
858 c
->u
.s32
.b
= tcg_const_i32(1);
860 case 0x2 | 0x1: /* cc > 1 */
862 c
->u
.s32
.b
= tcg_const_i32(1);
864 case 0x2: /* cc == 2 */
866 c
->u
.s32
.b
= tcg_const_i32(2);
868 case 0x1: /* cc == 3 */
870 c
->u
.s32
.b
= tcg_const_i32(3);
873 /* CC is masked by something else: (8 >> cc) & mask. */
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
);
890 static void free_compare(DisasCompare
*c
)
894 tcg_temp_free_i64(c
->u
.s64
.a
);
896 tcg_temp_free_i32(c
->u
.s32
.a
);
901 tcg_temp_free_i64(c
->u
.s64
.b
);
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)
918 #include "insn-format.def"
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
{
957 enum DisasFieldIndexC
{
991 unsigned presentC
:16;
992 unsigned int presentO
;
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
));
1012 /* Describe the layout of each field in each format. */
1013 typedef struct DisasField
{
1015 unsigned int size
:8;
1016 unsigned int type
:2;
1017 unsigned int indexC
:6;
1018 enum DisasFieldIndexO indexO
:8;
1021 typedef struct DisasFormatInfo
{
1022 DisasField op
[NUM_C_FIELD
];
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"
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. */
1070 bool g_out
, g_out2
, g_in1
, g_in2
;
1071 TCGv_i64 out
, out2
, in1
, in2
;
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. */
1089 /* Continue the TB. */
1091 /* We have emitted one or more goto_tb. No fixup required. */
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
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. */
1100 /* We are ending the TB with a noreturn function call, e.g. longjmp.
1101 No following code will be executed. */
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 */
1131 DisasFacility fac
:8;
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
*);
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
);
1156 o
->in2
= tcg_const_i64(d2
& mask
);
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
) {
1168 if (use_goto_tb(s
, dest
)) {
1171 tcg_gen_movi_i64(psw_addr
, dest
);
1172 tcg_gen_exit_tb((tcg_target_long
)s
->tb
);
1173 return EXIT_GOTO_TB
;
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
)
1184 uint64_t dest
= s
->pc
+ 2 * imm
;
1187 /* Take care of the special cases first. */
1188 if (c
->cond
== TCG_COND_NEVER
) {
1193 if (dest
== s
->next_pc
) {
1194 /* Branch to next. */
1198 if (c
->cond
== TCG_COND_ALWAYS
) {
1199 ret
= help_goto_direct(s
, dest
);
1203 if (TCGV_IS_UNUSED_I64(cdest
)) {
1204 /* E.g. bcr %r0 -> no branch. */
1208 if (c
->cond
== TCG_COND_ALWAYS
) {
1209 tcg_gen_mov_i64(psw_addr
, cdest
);
1210 ret
= EXIT_PC_UPDATED
;
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. */
1220 lab
= gen_new_label();
1222 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1224 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1227 /* Branch not taken. */
1229 tcg_gen_movi_i64(psw_addr
, s
->next_pc
);
1230 tcg_gen_exit_tb((tcg_target_long
)s
->tb
+ 0);
1235 tcg_gen_movi_i64(psw_addr
, dest
);
1236 tcg_gen_exit_tb((tcg_target_long
)s
->tb
+ 1);
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. */
1245 tcg_gen_mov_i64(psw_addr
, cdest
);
1248 lab
= gen_new_label();
1250 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1252 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1255 /* Branch not taken. */
1258 tcg_gen_movi_i64(psw_addr
, s
->next_pc
);
1259 tcg_gen_exit_tb((tcg_target_long
)s
->tb
+ 0);
1263 tcg_gen_movi_i64(psw_addr
, dest
);
1265 ret
= EXIT_PC_UPDATED
;
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
);
1274 cdest
= tcg_const_i64(dest
);
1278 tcg_gen_movcond_i64(c
->cond
, psw_addr
, c
->u
.s64
.a
, c
->u
.s64
.b
,
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
);
1293 tcg_temp_free_i64(cdest
);
1295 tcg_temp_free_i64(next
);
1297 ret
= EXIT_PC_UPDATED
;
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
);
1315 static ExitStatus
op_absf32(DisasContext
*s
, DisasOps
*o
)
1317 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffull
);
1321 static ExitStatus
op_absf64(DisasContext
*s
, DisasOps
*o
)
1323 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffffffffffull
);
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
);
1334 static ExitStatus
op_add(DisasContext
*s
, DisasOps
*o
)
1336 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1340 static ExitStatus
op_addc(DisasContext
*s
, DisasOps
*o
)
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();
1353 tcg_gen_setcond_i64(cmp
.cond
, carry
, cmp
.u
.s64
.a
, cmp
.u
.s64
.b
);
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
);
1362 tcg_gen_add_i64(o
->out
, o
->out
, carry
);
1363 tcg_temp_free_i64(carry
);
1367 static ExitStatus
op_aeb(DisasContext
*s
, DisasOps
*o
)
1369 gen_helper_aeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
1373 static ExitStatus
op_adb(DisasContext
*s
, DisasOps
*o
)
1375 gen_helper_adb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
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
);
1386 static ExitStatus
op_and(DisasContext
*s
, DisasOps
*o
)
1388 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
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
;
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
);
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
;
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;
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;
1445 c
.cond
= TCG_COND_NE
;
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;
1468 c
.cond
= TCG_COND_NE
;
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;
1489 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
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;
1514 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
1517 if (r1
== (r3
| 1)) {
1518 c
.u
.s64
.b
= load_reg(r3
| 1);
1521 c
.u
.s64
.b
= regs
[r3
| 1];
1525 tcg_gen_add_i64(regs
[r1
], regs
[r1
], regs
[r3
]);
1526 c
.u
.s64
.a
= regs
[r1
];
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
);
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;
1546 is_imm
= have_field(s
->fields
, i4
);
1548 imm
= get_field(s
->fields
, i4
);
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
);
1565 static ExitStatus
op_cdb(DisasContext
*s
, DisasOps
*o
)
1567 gen_helper_cdb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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]);
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
);
1754 static ExitStatus
op_clc(DisasContext
*s
, DisasOps
*o
)
1756 int l
= get_field(s
->fields
, l1
);
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
));
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
));
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
));
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
));
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
);
1784 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_64
, cc_src
, cc_dst
);
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
);
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
);
1808 tcg_temp_free_i32(t1
);
1809 tcg_temp_free_i32(m3
);
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
);
1818 return_low128(o
->in2
);
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
);
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
);
1848 tcg_gen_qemu_ld64(o
->out
, addr
, get_mem_index(s
));
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
);
1866 tcg_gen_qemu_st64(mem
, addr
, get_mem_index(s
));
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
);
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
);
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
);
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
);
1958 static ExitStatus
op_ct(DisasContext
*s
, DisasOps
*o
)
1960 int m3
= get_field(s
->fields
, m3
);
1961 int lab
= gen_new_label();
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
);
1979 gen_program_exception(s
, PGM_DATA
);
1985 #ifndef CONFIG_USER_ONLY
1986 static ExitStatus
op_diag(DisasContext
*s
, DisasOps
*o
)
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
);
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
);
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
);
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
);
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
);
2029 static ExitStatus
op_deb(DisasContext
*s
, DisasOps
*o
)
2031 gen_helper_deb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2035 static ExitStatus
op_ddb(DisasContext
*s
, DisasOps
*o
)
2037 gen_helper_ddb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
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
);
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
]));
2055 static ExitStatus
op_efpc(DisasContext
*s
, DisasOps
*o
)
2057 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, fpc
));
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. */
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
);
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
);
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();
2116 /* Effectively a 32-bit load. */
2117 tcg_gen_qemu_ld32u(tmp
, o
->in2
, get_mem_index(s
));
2124 /* Effectively a 16-bit load. */
2125 tcg_gen_qemu_ld16u(tmp
, o
->in2
, get_mem_index(s
));
2133 /* Effectively an 8-bit load. */
2134 tcg_gen_qemu_ld8u(tmp
, o
->in2
, get_mem_index(s
));
2139 pos
= base
+ ctz32(m3
) * 8;
2140 tcg_gen_deposit_i64(o
->out
, o
->out
, tmp
, pos
, len
);
2141 ccm
= ((1ull << len
) - 1) << pos
;
2145 /* This is going to be a sequence of loads and inserts. */
2146 pos
= base
+ 32 - 8;
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);
2155 m3
= (m3
<< 1) & 0xf;
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
);
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
);
2175 static ExitStatus
op_ipm(DisasContext
*s
, DisasOps
*o
)
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
);
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
);
2202 static ExitStatus
op_iske(DisasContext
*s
, DisasOps
*o
)
2204 check_privileged(s
);
2205 gen_helper_iske(o
->out
, cpu_env
, o
->in2
);
2210 static ExitStatus
op_ldeb(DisasContext
*s
, DisasOps
*o
)
2212 gen_helper_ldeb(o
->out
, cpu_env
, o
->in2
);
2216 static ExitStatus
op_ledb(DisasContext
*s
, DisasOps
*o
)
2218 gen_helper_ledb(o
->out
, cpu_env
, o
->in2
);
2222 static ExitStatus
op_ldxb(DisasContext
*s
, DisasOps
*o
)
2224 gen_helper_ldxb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2228 static ExitStatus
op_lexb(DisasContext
*s
, DisasOps
*o
)
2230 gen_helper_lexb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2234 static ExitStatus
op_lxdb(DisasContext
*s
, DisasOps
*o
)
2236 gen_helper_lxdb(o
->out
, cpu_env
, o
->in2
);
2237 return_low128(o
->out2
);
2241 static ExitStatus
op_lxeb(DisasContext
*s
, DisasOps
*o
)
2243 gen_helper_lxeb(o
->out
, cpu_env
, o
->in2
);
2244 return_low128(o
->out2
);
2248 static ExitStatus
op_llgt(DisasContext
*s
, DisasOps
*o
)
2250 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffff);
2254 static ExitStatus
op_ld8s(DisasContext
*s
, DisasOps
*o
)
2256 tcg_gen_qemu_ld8s(o
->out
, o
->in2
, get_mem_index(s
));
2260 static ExitStatus
op_ld8u(DisasContext
*s
, DisasOps
*o
)
2262 tcg_gen_qemu_ld8u(o
->out
, o
->in2
, get_mem_index(s
));
2266 static ExitStatus
op_ld16s(DisasContext
*s
, DisasOps
*o
)
2268 tcg_gen_qemu_ld16s(o
->out
, o
->in2
, get_mem_index(s
));
2272 static ExitStatus
op_ld16u(DisasContext
*s
, DisasOps
*o
)
2274 tcg_gen_qemu_ld16u(o
->out
, o
->in2
, get_mem_index(s
));
2278 static ExitStatus
op_ld32s(DisasContext
*s
, DisasOps
*o
)
2280 tcg_gen_qemu_ld32s(o
->out
, o
->in2
, get_mem_index(s
));
2284 static ExitStatus
op_ld32u(DisasContext
*s
, DisasOps
*o
)
2286 tcg_gen_qemu_ld32u(o
->out
, o
->in2
, get_mem_index(s
));
2290 static ExitStatus
op_ld64(DisasContext
*s
, DisasOps
*o
)
2292 tcg_gen_qemu_ld64(o
->out
, o
->in2
, get_mem_index(s
));
2296 static ExitStatus
op_loc(DisasContext
*s
, DisasOps
*o
)
2300 disas_jcc(s
, &c
, get_field(s
->fields
, m3
));
2303 tcg_gen_movcond_i64(c
.cond
, o
->out
, c
.u
.s64
.a
, c
.u
.s64
.b
,
2307 TCGv_i32 t32
= tcg_temp_new_i32();
2310 tcg_gen_setcond_i32(c
.cond
, t32
, c
.u
.s32
.a
, c
.u
.s32
.b
);
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
);
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
);
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
);
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
);
2359 static ExitStatus
op_lpsw(DisasContext
*s
, DisasOps
*o
)
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
)
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
;
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
);
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);
2415 tcg_gen_qemu_ld32u(t
, o
->in2
, get_mem_index(s
));
2416 store_reg32_i64(r1
, t
);
2420 tcg_gen_add_i64(o
->in2
, o
->in2
, t4
);
2424 tcg_temp_free_i64(t
);
2425 tcg_temp_free_i64(t4
);
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);
2437 tcg_gen_qemu_ld32u(t
, o
->in2
, get_mem_index(s
));
2438 store_reg32h_i64(r1
, t
);
2442 tcg_gen_add_i64(o
->in2
, o
->in2
, t4
);
2446 tcg_temp_free_i64(t
);
2447 tcg_temp_free_i64(t4
);
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);
2458 tcg_gen_qemu_ld64(regs
[r1
], o
->in2
, get_mem_index(s
));
2462 tcg_gen_add_i64(o
->in2
, o
->in2
, t8
);
2466 tcg_temp_free_i64(t8
);
2470 static ExitStatus
op_mov2(DisasContext
*s
, DisasOps
*o
)
2473 o
->g_out
= o
->g_in2
;
2474 TCGV_UNUSED_I64(o
->in2
);
2479 static ExitStatus
op_movx(DisasContext
*s
, DisasOps
*o
)
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;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
2559 return_low128(o
->in2
);
2563 static ExitStatus
op_mul(DisasContext
*s
, DisasOps
*o
)
2565 tcg_gen_mul_i64(o
->out
, o
->in1
, o
->in2
);
2569 static ExitStatus
op_mul128(DisasContext
*s
, DisasOps
*o
)
2571 tcg_gen_mulu2_i64(o
->out2
, o
->out
, o
->in1
, o
->in2
);
2575 static ExitStatus
op_meeb(DisasContext
*s
, DisasOps
*o
)
2577 gen_helper_meeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2581 static ExitStatus
op_mdeb(DisasContext
*s
, DisasOps
*o
)
2583 gen_helper_mdeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2587 static ExitStatus
op_mdb(DisasContext
*s
, DisasOps
*o
)
2589 gen_helper_mdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
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
);
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
);
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
);
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
]);
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
);
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
]);
2637 static ExitStatus
op_nabs(DisasContext
*s
, DisasOps
*o
)
2639 gen_helper_nabs_i64(o
->out
, o
->in2
);
2643 static ExitStatus
op_nabsf32(DisasContext
*s
, DisasOps
*o
)
2645 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x80000000ull
);
2649 static ExitStatus
op_nabsf64(DisasContext
*s
, DisasOps
*o
)
2651 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
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
);
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
);
2672 static ExitStatus
op_neg(DisasContext
*s
, DisasOps
*o
)
2674 tcg_gen_neg_i64(o
->out
, o
->in2
);
2678 static ExitStatus
op_negf32(DisasContext
*s
, DisasOps
*o
)
2680 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x80000000ull
);
2684 static ExitStatus
op_negf64(DisasContext
*s
, DisasOps
*o
)
2686 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
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
);
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
);
2707 static ExitStatus
op_or(DisasContext
*s
, DisasOps
*o
)
2709 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
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
;
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
);
2729 static ExitStatus
op_popcnt(DisasContext
*s
, DisasOps
*o
)
2731 gen_helper_popcnt(o
->out
, o
->in2
);
2735 #ifndef CONFIG_USER_ONLY
2736 static ExitStatus
op_ptlb(DisasContext
*s
, DisasOps
*o
)
2738 check_privileged(s
);
2739 gen_helper_ptlb(cpu_env
);
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
;
2753 /* Adjust the arguments for the specific insn. */
2754 switch (s
->fields
->op2
) {
2755 case 0x55: /* risbg */
2760 case 0x5d: /* risbhg */
2763 pmask
= 0xffffffff00000000ull
;
2765 case 0x51: /* risblg */
2768 pmask
= 0x00000000ffffffffull
;
2774 /* MASK is the set of bits to be inserted from R2.
2775 Take care for I3/I4 wraparound. */
2778 mask
^= pmask
>> i4
>> 1;
2780 mask
|= ~(pmask
>> i4
>> 1);
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
;
2788 if (s
->fields
->op2
== 0x55) {
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) {
2801 /* Note that we rotate the bits to be inserted to the lsb, not to
2802 the position as described in the PoO. */
2805 rot
= (i5
- pos
) & 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. */
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
);
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
);
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
);
2834 /* If this is a test-only form, arrange to discard the result. */
2836 o
->out
= tcg_temp_new_i64();
2844 /* MASK is the set of bits to be operated on from R2.
2845 Take care for I3/I4 wraparound. */
2848 mask
^= ~0ull >> i4
>> 1;
2850 mask
|= ~(~0ull >> i4
>> 1);
2853 /* Rotate the input as necessary. */
2854 tcg_gen_rotli_i64(o
->in2
, o
->in2
, i5
);
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
);
2863 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
2864 tcg_gen_or_i64(o
->out
, o
->out
, o
->in2
);
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
);
2875 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
2876 set_cc_nz_u64(s
, cc_dst
);
2880 static ExitStatus
op_rev16(DisasContext
*s
, DisasOps
*o
)
2882 tcg_gen_bswap16_i64(o
->out
, o
->in2
);
2886 static ExitStatus
op_rev32(DisasContext
*s
, DisasOps
*o
)
2888 tcg_gen_bswap32_i64(o
->out
, o
->in2
);
2892 static ExitStatus
op_rev64(DisasContext
*s
, DisasOps
*o
)
2894 tcg_gen_bswap64_i64(o
->out
, o
->in2
);
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
);
2913 static ExitStatus
op_rll64(DisasContext
*s
, DisasOps
*o
)
2915 tcg_gen_rotl_i64(o
->out
, o
->in1
, o
->in2
);
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
);
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
;
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
]));
2944 static ExitStatus
op_seb(DisasContext
*s
, DisasOps
*o
)
2946 gen_helper_seb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2950 static ExitStatus
op_sdb(DisasContext
*s
, DisasOps
*o
)
2952 gen_helper_sdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
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
);
2963 static ExitStatus
op_sqeb(DisasContext
*s
, DisasOps
*o
)
2965 gen_helper_sqeb(o
->out
, cpu_env
, o
->in2
);
2969 static ExitStatus
op_sqdb(DisasContext
*s
, DisasOps
*o
)
2971 gen_helper_sqdb(o
->out
, cpu_env
, o
->in2
);
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
);
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
);
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
);
3003 static ExitStatus
op_soc(DisasContext
*s
, DisasOps
*o
)
3009 disas_jcc(s
, &c
, get_field(s
->fields
, m3
));
3011 lab
= gen_new_label();
3013 tcg_gen_brcond_i64(c
.cond
, c
.u
.s64
.a
, c
.u
.s64
.b
, lab
);
3015 tcg_gen_brcond_i32(c
.cond
, c
.u
.s32
.a
, c
.u
.s32
.b
, lab
);
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
));
3024 tcg_gen_qemu_st32(regs
[r1
], a
, get_mem_index(s
));
3026 tcg_temp_free_i64(a
);
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
);
3046 static ExitStatus
op_sll(DisasContext
*s
, DisasOps
*o
)
3048 tcg_gen_shl_i64(o
->out
, o
->in1
, o
->in2
);
3052 static ExitStatus
op_sra(DisasContext
*s
, DisasOps
*o
)
3054 tcg_gen_sar_i64(o
->out
, o
->in1
, o
->in2
);
3058 static ExitStatus
op_srl(DisasContext
*s
, DisasOps
*o
)
3060 tcg_gen_shr_i64(o
->out
, o
->in1
, o
->in2
);
3064 static ExitStatus
op_sfpc(DisasContext
*s
, DisasOps
*o
)
3066 gen_helper_sfpc(cpu_env
, o
->in2
);
3070 static ExitStatus
op_sfas(DisasContext
*s
, DisasOps
*o
)
3072 gen_helper_sfas(cpu_env
, o
->in2
);
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();
3084 switch (s
->fields
->op2
) {
3085 case 0x99: /* SRNM */
3088 case 0xb8: /* SRNMB */
3091 case 0xb9: /* SRNMT */
3097 mask
= (1 << len
) - 1;
3099 /* Insert the value into the appropriate field of the FPC. */
3101 tcg_gen_movi_i64(t1
, d2
& mask
);
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
);
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);
3125 static ExitStatus
op_sske(DisasContext
*s
, DisasOps
*o
)
3127 check_privileged(s
);
3128 gen_helper_sske(cpu_env
, o
->in1
, o
->in2
);
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);
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
));
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);
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);
3179 static ExitStatus
op_sckc(DisasContext
*s
, DisasOps
*o
)
3181 check_privileged(s
);
3182 gen_helper_sckc(cpu_env
, o
->in2
);
3186 static ExitStatus
op_stckc(DisasContext
*s
, DisasOps
*o
)
3188 check_privileged(s
);
3189 gen_helper_stckc(o
->out
, cpu_env
);
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
);
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
);
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
));
3224 static ExitStatus
op_spt(DisasContext
*s
, DisasOps
*o
)
3226 check_privileged(s
);
3227 gen_helper_spt(cpu_env
, o
->in2
);
3231 static ExitStatus
op_stfl(DisasContext
*s
, DisasOps
*o
)
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
);
3245 static ExitStatus
op_stpt(DisasContext
*s
, DisasOps
*o
)
3247 check_privileged(s
);
3248 gen_helper_stpt(o
->out
, cpu_env
);
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]);
3261 static ExitStatus
op_spx(DisasContext
*s
, DisasOps
*o
)
3263 check_privileged(s
);
3264 gen_helper_spx(cpu_env
, o
->in2
);
3268 static ExitStatus
op_subchannel(DisasContext
*s
, DisasOps
*o
)
3270 check_privileged(s
);
3271 /* Not operational. */
3272 gen_op_movi_cc(s
, 3);
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);
3284 static ExitStatus
op_stnosm(DisasContext
*s
, DisasOps
*o
)
3286 uint64_t i2
= get_field(s
->fields
, i2
);
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
);
3303 tcg_gen_ori_i64(psw_mask
, psw_mask
, i2
<< 56);
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
);
3317 static ExitStatus
op_st8(DisasContext
*s
, DisasOps
*o
)
3319 tcg_gen_qemu_st8(o
->in1
, o
->in2
, get_mem_index(s
));
3323 static ExitStatus
op_st16(DisasContext
*s
, DisasOps
*o
)
3325 tcg_gen_qemu_st16(o
->in1
, o
->in2
, get_mem_index(s
));
3329 static ExitStatus
op_st32(DisasContext
*s
, DisasOps
*o
)
3331 tcg_gen_qemu_st32(o
->in1
, o
->in2
, get_mem_index(s
));
3335 static ExitStatus
op_st64(DisasContext
*s
, DisasOps
*o
)
3337 tcg_gen_qemu_st64(o
->in1
, o
->in2
, get_mem_index(s
));
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
);
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;
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
));
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
));
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
));
3384 /* This is going to be a sequence of shifts and stores. */
3385 pos
= base
+ 32 - 8;
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;
3397 tcg_temp_free_i64(tmp
);
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
);
3410 tcg_gen_qemu_st64(regs
[r1
], o
->in2
, get_mem_index(s
));
3412 tcg_gen_qemu_st32(regs
[r1
], o
->in2
, get_mem_index(s
));
3417 tcg_gen_add_i64(o
->in2
, o
->in2
, tsize
);
3421 tcg_temp_free_i64(tsize
);
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);
3434 tcg_gen_shl_i64(t
, regs
[r1
], t32
);
3435 tcg_gen_qemu_st32(t
, o
->in2
, get_mem_index(s
));
3439 tcg_gen_add_i64(o
->in2
, o
->in2
, t4
);
3443 tcg_temp_free_i64(t
);
3444 tcg_temp_free_i64(t4
);
3445 tcg_temp_free_i64(t32
);
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
);
3454 return_low128(o
->in2
);
3458 static ExitStatus
op_sub(DisasContext
*s
, DisasOps
*o
)
3460 tcg_gen_sub_i64(o
->out
, o
->in1
, o
->in2
);
3464 static ExitStatus
op_subb(DisasContext
*s
, DisasOps
*o
)
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();
3476 tcg_gen_setcond_i64(cmp
.cond
, borrow
, cmp
.u
.s64
.a
, cmp
.u
.s64
.b
);
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
);
3485 tcg_gen_sub_i64(o
->out
, o
->out
, borrow
);
3486 tcg_temp_free_i64(borrow
);
3490 static ExitStatus
op_svc(DisasContext
*s
, DisasOps
*o
)
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
);
3516 static ExitStatus
op_tcdb(DisasContext
*s
, DisasOps
*o
)
3518 gen_helper_tcdb(cc_op
, o
->in1
, o
->in2
);
3523 static ExitStatus
op_tcxb(DisasContext
*s
, DisasOps
*o
)
3525 gen_helper_tcxb(cc_op
, o
->out
, o
->out2
, o
->in2
);
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
);
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
);
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
);
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
);
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);
3576 tcg_gen_qemu_st64(o
->in2
, o
->addr1
, get_mem_index(s
));
3579 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 8);
3583 tcg_gen_qemu_st32(o
->in2
, o
->addr1
, get_mem_index(s
));
3586 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 4);
3590 tcg_gen_qemu_st16(o
->in2
, o
->addr1
, get_mem_index(s
));
3593 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 2);
3597 tcg_gen_qemu_st8(o
->in2
, o
->addr1
, get_mem_index(s
));
3599 gen_op_movi_cc(s
, 0);
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
);
3613 static ExitStatus
op_xor(DisasContext
*s
, DisasOps
*o
)
3615 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
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
;
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
);
3635 static ExitStatus
op_zero(DisasContext
*s
, DisasOps
*o
)
3637 o
->out
= tcg_const_i64(0);
3641 static ExitStatus
op_zero2(DisasContext
*s
, DisasOps
*o
)
3643 o
->out
= tcg_const_i64(0);
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
)];
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
);
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
)];
3850 #define SPEC_prep_f1 0
3852 static void prep_x1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
3854 int r1
= get_field(f
, 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
)];
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
)];
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
)];
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
);
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
)];
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
)
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
)
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
)
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
)
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
)
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
)
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
)];
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
)];
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
);
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
)];
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
);
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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
)
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"
4452 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4456 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
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, \
4467 /* Allow 0 to be used for NULL in the table below. */
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"
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
)
4491 #include "insn-data.def"
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
)
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. */
4517 case 0: /* unsigned */
4519 case 1: /* signed */
4520 assert(f
->size
<= 32);
4521 m
= 1u << (f
->size
- 1);
4524 case 2: /* dl+dh split, signed 20 bit. */
4525 r
= ((int8_t)r
<< 12) | (r
>> 8);
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
,
4546 uint64_t insn
, pc
= s
->pc
;
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
;
4560 insn
= ld_code4(env
, pc
) << 32;
4563 insn
= (insn
<< 48) | (ld_code4(env
, pc
+ 2) << 16);
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. */
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;
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;
4595 case 0xd0 ... 0xdf: /* SS */
4601 case 0xee ... 0xf3: /* SS */
4602 case 0xf8 ... 0xfd: /* SS */
4606 op2
= (insn
<< 40) >> 56;
4610 memset(f
, 0, sizeof(*f
));
4614 /* Lookup the instruction. */
4615 info
= lookup_opc(op
<< 8 | op2
);
4617 /* If we found it, extract the operands. */
4619 DisasFormat fmt
= info
->fmt
;
4622 for (i
= 0; i
< NUM_C_FIELD
; ++i
) {
4623 extract_field(f
, &format_info
[fmt
].op
[i
], insn
);
4629 static ExitStatus
translate_one(CPUS390XState
*env
, DisasContext
*s
)
4631 const DisasInsn
*insn
;
4632 ExitStatus ret
= NO_EXIT
;
4636 /* Search for the insn in the table. */
4637 insn
= extract_insn(env
, s
, &f
);
4639 /* Not found means unimplemented/illegal opcode. */
4641 qemu_log_mask(LOG_UNIMP
, "unimplemented opcode 0x%02x%02x\n",
4643 gen_illegal_opcode(s
);
4644 return EXIT_NORETURN
;
4647 /* Check for insn specification exceptions. */
4649 int spec
= insn
->spec
, excp
= 0, r
;
4651 if (spec
& SPEC_r1_even
) {
4652 r
= get_field(&f
, r1
);
4654 excp
= PGM_SPECIFICATION
;
4657 if (spec
& SPEC_r2_even
) {
4658 r
= get_field(&f
, r2
);
4660 excp
= PGM_SPECIFICATION
;
4663 if (spec
& SPEC_r3_even
) {
4664 r
= get_field(&f
, r3
);
4666 excp
= PGM_SPECIFICATION
;
4669 if (spec
& SPEC_r1_f128
) {
4670 r
= get_field(&f
, r1
);
4672 excp
= PGM_SPECIFICATION
;
4675 if (spec
& SPEC_r2_f128
) {
4676 r
= get_field(&f
, r2
);
4678 excp
= PGM_SPECIFICATION
;
4682 gen_program_exception(s
, excp
);
4683 return EXIT_NORETURN
;
4687 /* Set up the strutures we use to communicate with the helpers. */
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. */
4739 static inline void gen_intermediate_code_internal(S390CPU
*cpu
,
4740 TranslationBlock
*tb
,
4743 CPUState
*cs
= CPU(cpu
);
4744 CPUS390XState
*env
= &cpu
->env
;
4746 target_ulong pc_start
;
4747 uint64_t next_page_start
;
4748 uint16_t *gen_opc_end
;
4750 int num_insns
, max_insns
;
4758 if (!(tb
->flags
& FLAG_MASK_64
)) {
4759 pc_start
&= 0x7fffffff;
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
;
4772 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
4773 if (max_insns
== 0) {
4774 max_insns
= CF_COUNT_MASK
;
4781 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
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
)) {
4797 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
4798 tcg_gen_debug_insn_start(dc
.pc
);
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
;
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
4822 || cs
->singlestep_enabled
)) {
4823 status
= EXIT_PC_STALE
;
4825 } while (status
== NO_EXIT
);
4827 if (tb
->cflags
& CF_LAST_IO
) {
4836 update_psw_addr(&dc
);
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 */
4842 /* Exit the TB, either by raising a debug exception or by return. */
4844 gen_exception(EXCP_DEBUG
);
4853 gen_tb_end(tb
, num_insns
);
4854 *tcg_ctx
.gen_opc_ptr
= INDEX_op_end
;
4856 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
4859 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
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);
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
)
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
)) {