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"
36 #include "exec/cpu_ldst.h"
38 /* global register indexes */
39 static TCGv_ptr cpu_env
;
41 #include "exec/gen-icount.h"
42 #include "exec/helper-proto.h"
43 #include "exec/helper-gen.h"
45 #include "trace-tcg.h"
48 /* Information that (most) every instruction needs to manipulate. */
49 typedef struct DisasContext DisasContext
;
50 typedef struct DisasInsn DisasInsn
;
51 typedef struct DisasFields DisasFields
;
54 struct TranslationBlock
*tb
;
55 const DisasInsn
*insn
;
59 bool singlestep_enabled
;
62 /* Information carried about a condition to be evaluated. */
69 struct { TCGv_i64 a
, b
; } s64
;
70 struct { TCGv_i32 a
, b
; } s32
;
76 #ifdef DEBUG_INLINE_BRANCHES
77 static uint64_t inline_branch_hit
[CC_OP_MAX
];
78 static uint64_t inline_branch_miss
[CC_OP_MAX
];
81 static uint64_t pc_to_link_info(DisasContext
*s
, uint64_t pc
)
83 if (!(s
->tb
->flags
& FLAG_MASK_64
)) {
84 if (s
->tb
->flags
& FLAG_MASK_32
) {
85 return pc
| 0x80000000;
91 void s390_cpu_dump_state(CPUState
*cs
, FILE *f
, fprintf_function cpu_fprintf
,
94 S390CPU
*cpu
= S390_CPU(cs
);
95 CPUS390XState
*env
= &cpu
->env
;
99 cpu_fprintf(f
, "PSW=mask %016" PRIx64
" addr %016" PRIx64
" cc %15s\n",
100 env
->psw
.mask
, env
->psw
.addr
, cc_name(env
->cc_op
));
102 cpu_fprintf(f
, "PSW=mask %016" PRIx64
" addr %016" PRIx64
" cc %02x\n",
103 env
->psw
.mask
, env
->psw
.addr
, env
->cc_op
);
106 for (i
= 0; i
< 16; i
++) {
107 cpu_fprintf(f
, "R%02d=%016" PRIx64
, i
, env
->regs
[i
]);
109 cpu_fprintf(f
, "\n");
115 for (i
= 0; i
< 16; i
++) {
116 cpu_fprintf(f
, "F%02d=%016" PRIx64
, i
, get_freg(env
, i
)->ll
);
118 cpu_fprintf(f
, "\n");
124 for (i
= 0; i
< 32; i
++) {
125 cpu_fprintf(f
, "V%02d=%016" PRIx64
"%016" PRIx64
, i
,
126 env
->vregs
[i
][0].ll
, env
->vregs
[i
][1].ll
);
127 cpu_fprintf(f
, (i
% 2) ? " " : "\n");
130 #ifndef CONFIG_USER_ONLY
131 for (i
= 0; i
< 16; i
++) {
132 cpu_fprintf(f
, "C%02d=%016" PRIx64
, i
, env
->cregs
[i
]);
134 cpu_fprintf(f
, "\n");
141 #ifdef DEBUG_INLINE_BRANCHES
142 for (i
= 0; i
< CC_OP_MAX
; i
++) {
143 cpu_fprintf(f
, " %15s = %10ld\t%10ld\n", cc_name(i
),
144 inline_branch_miss
[i
], inline_branch_hit
[i
]);
148 cpu_fprintf(f
, "\n");
151 static TCGv_i64 psw_addr
;
152 static TCGv_i64 psw_mask
;
154 static TCGv_i32 cc_op
;
155 static TCGv_i64 cc_src
;
156 static TCGv_i64 cc_dst
;
157 static TCGv_i64 cc_vr
;
159 static char cpu_reg_names
[32][4];
160 static TCGv_i64 regs
[16];
161 static TCGv_i64 fregs
[16];
163 static uint8_t gen_opc_cc_op
[OPC_BUF_SIZE
];
165 void s390x_translate_init(void)
169 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
170 psw_addr
= tcg_global_mem_new_i64(TCG_AREG0
,
171 offsetof(CPUS390XState
, psw
.addr
),
173 psw_mask
= tcg_global_mem_new_i64(TCG_AREG0
,
174 offsetof(CPUS390XState
, psw
.mask
),
177 cc_op
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUS390XState
, cc_op
),
179 cc_src
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, cc_src
),
181 cc_dst
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, cc_dst
),
183 cc_vr
= tcg_global_mem_new_i64(TCG_AREG0
, offsetof(CPUS390XState
, cc_vr
),
186 for (i
= 0; i
< 16; i
++) {
187 snprintf(cpu_reg_names
[i
], sizeof(cpu_reg_names
[0]), "r%d", i
);
188 regs
[i
] = tcg_global_mem_new(TCG_AREG0
,
189 offsetof(CPUS390XState
, regs
[i
]),
193 for (i
= 0; i
< 16; i
++) {
194 snprintf(cpu_reg_names
[i
+ 16], sizeof(cpu_reg_names
[0]), "f%d", i
);
195 fregs
[i
] = tcg_global_mem_new(TCG_AREG0
,
196 offsetof(CPUS390XState
, vregs
[i
][0].d
),
197 cpu_reg_names
[i
+ 16]);
201 static TCGv_i64
load_reg(int reg
)
203 TCGv_i64 r
= tcg_temp_new_i64();
204 tcg_gen_mov_i64(r
, regs
[reg
]);
208 static TCGv_i64
load_freg32_i64(int reg
)
210 TCGv_i64 r
= tcg_temp_new_i64();
211 tcg_gen_shri_i64(r
, fregs
[reg
], 32);
215 static void store_reg(int reg
, TCGv_i64 v
)
217 tcg_gen_mov_i64(regs
[reg
], v
);
220 static void store_freg(int reg
, TCGv_i64 v
)
222 tcg_gen_mov_i64(fregs
[reg
], v
);
225 static void store_reg32_i64(int reg
, TCGv_i64 v
)
227 /* 32 bit register writes keep the upper half */
228 tcg_gen_deposit_i64(regs
[reg
], regs
[reg
], v
, 0, 32);
231 static void store_reg32h_i64(int reg
, TCGv_i64 v
)
233 tcg_gen_deposit_i64(regs
[reg
], regs
[reg
], v
, 32, 32);
236 static void store_freg32_i64(int reg
, TCGv_i64 v
)
238 tcg_gen_deposit_i64(fregs
[reg
], fregs
[reg
], v
, 32, 32);
241 static void return_low128(TCGv_i64 dest
)
243 tcg_gen_ld_i64(dest
, cpu_env
, offsetof(CPUS390XState
, retxl
));
246 static void update_psw_addr(DisasContext
*s
)
249 tcg_gen_movi_i64(psw_addr
, s
->pc
);
252 static void update_cc_op(DisasContext
*s
)
254 if (s
->cc_op
!= CC_OP_DYNAMIC
&& s
->cc_op
!= CC_OP_STATIC
) {
255 tcg_gen_movi_i32(cc_op
, s
->cc_op
);
259 static void potential_page_fault(DisasContext
*s
)
265 static inline uint64_t ld_code2(CPUS390XState
*env
, uint64_t pc
)
267 return (uint64_t)cpu_lduw_code(env
, pc
);
270 static inline uint64_t ld_code4(CPUS390XState
*env
, uint64_t pc
)
272 return (uint64_t)(uint32_t)cpu_ldl_code(env
, pc
);
275 static int get_mem_index(DisasContext
*s
)
277 switch (s
->tb
->flags
& FLAG_MASK_ASC
) {
278 case PSW_ASC_PRIMARY
>> 32:
280 case PSW_ASC_SECONDARY
>> 32:
282 case PSW_ASC_HOME
>> 32:
290 static void gen_exception(int excp
)
292 TCGv_i32 tmp
= tcg_const_i32(excp
);
293 gen_helper_exception(cpu_env
, tmp
);
294 tcg_temp_free_i32(tmp
);
297 static void gen_program_exception(DisasContext
*s
, int code
)
301 /* Remember what pgm exeption this was. */
302 tmp
= tcg_const_i32(code
);
303 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUS390XState
, int_pgm_code
));
304 tcg_temp_free_i32(tmp
);
306 tmp
= tcg_const_i32(s
->next_pc
- s
->pc
);
307 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUS390XState
, int_pgm_ilen
));
308 tcg_temp_free_i32(tmp
);
310 /* Advance past instruction. */
317 /* Trigger exception. */
318 gen_exception(EXCP_PGM
);
321 static inline void gen_illegal_opcode(DisasContext
*s
)
323 gen_program_exception(s
, PGM_OPERATION
);
326 static inline void gen_trap(DisasContext
*s
)
330 /* Set DXC to 0xff. */
331 t
= tcg_temp_new_i32();
332 tcg_gen_ld_i32(t
, cpu_env
, offsetof(CPUS390XState
, fpc
));
333 tcg_gen_ori_i32(t
, t
, 0xff00);
334 tcg_gen_st_i32(t
, cpu_env
, offsetof(CPUS390XState
, fpc
));
335 tcg_temp_free_i32(t
);
337 gen_program_exception(s
, PGM_DATA
);
340 #ifndef CONFIG_USER_ONLY
341 static void check_privileged(DisasContext
*s
)
343 if (s
->tb
->flags
& (PSW_MASK_PSTATE
>> 32)) {
344 gen_program_exception(s
, PGM_PRIVILEGED
);
349 static TCGv_i64
get_address(DisasContext
*s
, int x2
, int b2
, int d2
)
351 TCGv_i64 tmp
= tcg_temp_new_i64();
352 bool need_31
= !(s
->tb
->flags
& FLAG_MASK_64
);
354 /* Note that d2 is limited to 20 bits, signed. If we crop negative
355 displacements early we create larger immedate addends. */
357 /* Note that addi optimizes the imm==0 case. */
359 tcg_gen_add_i64(tmp
, regs
[b2
], regs
[x2
]);
360 tcg_gen_addi_i64(tmp
, tmp
, d2
);
362 tcg_gen_addi_i64(tmp
, regs
[b2
], d2
);
364 tcg_gen_addi_i64(tmp
, regs
[x2
], d2
);
370 tcg_gen_movi_i64(tmp
, d2
);
373 tcg_gen_andi_i64(tmp
, tmp
, 0x7fffffff);
379 static inline bool live_cc_data(DisasContext
*s
)
381 return (s
->cc_op
!= CC_OP_DYNAMIC
382 && s
->cc_op
!= CC_OP_STATIC
386 static inline void gen_op_movi_cc(DisasContext
*s
, uint32_t val
)
388 if (live_cc_data(s
)) {
389 tcg_gen_discard_i64(cc_src
);
390 tcg_gen_discard_i64(cc_dst
);
391 tcg_gen_discard_i64(cc_vr
);
393 s
->cc_op
= CC_OP_CONST0
+ val
;
396 static void gen_op_update1_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 dst
)
398 if (live_cc_data(s
)) {
399 tcg_gen_discard_i64(cc_src
);
400 tcg_gen_discard_i64(cc_vr
);
402 tcg_gen_mov_i64(cc_dst
, dst
);
406 static void gen_op_update2_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 src
,
409 if (live_cc_data(s
)) {
410 tcg_gen_discard_i64(cc_vr
);
412 tcg_gen_mov_i64(cc_src
, src
);
413 tcg_gen_mov_i64(cc_dst
, dst
);
417 static void gen_op_update3_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 src
,
418 TCGv_i64 dst
, TCGv_i64 vr
)
420 tcg_gen_mov_i64(cc_src
, src
);
421 tcg_gen_mov_i64(cc_dst
, dst
);
422 tcg_gen_mov_i64(cc_vr
, vr
);
426 static void set_cc_nz_u64(DisasContext
*s
, TCGv_i64 val
)
428 gen_op_update1_cc_i64(s
, CC_OP_NZ
, val
);
431 static void gen_set_cc_nz_f32(DisasContext
*s
, TCGv_i64 val
)
433 gen_op_update1_cc_i64(s
, CC_OP_NZ_F32
, val
);
436 static void gen_set_cc_nz_f64(DisasContext
*s
, TCGv_i64 val
)
438 gen_op_update1_cc_i64(s
, CC_OP_NZ_F64
, val
);
441 static void gen_set_cc_nz_f128(DisasContext
*s
, TCGv_i64 vh
, TCGv_i64 vl
)
443 gen_op_update2_cc_i64(s
, CC_OP_NZ_F128
, vh
, vl
);
446 /* CC value is in env->cc_op */
447 static void set_cc_static(DisasContext
*s
)
449 if (live_cc_data(s
)) {
450 tcg_gen_discard_i64(cc_src
);
451 tcg_gen_discard_i64(cc_dst
);
452 tcg_gen_discard_i64(cc_vr
);
454 s
->cc_op
= CC_OP_STATIC
;
457 /* calculates cc into cc_op */
458 static void gen_op_calc_cc(DisasContext
*s
)
460 TCGv_i32 local_cc_op
;
463 TCGV_UNUSED_I32(local_cc_op
);
464 TCGV_UNUSED_I64(dummy
);
467 dummy
= tcg_const_i64(0);
481 local_cc_op
= tcg_const_i32(s
->cc_op
);
497 /* s->cc_op is the cc value */
498 tcg_gen_movi_i32(cc_op
, s
->cc_op
- CC_OP_CONST0
);
501 /* env->cc_op already is the cc value */
516 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, dummy
, cc_dst
, dummy
);
521 case CC_OP_LTUGTU_32
:
522 case CC_OP_LTUGTU_64
:
529 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, dummy
);
544 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, cc_vr
);
547 /* unknown operation - assume 3 arguments and cc_op in env */
548 gen_helper_calc_cc(cc_op
, cpu_env
, cc_op
, cc_src
, cc_dst
, cc_vr
);
554 if (!TCGV_IS_UNUSED_I32(local_cc_op
)) {
555 tcg_temp_free_i32(local_cc_op
);
557 if (!TCGV_IS_UNUSED_I64(dummy
)) {
558 tcg_temp_free_i64(dummy
);
561 /* We now have cc in cc_op as constant */
565 static int use_goto_tb(DisasContext
*s
, uint64_t dest
)
567 /* NOTE: we handle the case where the TB spans two pages here */
568 return (((dest
& TARGET_PAGE_MASK
) == (s
->tb
->pc
& TARGET_PAGE_MASK
)
569 || (dest
& TARGET_PAGE_MASK
) == ((s
->pc
- 1) & TARGET_PAGE_MASK
))
570 && !s
->singlestep_enabled
571 && !(s
->tb
->cflags
& CF_LAST_IO
)
572 && !(s
->tb
->flags
& FLAG_MASK_PER
));
575 static void account_noninline_branch(DisasContext
*s
, int cc_op
)
577 #ifdef DEBUG_INLINE_BRANCHES
578 inline_branch_miss
[cc_op
]++;
582 static void account_inline_branch(DisasContext
*s
, int cc_op
)
584 #ifdef DEBUG_INLINE_BRANCHES
585 inline_branch_hit
[cc_op
]++;
589 /* Table of mask values to comparison codes, given a comparison as input.
590 For such, CC=3 should not be possible. */
591 static const TCGCond ltgt_cond
[16] = {
592 TCG_COND_NEVER
, TCG_COND_NEVER
, /* | | | x */
593 TCG_COND_GT
, TCG_COND_GT
, /* | | GT | x */
594 TCG_COND_LT
, TCG_COND_LT
, /* | LT | | x */
595 TCG_COND_NE
, TCG_COND_NE
, /* | LT | GT | x */
596 TCG_COND_EQ
, TCG_COND_EQ
, /* EQ | | | x */
597 TCG_COND_GE
, TCG_COND_GE
, /* EQ | | GT | x */
598 TCG_COND_LE
, TCG_COND_LE
, /* EQ | LT | | x */
599 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
, /* EQ | LT | GT | x */
602 /* Table of mask values to comparison codes, given a logic op as input.
603 For such, only CC=0 and CC=1 should be possible. */
604 static const TCGCond nz_cond
[16] = {
605 TCG_COND_NEVER
, TCG_COND_NEVER
, /* | | x | x */
606 TCG_COND_NEVER
, TCG_COND_NEVER
,
607 TCG_COND_NE
, TCG_COND_NE
, /* | NE | x | x */
608 TCG_COND_NE
, TCG_COND_NE
,
609 TCG_COND_EQ
, TCG_COND_EQ
, /* EQ | | x | x */
610 TCG_COND_EQ
, TCG_COND_EQ
,
611 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
, /* EQ | NE | x | x */
612 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
,
615 /* Interpret MASK in terms of S->CC_OP, and fill in C with all the
616 details required to generate a TCG comparison. */
617 static void disas_jcc(DisasContext
*s
, DisasCompare
*c
, uint32_t mask
)
620 enum cc_op old_cc_op
= s
->cc_op
;
622 if (mask
== 15 || mask
== 0) {
623 c
->cond
= (mask
? TCG_COND_ALWAYS
: TCG_COND_NEVER
);
626 c
->g1
= c
->g2
= true;
631 /* Find the TCG condition for the mask + cc op. */
637 cond
= ltgt_cond
[mask
];
638 if (cond
== TCG_COND_NEVER
) {
641 account_inline_branch(s
, old_cc_op
);
644 case CC_OP_LTUGTU_32
:
645 case CC_OP_LTUGTU_64
:
646 cond
= tcg_unsigned_cond(ltgt_cond
[mask
]);
647 if (cond
== TCG_COND_NEVER
) {
650 account_inline_branch(s
, old_cc_op
);
654 cond
= nz_cond
[mask
];
655 if (cond
== TCG_COND_NEVER
) {
658 account_inline_branch(s
, old_cc_op
);
673 account_inline_branch(s
, old_cc_op
);
688 account_inline_branch(s
, old_cc_op
);
692 switch (mask
& 0xa) {
693 case 8: /* src == 0 -> no one bit found */
696 case 2: /* src != 0 -> one bit found */
702 account_inline_branch(s
, old_cc_op
);
708 case 8 | 2: /* vr == 0 */
711 case 4 | 1: /* vr != 0 */
714 case 8 | 4: /* no carry -> vr >= src */
717 case 2 | 1: /* carry -> vr < src */
723 account_inline_branch(s
, old_cc_op
);
728 /* Note that CC=0 is impossible; treat it as dont-care. */
730 case 2: /* zero -> op1 == op2 */
733 case 4 | 1: /* !zero -> op1 != op2 */
736 case 4: /* borrow (!carry) -> op1 < op2 */
739 case 2 | 1: /* !borrow (carry) -> op1 >= op2 */
745 account_inline_branch(s
, old_cc_op
);
750 /* Calculate cc value. */
755 /* Jump based on CC. We'll load up the real cond below;
756 the assignment here merely avoids a compiler warning. */
757 account_noninline_branch(s
, old_cc_op
);
758 old_cc_op
= CC_OP_STATIC
;
759 cond
= TCG_COND_NEVER
;
763 /* Load up the arguments of the comparison. */
765 c
->g1
= c
->g2
= false;
769 c
->u
.s32
.a
= tcg_temp_new_i32();
770 tcg_gen_trunc_i64_i32(c
->u
.s32
.a
, cc_dst
);
771 c
->u
.s32
.b
= tcg_const_i32(0);
774 case CC_OP_LTUGTU_32
:
777 c
->u
.s32
.a
= tcg_temp_new_i32();
778 tcg_gen_trunc_i64_i32(c
->u
.s32
.a
, cc_src
);
779 c
->u
.s32
.b
= tcg_temp_new_i32();
780 tcg_gen_trunc_i64_i32(c
->u
.s32
.b
, cc_dst
);
787 c
->u
.s64
.b
= tcg_const_i64(0);
791 case CC_OP_LTUGTU_64
:
795 c
->g1
= c
->g2
= true;
801 c
->u
.s64
.a
= tcg_temp_new_i64();
802 c
->u
.s64
.b
= tcg_const_i64(0);
803 tcg_gen_and_i64(c
->u
.s64
.a
, cc_src
, cc_dst
);
808 c
->u
.s32
.a
= tcg_temp_new_i32();
809 c
->u
.s32
.b
= tcg_temp_new_i32();
810 tcg_gen_trunc_i64_i32(c
->u
.s32
.a
, cc_vr
);
811 if (cond
== TCG_COND_EQ
|| cond
== TCG_COND_NE
) {
812 tcg_gen_movi_i32(c
->u
.s32
.b
, 0);
814 tcg_gen_trunc_i64_i32(c
->u
.s32
.b
, cc_src
);
821 if (cond
== TCG_COND_EQ
|| cond
== TCG_COND_NE
) {
822 c
->u
.s64
.b
= tcg_const_i64(0);
834 case 0x8 | 0x4 | 0x2: /* cc != 3 */
836 c
->u
.s32
.b
= tcg_const_i32(3);
838 case 0x8 | 0x4 | 0x1: /* cc != 2 */
840 c
->u
.s32
.b
= tcg_const_i32(2);
842 case 0x8 | 0x2 | 0x1: /* cc != 1 */
844 c
->u
.s32
.b
= tcg_const_i32(1);
846 case 0x8 | 0x2: /* cc == 0 ||Â cc == 2 => (cc & 1) == 0 */
849 c
->u
.s32
.a
= tcg_temp_new_i32();
850 c
->u
.s32
.b
= tcg_const_i32(0);
851 tcg_gen_andi_i32(c
->u
.s32
.a
, cc_op
, 1);
853 case 0x8 | 0x4: /* cc < 2 */
855 c
->u
.s32
.b
= tcg_const_i32(2);
857 case 0x8: /* cc == 0 */
859 c
->u
.s32
.b
= tcg_const_i32(0);
861 case 0x4 | 0x2 | 0x1: /* cc != 0 */
863 c
->u
.s32
.b
= tcg_const_i32(0);
865 case 0x4 | 0x1: /* cc == 1 ||Â cc == 3 => (cc & 1) != 0 */
868 c
->u
.s32
.a
= tcg_temp_new_i32();
869 c
->u
.s32
.b
= tcg_const_i32(0);
870 tcg_gen_andi_i32(c
->u
.s32
.a
, cc_op
, 1);
872 case 0x4: /* cc == 1 */
874 c
->u
.s32
.b
= tcg_const_i32(1);
876 case 0x2 | 0x1: /* cc > 1 */
878 c
->u
.s32
.b
= tcg_const_i32(1);
880 case 0x2: /* cc == 2 */
882 c
->u
.s32
.b
= tcg_const_i32(2);
884 case 0x1: /* cc == 3 */
886 c
->u
.s32
.b
= tcg_const_i32(3);
889 /* CC is masked by something else: (8 >> cc) & mask. */
892 c
->u
.s32
.a
= tcg_const_i32(8);
893 c
->u
.s32
.b
= tcg_const_i32(0);
894 tcg_gen_shr_i32(c
->u
.s32
.a
, c
->u
.s32
.a
, cc_op
);
895 tcg_gen_andi_i32(c
->u
.s32
.a
, c
->u
.s32
.a
, mask
);
906 static void free_compare(DisasCompare
*c
)
910 tcg_temp_free_i64(c
->u
.s64
.a
);
912 tcg_temp_free_i32(c
->u
.s32
.a
);
917 tcg_temp_free_i64(c
->u
.s64
.b
);
919 tcg_temp_free_i32(c
->u
.s32
.b
);
924 /* ====================================================================== */
925 /* Define the insn format enumeration. */
926 #define F0(N) FMT_##N,
927 #define F1(N, X1) F0(N)
928 #define F2(N, X1, X2) F0(N)
929 #define F3(N, X1, X2, X3) F0(N)
930 #define F4(N, X1, X2, X3, X4) F0(N)
931 #define F5(N, X1, X2, X3, X4, X5) F0(N)
934 #include "insn-format.def"
944 /* Define a structure to hold the decoded fields. We'll store each inside
945 an array indexed by an enum. In order to conserve memory, we'll arrange
946 for fields that do not exist at the same time to overlap, thus the "C"
947 for compact. For checking purposes there is an "O" for original index
948 as well that will be applied to availability bitmaps. */
950 enum DisasFieldIndexO
{
973 enum DisasFieldIndexC
{
1004 struct DisasFields
{
1008 unsigned presentC
:16;
1009 unsigned int presentO
;
1013 /* This is the way fields are to be accessed out of DisasFields. */
1014 #define have_field(S, F) have_field1((S), FLD_O_##F)
1015 #define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
1017 static bool have_field1(const DisasFields
*f
, enum DisasFieldIndexO c
)
1019 return (f
->presentO
>> c
) & 1;
1022 static int get_field1(const DisasFields
*f
, enum DisasFieldIndexO o
,
1023 enum DisasFieldIndexC c
)
1025 assert(have_field1(f
, o
));
1029 /* Describe the layout of each field in each format. */
1030 typedef struct DisasField
{
1032 unsigned int size
:8;
1033 unsigned int type
:2;
1034 unsigned int indexC
:6;
1035 enum DisasFieldIndexO indexO
:8;
1038 typedef struct DisasFormatInfo
{
1039 DisasField op
[NUM_C_FIELD
];
1042 #define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
1043 #define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
1044 #define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1045 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
1046 #define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1047 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1048 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
1049 #define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1050 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1051 #define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1052 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1053 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1054 #define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
1055 #define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
1057 #define F0(N) { { } },
1058 #define F1(N, X1) { { X1 } },
1059 #define F2(N, X1, X2) { { X1, X2 } },
1060 #define F3(N, X1, X2, X3) { { X1, X2, X3 } },
1061 #define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
1062 #define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
1064 static const DisasFormatInfo format_info
[] = {
1065 #include "insn-format.def"
1083 /* Generally, we'll extract operands into this structures, operate upon
1084 them, and store them back. See the "in1", "in2", "prep", "wout" sets
1085 of routines below for more details. */
1087 bool g_out
, g_out2
, g_in1
, g_in2
;
1088 TCGv_i64 out
, out2
, in1
, in2
;
1092 /* Instructions can place constraints on their operands, raising specification
1093 exceptions if they are violated. To make this easy to automate, each "in1",
1094 "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
1095 of the following, or 0. To make this easy to document, we'll put the
1096 SPEC_<name> defines next to <name>. */
1098 #define SPEC_r1_even 1
1099 #define SPEC_r2_even 2
1100 #define SPEC_r3_even 4
1101 #define SPEC_r1_f128 8
1102 #define SPEC_r2_f128 16
1104 /* Return values from translate_one, indicating the state of the TB. */
1106 /* Continue the TB. */
1108 /* We have emitted one or more goto_tb. No fixup required. */
1110 /* We are not using a goto_tb (for whatever reason), but have updated
1111 the PC (for whatever reason), so there's no need to do it again on
1114 /* We are exiting the TB, but have neither emitted a goto_tb, nor
1115 updated the PC for the next instruction to be executed. */
1117 /* We are ending the TB with a noreturn function call, e.g. longjmp.
1118 No following code will be executed. */
1122 typedef enum DisasFacility
{
1123 FAC_Z
, /* zarch (default) */
1124 FAC_CASS
, /* compare and swap and store */
1125 FAC_CASS2
, /* compare and swap and store 2*/
1126 FAC_DFP
, /* decimal floating point */
1127 FAC_DFPR
, /* decimal floating point rounding */
1128 FAC_DO
, /* distinct operands */
1129 FAC_EE
, /* execute extensions */
1130 FAC_EI
, /* extended immediate */
1131 FAC_FPE
, /* floating point extension */
1132 FAC_FPSSH
, /* floating point support sign handling */
1133 FAC_FPRGR
, /* FPR-GR transfer */
1134 FAC_GIE
, /* general instructions extension */
1135 FAC_HFP_MA
, /* HFP multiply-and-add/subtract */
1136 FAC_HW
, /* high-word */
1137 FAC_IEEEE_SIM
, /* IEEE exception sumilation */
1138 FAC_MIE
, /* miscellaneous-instruction-extensions */
1139 FAC_LAT
, /* load-and-trap */
1140 FAC_LOC
, /* load/store on condition */
1141 FAC_LD
, /* long displacement */
1142 FAC_PC
, /* population count */
1143 FAC_SCF
, /* store clock fast */
1144 FAC_SFLE
, /* store facility list extended */
1145 FAC_ILA
, /* interlocked access facility 1 */
1151 DisasFacility fac
:8;
1156 void (*help_in1
)(DisasContext
*, DisasFields
*, DisasOps
*);
1157 void (*help_in2
)(DisasContext
*, DisasFields
*, DisasOps
*);
1158 void (*help_prep
)(DisasContext
*, DisasFields
*, DisasOps
*);
1159 void (*help_wout
)(DisasContext
*, DisasFields
*, DisasOps
*);
1160 void (*help_cout
)(DisasContext
*, DisasOps
*);
1161 ExitStatus (*help_op
)(DisasContext
*, DisasOps
*);
1166 /* ====================================================================== */
1167 /* Miscellaneous helpers, used by several operations. */
1169 static void help_l2_shift(DisasContext
*s
, DisasFields
*f
,
1170 DisasOps
*o
, int mask
)
1172 int b2
= get_field(f
, b2
);
1173 int d2
= get_field(f
, d2
);
1176 o
->in2
= tcg_const_i64(d2
& mask
);
1178 o
->in2
= get_address(s
, 0, b2
, d2
);
1179 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
1183 static ExitStatus
help_goto_direct(DisasContext
*s
, uint64_t dest
)
1185 if (dest
== s
->next_pc
) {
1188 if (use_goto_tb(s
, dest
)) {
1191 tcg_gen_movi_i64(psw_addr
, dest
);
1192 tcg_gen_exit_tb((uintptr_t)s
->tb
);
1193 return EXIT_GOTO_TB
;
1195 tcg_gen_movi_i64(psw_addr
, dest
);
1196 return EXIT_PC_UPDATED
;
1200 static ExitStatus
help_branch(DisasContext
*s
, DisasCompare
*c
,
1201 bool is_imm
, int imm
, TCGv_i64 cdest
)
1204 uint64_t dest
= s
->pc
+ 2 * imm
;
1207 /* Take care of the special cases first. */
1208 if (c
->cond
== TCG_COND_NEVER
) {
1213 if (dest
== s
->next_pc
) {
1214 /* Branch to next. */
1218 if (c
->cond
== TCG_COND_ALWAYS
) {
1219 ret
= help_goto_direct(s
, dest
);
1223 if (TCGV_IS_UNUSED_I64(cdest
)) {
1224 /* E.g. bcr %r0 -> no branch. */
1228 if (c
->cond
== TCG_COND_ALWAYS
) {
1229 tcg_gen_mov_i64(psw_addr
, cdest
);
1230 ret
= EXIT_PC_UPDATED
;
1235 if (use_goto_tb(s
, s
->next_pc
)) {
1236 if (is_imm
&& use_goto_tb(s
, dest
)) {
1237 /* Both exits can use goto_tb. */
1240 lab
= gen_new_label();
1242 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1244 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1247 /* Branch not taken. */
1249 tcg_gen_movi_i64(psw_addr
, s
->next_pc
);
1250 tcg_gen_exit_tb((uintptr_t)s
->tb
+ 0);
1255 tcg_gen_movi_i64(psw_addr
, dest
);
1256 tcg_gen_exit_tb((uintptr_t)s
->tb
+ 1);
1260 /* Fallthru can use goto_tb, but taken branch cannot. */
1261 /* Store taken branch destination before the brcond. This
1262 avoids having to allocate a new local temp to hold it.
1263 We'll overwrite this in the not taken case anyway. */
1265 tcg_gen_mov_i64(psw_addr
, cdest
);
1268 lab
= gen_new_label();
1270 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1272 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1275 /* Branch not taken. */
1278 tcg_gen_movi_i64(psw_addr
, s
->next_pc
);
1279 tcg_gen_exit_tb((uintptr_t)s
->tb
+ 0);
1283 tcg_gen_movi_i64(psw_addr
, dest
);
1285 ret
= EXIT_PC_UPDATED
;
1288 /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
1289 Most commonly we're single-stepping or some other condition that
1290 disables all use of goto_tb. Just update the PC and exit. */
1292 TCGv_i64 next
= tcg_const_i64(s
->next_pc
);
1294 cdest
= tcg_const_i64(dest
);
1298 tcg_gen_movcond_i64(c
->cond
, psw_addr
, c
->u
.s64
.a
, c
->u
.s64
.b
,
1301 TCGv_i32 t0
= tcg_temp_new_i32();
1302 TCGv_i64 t1
= tcg_temp_new_i64();
1303 TCGv_i64 z
= tcg_const_i64(0);
1304 tcg_gen_setcond_i32(c
->cond
, t0
, c
->u
.s32
.a
, c
->u
.s32
.b
);
1305 tcg_gen_extu_i32_i64(t1
, t0
);
1306 tcg_temp_free_i32(t0
);
1307 tcg_gen_movcond_i64(TCG_COND_NE
, psw_addr
, t1
, z
, cdest
, next
);
1308 tcg_temp_free_i64(t1
);
1309 tcg_temp_free_i64(z
);
1313 tcg_temp_free_i64(cdest
);
1315 tcg_temp_free_i64(next
);
1317 ret
= EXIT_PC_UPDATED
;
1325 /* ====================================================================== */
1326 /* The operations. These perform the bulk of the work for any insn,
1327 usually after the operands have been loaded and output initialized. */
1329 static ExitStatus
op_abs(DisasContext
*s
, DisasOps
*o
)
1332 z
= tcg_const_i64(0);
1333 n
= tcg_temp_new_i64();
1334 tcg_gen_neg_i64(n
, o
->in2
);
1335 tcg_gen_movcond_i64(TCG_COND_LT
, o
->out
, o
->in2
, z
, n
, o
->in2
);
1336 tcg_temp_free_i64(n
);
1337 tcg_temp_free_i64(z
);
1341 static ExitStatus
op_absf32(DisasContext
*s
, DisasOps
*o
)
1343 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffull
);
1347 static ExitStatus
op_absf64(DisasContext
*s
, DisasOps
*o
)
1349 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffffffffffull
);
1353 static ExitStatus
op_absf128(DisasContext
*s
, DisasOps
*o
)
1355 tcg_gen_andi_i64(o
->out
, o
->in1
, 0x7fffffffffffffffull
);
1356 tcg_gen_mov_i64(o
->out2
, o
->in2
);
1360 static ExitStatus
op_add(DisasContext
*s
, DisasOps
*o
)
1362 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1366 static ExitStatus
op_addc(DisasContext
*s
, DisasOps
*o
)
1371 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1373 /* The carry flag is the msb of CC, therefore the branch mask that would
1374 create that comparison is 3. Feeding the generated comparison to
1375 setcond produces the carry flag that we desire. */
1376 disas_jcc(s
, &cmp
, 3);
1377 carry
= tcg_temp_new_i64();
1379 tcg_gen_setcond_i64(cmp
.cond
, carry
, cmp
.u
.s64
.a
, cmp
.u
.s64
.b
);
1381 TCGv_i32 t
= tcg_temp_new_i32();
1382 tcg_gen_setcond_i32(cmp
.cond
, t
, cmp
.u
.s32
.a
, cmp
.u
.s32
.b
);
1383 tcg_gen_extu_i32_i64(carry
, t
);
1384 tcg_temp_free_i32(t
);
1388 tcg_gen_add_i64(o
->out
, o
->out
, carry
);
1389 tcg_temp_free_i64(carry
);
1393 static ExitStatus
op_aeb(DisasContext
*s
, DisasOps
*o
)
1395 gen_helper_aeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
1399 static ExitStatus
op_adb(DisasContext
*s
, DisasOps
*o
)
1401 gen_helper_adb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
1405 static ExitStatus
op_axb(DisasContext
*s
, DisasOps
*o
)
1407 gen_helper_axb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
1408 return_low128(o
->out2
);
1412 static ExitStatus
op_and(DisasContext
*s
, DisasOps
*o
)
1414 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
1418 static ExitStatus
op_andi(DisasContext
*s
, DisasOps
*o
)
1420 int shift
= s
->insn
->data
& 0xff;
1421 int size
= s
->insn
->data
>> 8;
1422 uint64_t mask
= ((1ull << size
) - 1) << shift
;
1425 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
1426 tcg_gen_ori_i64(o
->in2
, o
->in2
, ~mask
);
1427 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
1429 /* Produce the CC from only the bits manipulated. */
1430 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
1431 set_cc_nz_u64(s
, cc_dst
);
1435 static ExitStatus
op_bas(DisasContext
*s
, DisasOps
*o
)
1437 tcg_gen_movi_i64(o
->out
, pc_to_link_info(s
, s
->next_pc
));
1438 if (!TCGV_IS_UNUSED_I64(o
->in2
)) {
1439 tcg_gen_mov_i64(psw_addr
, o
->in2
);
1440 return EXIT_PC_UPDATED
;
1446 static ExitStatus
op_basi(DisasContext
*s
, DisasOps
*o
)
1448 tcg_gen_movi_i64(o
->out
, pc_to_link_info(s
, s
->next_pc
));
1449 return help_goto_direct(s
, s
->pc
+ 2 * get_field(s
->fields
, i2
));
1452 static ExitStatus
op_bc(DisasContext
*s
, DisasOps
*o
)
1454 int m1
= get_field(s
->fields
, m1
);
1455 bool is_imm
= have_field(s
->fields
, i2
);
1456 int imm
= is_imm
? get_field(s
->fields
, i2
) : 0;
1459 disas_jcc(s
, &c
, m1
);
1460 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1463 static ExitStatus
op_bct32(DisasContext
*s
, DisasOps
*o
)
1465 int r1
= get_field(s
->fields
, r1
);
1466 bool is_imm
= have_field(s
->fields
, i2
);
1467 int imm
= is_imm
? get_field(s
->fields
, i2
) : 0;
1471 c
.cond
= TCG_COND_NE
;
1476 t
= tcg_temp_new_i64();
1477 tcg_gen_subi_i64(t
, regs
[r1
], 1);
1478 store_reg32_i64(r1
, t
);
1479 c
.u
.s32
.a
= tcg_temp_new_i32();
1480 c
.u
.s32
.b
= tcg_const_i32(0);
1481 tcg_gen_trunc_i64_i32(c
.u
.s32
.a
, t
);
1482 tcg_temp_free_i64(t
);
1484 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1487 static ExitStatus
op_bcth(DisasContext
*s
, DisasOps
*o
)
1489 int r1
= get_field(s
->fields
, r1
);
1490 int imm
= get_field(s
->fields
, i2
);
1494 c
.cond
= TCG_COND_NE
;
1499 t
= tcg_temp_new_i64();
1500 tcg_gen_shri_i64(t
, regs
[r1
], 32);
1501 tcg_gen_subi_i64(t
, t
, 1);
1502 store_reg32h_i64(r1
, t
);
1503 c
.u
.s32
.a
= tcg_temp_new_i32();
1504 c
.u
.s32
.b
= tcg_const_i32(0);
1505 tcg_gen_trunc_i64_i32(c
.u
.s32
.a
, t
);
1506 tcg_temp_free_i64(t
);
1508 return help_branch(s
, &c
, 1, imm
, o
->in2
);
1511 static ExitStatus
op_bct64(DisasContext
*s
, DisasOps
*o
)
1513 int r1
= get_field(s
->fields
, r1
);
1514 bool is_imm
= have_field(s
->fields
, i2
);
1515 int imm
= is_imm
? get_field(s
->fields
, i2
) : 0;
1518 c
.cond
= TCG_COND_NE
;
1523 tcg_gen_subi_i64(regs
[r1
], regs
[r1
], 1);
1524 c
.u
.s64
.a
= regs
[r1
];
1525 c
.u
.s64
.b
= tcg_const_i64(0);
1527 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1530 static ExitStatus
op_bx32(DisasContext
*s
, DisasOps
*o
)
1532 int r1
= get_field(s
->fields
, r1
);
1533 int r3
= get_field(s
->fields
, r3
);
1534 bool is_imm
= have_field(s
->fields
, i2
);
1535 int imm
= is_imm
? get_field(s
->fields
, i2
) : 0;
1539 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
1544 t
= tcg_temp_new_i64();
1545 tcg_gen_add_i64(t
, regs
[r1
], regs
[r3
]);
1546 c
.u
.s32
.a
= tcg_temp_new_i32();
1547 c
.u
.s32
.b
= tcg_temp_new_i32();
1548 tcg_gen_trunc_i64_i32(c
.u
.s32
.a
, t
);
1549 tcg_gen_trunc_i64_i32(c
.u
.s32
.b
, regs
[r3
| 1]);
1550 store_reg32_i64(r1
, t
);
1551 tcg_temp_free_i64(t
);
1553 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1556 static ExitStatus
op_bx64(DisasContext
*s
, DisasOps
*o
)
1558 int r1
= get_field(s
->fields
, r1
);
1559 int r3
= get_field(s
->fields
, r3
);
1560 bool is_imm
= have_field(s
->fields
, i2
);
1561 int imm
= is_imm
? get_field(s
->fields
, i2
) : 0;
1564 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
1567 if (r1
== (r3
| 1)) {
1568 c
.u
.s64
.b
= load_reg(r3
| 1);
1571 c
.u
.s64
.b
= regs
[r3
| 1];
1575 tcg_gen_add_i64(regs
[r1
], regs
[r1
], regs
[r3
]);
1576 c
.u
.s64
.a
= regs
[r1
];
1579 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1582 static ExitStatus
op_cj(DisasContext
*s
, DisasOps
*o
)
1584 int imm
, m3
= get_field(s
->fields
, m3
);
1588 c
.cond
= ltgt_cond
[m3
];
1589 if (s
->insn
->data
) {
1590 c
.cond
= tcg_unsigned_cond(c
.cond
);
1592 c
.is_64
= c
.g1
= c
.g2
= true;
1596 is_imm
= have_field(s
->fields
, i4
);
1598 imm
= get_field(s
->fields
, i4
);
1601 o
->out
= get_address(s
, 0, get_field(s
->fields
, b4
),
1602 get_field(s
->fields
, d4
));
1605 return help_branch(s
, &c
, is_imm
, imm
, o
->out
);
1608 static ExitStatus
op_ceb(DisasContext
*s
, DisasOps
*o
)
1610 gen_helper_ceb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
1615 static ExitStatus
op_cdb(DisasContext
*s
, DisasOps
*o
)
1617 gen_helper_cdb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
1622 static ExitStatus
op_cxb(DisasContext
*s
, DisasOps
*o
)
1624 gen_helper_cxb(cc_op
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
1629 static ExitStatus
op_cfeb(DisasContext
*s
, DisasOps
*o
)
1631 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1632 gen_helper_cfeb(o
->out
, cpu_env
, o
->in2
, m3
);
1633 tcg_temp_free_i32(m3
);
1634 gen_set_cc_nz_f32(s
, o
->in2
);
1638 static ExitStatus
op_cfdb(DisasContext
*s
, DisasOps
*o
)
1640 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1641 gen_helper_cfdb(o
->out
, cpu_env
, o
->in2
, m3
);
1642 tcg_temp_free_i32(m3
);
1643 gen_set_cc_nz_f64(s
, o
->in2
);
1647 static ExitStatus
op_cfxb(DisasContext
*s
, DisasOps
*o
)
1649 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1650 gen_helper_cfxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m3
);
1651 tcg_temp_free_i32(m3
);
1652 gen_set_cc_nz_f128(s
, o
->in1
, o
->in2
);
1656 static ExitStatus
op_cgeb(DisasContext
*s
, DisasOps
*o
)
1658 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1659 gen_helper_cgeb(o
->out
, cpu_env
, o
->in2
, m3
);
1660 tcg_temp_free_i32(m3
);
1661 gen_set_cc_nz_f32(s
, o
->in2
);
1665 static ExitStatus
op_cgdb(DisasContext
*s
, DisasOps
*o
)
1667 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1668 gen_helper_cgdb(o
->out
, cpu_env
, o
->in2
, m3
);
1669 tcg_temp_free_i32(m3
);
1670 gen_set_cc_nz_f64(s
, o
->in2
);
1674 static ExitStatus
op_cgxb(DisasContext
*s
, DisasOps
*o
)
1676 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1677 gen_helper_cgxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m3
);
1678 tcg_temp_free_i32(m3
);
1679 gen_set_cc_nz_f128(s
, o
->in1
, o
->in2
);
1683 static ExitStatus
op_clfeb(DisasContext
*s
, DisasOps
*o
)
1685 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1686 gen_helper_clfeb(o
->out
, cpu_env
, o
->in2
, m3
);
1687 tcg_temp_free_i32(m3
);
1688 gen_set_cc_nz_f32(s
, o
->in2
);
1692 static ExitStatus
op_clfdb(DisasContext
*s
, DisasOps
*o
)
1694 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1695 gen_helper_clfdb(o
->out
, cpu_env
, o
->in2
, m3
);
1696 tcg_temp_free_i32(m3
);
1697 gen_set_cc_nz_f64(s
, o
->in2
);
1701 static ExitStatus
op_clfxb(DisasContext
*s
, DisasOps
*o
)
1703 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1704 gen_helper_clfxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m3
);
1705 tcg_temp_free_i32(m3
);
1706 gen_set_cc_nz_f128(s
, o
->in1
, o
->in2
);
1710 static ExitStatus
op_clgeb(DisasContext
*s
, DisasOps
*o
)
1712 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1713 gen_helper_clgeb(o
->out
, cpu_env
, o
->in2
, m3
);
1714 tcg_temp_free_i32(m3
);
1715 gen_set_cc_nz_f32(s
, o
->in2
);
1719 static ExitStatus
op_clgdb(DisasContext
*s
, DisasOps
*o
)
1721 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1722 gen_helper_clgdb(o
->out
, cpu_env
, o
->in2
, m3
);
1723 tcg_temp_free_i32(m3
);
1724 gen_set_cc_nz_f64(s
, o
->in2
);
1728 static ExitStatus
op_clgxb(DisasContext
*s
, DisasOps
*o
)
1730 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1731 gen_helper_clgxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m3
);
1732 tcg_temp_free_i32(m3
);
1733 gen_set_cc_nz_f128(s
, o
->in1
, o
->in2
);
1737 static ExitStatus
op_cegb(DisasContext
*s
, DisasOps
*o
)
1739 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1740 gen_helper_cegb(o
->out
, cpu_env
, o
->in2
, m3
);
1741 tcg_temp_free_i32(m3
);
1745 static ExitStatus
op_cdgb(DisasContext
*s
, DisasOps
*o
)
1747 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1748 gen_helper_cdgb(o
->out
, cpu_env
, o
->in2
, m3
);
1749 tcg_temp_free_i32(m3
);
1753 static ExitStatus
op_cxgb(DisasContext
*s
, DisasOps
*o
)
1755 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1756 gen_helper_cxgb(o
->out
, cpu_env
, o
->in2
, m3
);
1757 tcg_temp_free_i32(m3
);
1758 return_low128(o
->out2
);
1762 static ExitStatus
op_celgb(DisasContext
*s
, DisasOps
*o
)
1764 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1765 gen_helper_celgb(o
->out
, cpu_env
, o
->in2
, m3
);
1766 tcg_temp_free_i32(m3
);
1770 static ExitStatus
op_cdlgb(DisasContext
*s
, DisasOps
*o
)
1772 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1773 gen_helper_cdlgb(o
->out
, cpu_env
, o
->in2
, m3
);
1774 tcg_temp_free_i32(m3
);
1778 static ExitStatus
op_cxlgb(DisasContext
*s
, DisasOps
*o
)
1780 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1781 gen_helper_cxlgb(o
->out
, cpu_env
, o
->in2
, m3
);
1782 tcg_temp_free_i32(m3
);
1783 return_low128(o
->out2
);
1787 static ExitStatus
op_cksm(DisasContext
*s
, DisasOps
*o
)
1789 int r2
= get_field(s
->fields
, r2
);
1790 TCGv_i64 len
= tcg_temp_new_i64();
1792 potential_page_fault(s
);
1793 gen_helper_cksm(len
, cpu_env
, o
->in1
, o
->in2
, regs
[r2
+ 1]);
1795 return_low128(o
->out
);
1797 tcg_gen_add_i64(regs
[r2
], regs
[r2
], len
);
1798 tcg_gen_sub_i64(regs
[r2
+ 1], regs
[r2
+ 1], len
);
1799 tcg_temp_free_i64(len
);
1804 static ExitStatus
op_clc(DisasContext
*s
, DisasOps
*o
)
1806 int l
= get_field(s
->fields
, l1
);
1811 tcg_gen_qemu_ld8u(cc_src
, o
->addr1
, get_mem_index(s
));
1812 tcg_gen_qemu_ld8u(cc_dst
, o
->in2
, get_mem_index(s
));
1815 tcg_gen_qemu_ld16u(cc_src
, o
->addr1
, get_mem_index(s
));
1816 tcg_gen_qemu_ld16u(cc_dst
, o
->in2
, get_mem_index(s
));
1819 tcg_gen_qemu_ld32u(cc_src
, o
->addr1
, get_mem_index(s
));
1820 tcg_gen_qemu_ld32u(cc_dst
, o
->in2
, get_mem_index(s
));
1823 tcg_gen_qemu_ld64(cc_src
, o
->addr1
, get_mem_index(s
));
1824 tcg_gen_qemu_ld64(cc_dst
, o
->in2
, get_mem_index(s
));
1827 potential_page_fault(s
);
1828 vl
= tcg_const_i32(l
);
1829 gen_helper_clc(cc_op
, cpu_env
, vl
, o
->addr1
, o
->in2
);
1830 tcg_temp_free_i32(vl
);
1834 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_64
, cc_src
, cc_dst
);
1838 static ExitStatus
op_clcle(DisasContext
*s
, DisasOps
*o
)
1840 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
1841 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
1842 potential_page_fault(s
);
1843 gen_helper_clcle(cc_op
, cpu_env
, r1
, o
->in2
, r3
);
1844 tcg_temp_free_i32(r1
);
1845 tcg_temp_free_i32(r3
);
1850 static ExitStatus
op_clm(DisasContext
*s
, DisasOps
*o
)
1852 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
1853 TCGv_i32 t1
= tcg_temp_new_i32();
1854 tcg_gen_trunc_i64_i32(t1
, o
->in1
);
1855 potential_page_fault(s
);
1856 gen_helper_clm(cc_op
, cpu_env
, t1
, m3
, o
->in2
);
1858 tcg_temp_free_i32(t1
);
1859 tcg_temp_free_i32(m3
);
1863 static ExitStatus
op_clst(DisasContext
*s
, DisasOps
*o
)
1865 potential_page_fault(s
);
1866 gen_helper_clst(o
->in1
, cpu_env
, regs
[0], o
->in1
, o
->in2
);
1868 return_low128(o
->in2
);
1872 static ExitStatus
op_cps(DisasContext
*s
, DisasOps
*o
)
1874 TCGv_i64 t
= tcg_temp_new_i64();
1875 tcg_gen_andi_i64(t
, o
->in1
, 0x8000000000000000ull
);
1876 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffffffffffull
);
1877 tcg_gen_or_i64(o
->out
, o
->out
, t
);
1878 tcg_temp_free_i64(t
);
1882 static ExitStatus
op_cs(DisasContext
*s
, DisasOps
*o
)
1884 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1885 int d2
= get_field(s
->fields
, d2
);
1886 int b2
= get_field(s
->fields
, b2
);
1887 int is_64
= s
->insn
->data
;
1888 TCGv_i64 addr
, mem
, cc
, z
;
1890 /* Note that in1 = R3 (new value) and
1891 in2 = (zero-extended) R1 (expected value). */
1893 /* Load the memory into the (temporary) output. While the PoO only talks
1894 about moving the memory to R1 on inequality, if we include equality it
1895 means that R1 is equal to the memory in all conditions. */
1896 addr
= get_address(s
, 0, b2
, d2
);
1898 tcg_gen_qemu_ld64(o
->out
, addr
, get_mem_index(s
));
1900 tcg_gen_qemu_ld32u(o
->out
, addr
, get_mem_index(s
));
1903 /* Are the memory and expected values (un)equal? Note that this setcond
1904 produces the output CC value, thus the NE sense of the test. */
1905 cc
= tcg_temp_new_i64();
1906 tcg_gen_setcond_i64(TCG_COND_NE
, cc
, o
->in2
, o
->out
);
1908 /* If the memory and expected values are equal (CC==0), copy R3 to MEM.
1909 Recall that we are allowed to unconditionally issue the store (and
1910 thus any possible write trap), so (re-)store the original contents
1911 of MEM in case of inequality. */
1912 z
= tcg_const_i64(0);
1913 mem
= tcg_temp_new_i64();
1914 tcg_gen_movcond_i64(TCG_COND_EQ
, mem
, cc
, z
, o
->in1
, o
->out
);
1916 tcg_gen_qemu_st64(mem
, addr
, get_mem_index(s
));
1918 tcg_gen_qemu_st32(mem
, addr
, get_mem_index(s
));
1920 tcg_temp_free_i64(z
);
1921 tcg_temp_free_i64(mem
);
1922 tcg_temp_free_i64(addr
);
1924 /* Store CC back to cc_op. Wait until after the store so that any
1925 exception gets the old cc_op value. */
1926 tcg_gen_trunc_i64_i32(cc_op
, cc
);
1927 tcg_temp_free_i64(cc
);
1932 static ExitStatus
op_cdsg(DisasContext
*s
, DisasOps
*o
)
1934 /* FIXME: needs an atomic solution for CONFIG_USER_ONLY. */
1935 int r1
= get_field(s
->fields
, r1
);
1936 int r3
= get_field(s
->fields
, r3
);
1937 int d2
= get_field(s
->fields
, d2
);
1938 int b2
= get_field(s
->fields
, b2
);
1939 TCGv_i64 addrh
, addrl
, memh
, meml
, outh
, outl
, cc
, z
;
1941 /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
1943 addrh
= get_address(s
, 0, b2
, d2
);
1944 addrl
= get_address(s
, 0, b2
, d2
+ 8);
1945 outh
= tcg_temp_new_i64();
1946 outl
= tcg_temp_new_i64();
1948 tcg_gen_qemu_ld64(outh
, addrh
, get_mem_index(s
));
1949 tcg_gen_qemu_ld64(outl
, addrl
, get_mem_index(s
));
1951 /* Fold the double-word compare with arithmetic. */
1952 cc
= tcg_temp_new_i64();
1953 z
= tcg_temp_new_i64();
1954 tcg_gen_xor_i64(cc
, outh
, regs
[r1
]);
1955 tcg_gen_xor_i64(z
, outl
, regs
[r1
+ 1]);
1956 tcg_gen_or_i64(cc
, cc
, z
);
1957 tcg_gen_movi_i64(z
, 0);
1958 tcg_gen_setcond_i64(TCG_COND_NE
, cc
, cc
, z
);
1960 memh
= tcg_temp_new_i64();
1961 meml
= tcg_temp_new_i64();
1962 tcg_gen_movcond_i64(TCG_COND_EQ
, memh
, cc
, z
, regs
[r3
], outh
);
1963 tcg_gen_movcond_i64(TCG_COND_EQ
, meml
, cc
, z
, regs
[r3
+ 1], outl
);
1964 tcg_temp_free_i64(z
);
1966 tcg_gen_qemu_st64(memh
, addrh
, get_mem_index(s
));
1967 tcg_gen_qemu_st64(meml
, addrl
, get_mem_index(s
));
1968 tcg_temp_free_i64(memh
);
1969 tcg_temp_free_i64(meml
);
1970 tcg_temp_free_i64(addrh
);
1971 tcg_temp_free_i64(addrl
);
1973 /* Save back state now that we've passed all exceptions. */
1974 tcg_gen_mov_i64(regs
[r1
], outh
);
1975 tcg_gen_mov_i64(regs
[r1
+ 1], outl
);
1976 tcg_gen_trunc_i64_i32(cc_op
, cc
);
1977 tcg_temp_free_i64(outh
);
1978 tcg_temp_free_i64(outl
);
1979 tcg_temp_free_i64(cc
);
1984 #ifndef CONFIG_USER_ONLY
1985 static ExitStatus
op_csp(DisasContext
*s
, DisasOps
*o
)
1987 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
1988 check_privileged(s
);
1989 gen_helper_csp(cc_op
, cpu_env
, r1
, o
->in2
);
1990 tcg_temp_free_i32(r1
);
1996 static ExitStatus
op_cvd(DisasContext
*s
, DisasOps
*o
)
1998 TCGv_i64 t1
= tcg_temp_new_i64();
1999 TCGv_i32 t2
= tcg_temp_new_i32();
2000 tcg_gen_trunc_i64_i32(t2
, o
->in1
);
2001 gen_helper_cvd(t1
, t2
);
2002 tcg_temp_free_i32(t2
);
2003 tcg_gen_qemu_st64(t1
, o
->in2
, get_mem_index(s
));
2004 tcg_temp_free_i64(t1
);
2008 static ExitStatus
op_ct(DisasContext
*s
, DisasOps
*o
)
2010 int m3
= get_field(s
->fields
, m3
);
2011 TCGLabel
*lab
= gen_new_label();
2014 c
= tcg_invert_cond(ltgt_cond
[m3
]);
2015 if (s
->insn
->data
) {
2016 c
= tcg_unsigned_cond(c
);
2018 tcg_gen_brcond_i64(c
, o
->in1
, o
->in2
, lab
);
2027 #ifndef CONFIG_USER_ONLY
2028 static ExitStatus
op_diag(DisasContext
*s
, DisasOps
*o
)
2030 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2031 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
2032 TCGv_i32 func_code
= tcg_const_i32(get_field(s
->fields
, i2
));
2034 check_privileged(s
);
2038 gen_helper_diag(cpu_env
, r1
, r3
, func_code
);
2040 tcg_temp_free_i32(func_code
);
2041 tcg_temp_free_i32(r3
);
2042 tcg_temp_free_i32(r1
);
2047 static ExitStatus
op_divs32(DisasContext
*s
, DisasOps
*o
)
2049 gen_helper_divs32(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2050 return_low128(o
->out
);
2054 static ExitStatus
op_divu32(DisasContext
*s
, DisasOps
*o
)
2056 gen_helper_divu32(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2057 return_low128(o
->out
);
2061 static ExitStatus
op_divs64(DisasContext
*s
, DisasOps
*o
)
2063 gen_helper_divs64(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2064 return_low128(o
->out
);
2068 static ExitStatus
op_divu64(DisasContext
*s
, DisasOps
*o
)
2070 gen_helper_divu64(o
->out2
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
2071 return_low128(o
->out
);
2075 static ExitStatus
op_deb(DisasContext
*s
, DisasOps
*o
)
2077 gen_helper_deb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2081 static ExitStatus
op_ddb(DisasContext
*s
, DisasOps
*o
)
2083 gen_helper_ddb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2087 static ExitStatus
op_dxb(DisasContext
*s
, DisasOps
*o
)
2089 gen_helper_dxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
2090 return_low128(o
->out2
);
2094 static ExitStatus
op_ear(DisasContext
*s
, DisasOps
*o
)
2096 int r2
= get_field(s
->fields
, r2
);
2097 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, aregs
[r2
]));
2101 static ExitStatus
op_ecag(DisasContext
*s
, DisasOps
*o
)
2103 /* No cache information provided. */
2104 tcg_gen_movi_i64(o
->out
, -1);
2108 static ExitStatus
op_efpc(DisasContext
*s
, DisasOps
*o
)
2110 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, fpc
));
2114 static ExitStatus
op_epsw(DisasContext
*s
, DisasOps
*o
)
2116 int r1
= get_field(s
->fields
, r1
);
2117 int r2
= get_field(s
->fields
, r2
);
2118 TCGv_i64 t
= tcg_temp_new_i64();
2120 /* Note the "subsequently" in the PoO, which implies a defined result
2121 if r1 == r2. Thus we cannot defer these writes to an output hook. */
2122 tcg_gen_shri_i64(t
, psw_mask
, 32);
2123 store_reg32_i64(r1
, t
);
2125 store_reg32_i64(r2
, psw_mask
);
2128 tcg_temp_free_i64(t
);
2132 static ExitStatus
op_ex(DisasContext
*s
, DisasOps
*o
)
2134 /* ??? Perhaps a better way to implement EXECUTE is to set a bit in
2135 tb->flags, (ab)use the tb->cs_base field as the address of
2136 the template in memory, and grab 8 bits of tb->flags/cflags for
2137 the contents of the register. We would then recognize all this
2138 in gen_intermediate_code_internal, generating code for exactly
2139 one instruction. This new TB then gets executed normally.
2141 On the other hand, this seems to be mostly used for modifying
2142 MVC inside of memcpy, which needs a helper call anyway. So
2143 perhaps this doesn't bear thinking about any further. */
2150 tmp
= tcg_const_i64(s
->next_pc
);
2151 gen_helper_ex(cc_op
, cpu_env
, cc_op
, o
->in1
, o
->in2
, tmp
);
2152 tcg_temp_free_i64(tmp
);
2157 static ExitStatus
op_fieb(DisasContext
*s
, DisasOps
*o
)
2159 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
2160 gen_helper_fieb(o
->out
, cpu_env
, o
->in2
, m3
);
2161 tcg_temp_free_i32(m3
);
2165 static ExitStatus
op_fidb(DisasContext
*s
, DisasOps
*o
)
2167 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
2168 gen_helper_fidb(o
->out
, cpu_env
, o
->in2
, m3
);
2169 tcg_temp_free_i32(m3
);
2173 static ExitStatus
op_fixb(DisasContext
*s
, DisasOps
*o
)
2175 TCGv_i32 m3
= tcg_const_i32(get_field(s
->fields
, m3
));
2176 gen_helper_fixb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m3
);
2177 return_low128(o
->out2
);
2178 tcg_temp_free_i32(m3
);
2182 static ExitStatus
op_flogr(DisasContext
*s
, DisasOps
*o
)
2184 /* We'll use the original input for cc computation, since we get to
2185 compare that against 0, which ought to be better than comparing
2186 the real output against 64. It also lets cc_dst be a convenient
2187 temporary during our computation. */
2188 gen_op_update1_cc_i64(s
, CC_OP_FLOGR
, o
->in2
);
2190 /* R1 = IN ? CLZ(IN) : 64. */
2191 gen_helper_clz(o
->out
, o
->in2
);
2193 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2194 value by 64, which is undefined. But since the shift is 64 iff the
2195 input is zero, we still get the correct result after and'ing. */
2196 tcg_gen_movi_i64(o
->out2
, 0x8000000000000000ull
);
2197 tcg_gen_shr_i64(o
->out2
, o
->out2
, o
->out
);
2198 tcg_gen_andc_i64(o
->out2
, cc_dst
, o
->out2
);
2202 static ExitStatus
op_icm(DisasContext
*s
, DisasOps
*o
)
2204 int m3
= get_field(s
->fields
, m3
);
2205 int pos
, len
, base
= s
->insn
->data
;
2206 TCGv_i64 tmp
= tcg_temp_new_i64();
2211 /* Effectively a 32-bit load. */
2212 tcg_gen_qemu_ld32u(tmp
, o
->in2
, get_mem_index(s
));
2219 /* Effectively a 16-bit load. */
2220 tcg_gen_qemu_ld16u(tmp
, o
->in2
, get_mem_index(s
));
2228 /* Effectively an 8-bit load. */
2229 tcg_gen_qemu_ld8u(tmp
, o
->in2
, get_mem_index(s
));
2234 pos
= base
+ ctz32(m3
) * 8;
2235 tcg_gen_deposit_i64(o
->out
, o
->out
, tmp
, pos
, len
);
2236 ccm
= ((1ull << len
) - 1) << pos
;
2240 /* This is going to be a sequence of loads and inserts. */
2241 pos
= base
+ 32 - 8;
2245 tcg_gen_qemu_ld8u(tmp
, o
->in2
, get_mem_index(s
));
2246 tcg_gen_addi_i64(o
->in2
, o
->in2
, 1);
2247 tcg_gen_deposit_i64(o
->out
, o
->out
, tmp
, pos
, 8);
2250 m3
= (m3
<< 1) & 0xf;
2256 tcg_gen_movi_i64(tmp
, ccm
);
2257 gen_op_update2_cc_i64(s
, CC_OP_ICM
, tmp
, o
->out
);
2258 tcg_temp_free_i64(tmp
);
2262 static ExitStatus
op_insi(DisasContext
*s
, DisasOps
*o
)
2264 int shift
= s
->insn
->data
& 0xff;
2265 int size
= s
->insn
->data
>> 8;
2266 tcg_gen_deposit_i64(o
->out
, o
->in1
, o
->in2
, shift
, size
);
2270 static ExitStatus
op_ipm(DisasContext
*s
, DisasOps
*o
)
2275 tcg_gen_andi_i64(o
->out
, o
->out
, ~0xff000000ull
);
2277 t1
= tcg_temp_new_i64();
2278 tcg_gen_shli_i64(t1
, psw_mask
, 20);
2279 tcg_gen_shri_i64(t1
, t1
, 36);
2280 tcg_gen_or_i64(o
->out
, o
->out
, t1
);
2282 tcg_gen_extu_i32_i64(t1
, cc_op
);
2283 tcg_gen_shli_i64(t1
, t1
, 28);
2284 tcg_gen_or_i64(o
->out
, o
->out
, t1
);
2285 tcg_temp_free_i64(t1
);
2289 #ifndef CONFIG_USER_ONLY
2290 static ExitStatus
op_ipte(DisasContext
*s
, DisasOps
*o
)
2292 check_privileged(s
);
2293 gen_helper_ipte(cpu_env
, o
->in1
, o
->in2
);
2297 static ExitStatus
op_iske(DisasContext
*s
, DisasOps
*o
)
2299 check_privileged(s
);
2300 gen_helper_iske(o
->out
, cpu_env
, o
->in2
);
2305 static ExitStatus
op_ldeb(DisasContext
*s
, DisasOps
*o
)
2307 gen_helper_ldeb(o
->out
, cpu_env
, o
->in2
);
2311 static ExitStatus
op_ledb(DisasContext
*s
, DisasOps
*o
)
2313 gen_helper_ledb(o
->out
, cpu_env
, o
->in2
);
2317 static ExitStatus
op_ldxb(DisasContext
*s
, DisasOps
*o
)
2319 gen_helper_ldxb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2323 static ExitStatus
op_lexb(DisasContext
*s
, DisasOps
*o
)
2325 gen_helper_lexb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2329 static ExitStatus
op_lxdb(DisasContext
*s
, DisasOps
*o
)
2331 gen_helper_lxdb(o
->out
, cpu_env
, o
->in2
);
2332 return_low128(o
->out2
);
2336 static ExitStatus
op_lxeb(DisasContext
*s
, DisasOps
*o
)
2338 gen_helper_lxeb(o
->out
, cpu_env
, o
->in2
);
2339 return_low128(o
->out2
);
2343 static ExitStatus
op_llgt(DisasContext
*s
, DisasOps
*o
)
2345 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffff);
2349 static ExitStatus
op_ld8s(DisasContext
*s
, DisasOps
*o
)
2351 tcg_gen_qemu_ld8s(o
->out
, o
->in2
, get_mem_index(s
));
2355 static ExitStatus
op_ld8u(DisasContext
*s
, DisasOps
*o
)
2357 tcg_gen_qemu_ld8u(o
->out
, o
->in2
, get_mem_index(s
));
2361 static ExitStatus
op_ld16s(DisasContext
*s
, DisasOps
*o
)
2363 tcg_gen_qemu_ld16s(o
->out
, o
->in2
, get_mem_index(s
));
2367 static ExitStatus
op_ld16u(DisasContext
*s
, DisasOps
*o
)
2369 tcg_gen_qemu_ld16u(o
->out
, o
->in2
, get_mem_index(s
));
2373 static ExitStatus
op_ld32s(DisasContext
*s
, DisasOps
*o
)
2375 tcg_gen_qemu_ld32s(o
->out
, o
->in2
, get_mem_index(s
));
2379 static ExitStatus
op_ld32u(DisasContext
*s
, DisasOps
*o
)
2381 tcg_gen_qemu_ld32u(o
->out
, o
->in2
, get_mem_index(s
));
2385 static ExitStatus
op_ld64(DisasContext
*s
, DisasOps
*o
)
2387 tcg_gen_qemu_ld64(o
->out
, o
->in2
, get_mem_index(s
));
2391 static ExitStatus
op_lat(DisasContext
*s
, DisasOps
*o
)
2393 TCGLabel
*lab
= gen_new_label();
2394 store_reg32_i64(get_field(s
->fields
, r1
), o
->in2
);
2395 /* The value is stored even in case of trap. */
2396 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->in2
, 0, lab
);
2402 static ExitStatus
op_lgat(DisasContext
*s
, DisasOps
*o
)
2404 TCGLabel
*lab
= gen_new_label();
2405 tcg_gen_qemu_ld64(o
->out
, o
->in2
, get_mem_index(s
));
2406 /* The value is stored even in case of trap. */
2407 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2413 static ExitStatus
op_lfhat(DisasContext
*s
, DisasOps
*o
)
2415 TCGLabel
*lab
= gen_new_label();
2416 store_reg32h_i64(get_field(s
->fields
, r1
), o
->in2
);
2417 /* The value is stored even in case of trap. */
2418 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->in2
, 0, lab
);
2424 static ExitStatus
op_llgfat(DisasContext
*s
, DisasOps
*o
)
2426 TCGLabel
*lab
= gen_new_label();
2427 tcg_gen_qemu_ld32u(o
->out
, o
->in2
, get_mem_index(s
));
2428 /* The value is stored even in case of trap. */
2429 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2435 static ExitStatus
op_llgtat(DisasContext
*s
, DisasOps
*o
)
2437 TCGLabel
*lab
= gen_new_label();
2438 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffff);
2439 /* The value is stored even in case of trap. */
2440 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2446 static ExitStatus
op_loc(DisasContext
*s
, DisasOps
*o
)
2450 disas_jcc(s
, &c
, get_field(s
->fields
, m3
));
2453 tcg_gen_movcond_i64(c
.cond
, o
->out
, c
.u
.s64
.a
, c
.u
.s64
.b
,
2457 TCGv_i32 t32
= tcg_temp_new_i32();
2460 tcg_gen_setcond_i32(c
.cond
, t32
, c
.u
.s32
.a
, c
.u
.s32
.b
);
2463 t
= tcg_temp_new_i64();
2464 tcg_gen_extu_i32_i64(t
, t32
);
2465 tcg_temp_free_i32(t32
);
2467 z
= tcg_const_i64(0);
2468 tcg_gen_movcond_i64(TCG_COND_NE
, o
->out
, t
, z
, o
->in2
, o
->in1
);
2469 tcg_temp_free_i64(t
);
2470 tcg_temp_free_i64(z
);
2476 #ifndef CONFIG_USER_ONLY
2477 static ExitStatus
op_lctl(DisasContext
*s
, DisasOps
*o
)
2479 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2480 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
2481 check_privileged(s
);
2482 potential_page_fault(s
);
2483 gen_helper_lctl(cpu_env
, r1
, o
->in2
, r3
);
2484 tcg_temp_free_i32(r1
);
2485 tcg_temp_free_i32(r3
);
2489 static ExitStatus
op_lctlg(DisasContext
*s
, DisasOps
*o
)
2491 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2492 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
2493 check_privileged(s
);
2494 potential_page_fault(s
);
2495 gen_helper_lctlg(cpu_env
, r1
, o
->in2
, r3
);
2496 tcg_temp_free_i32(r1
);
2497 tcg_temp_free_i32(r3
);
2500 static ExitStatus
op_lra(DisasContext
*s
, DisasOps
*o
)
2502 check_privileged(s
);
2503 potential_page_fault(s
);
2504 gen_helper_lra(o
->out
, cpu_env
, o
->in2
);
2509 static ExitStatus
op_lpsw(DisasContext
*s
, DisasOps
*o
)
2513 check_privileged(s
);
2515 t1
= tcg_temp_new_i64();
2516 t2
= tcg_temp_new_i64();
2517 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2518 tcg_gen_addi_i64(o
->in2
, o
->in2
, 4);
2519 tcg_gen_qemu_ld32u(t2
, o
->in2
, get_mem_index(s
));
2520 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
2521 tcg_gen_shli_i64(t1
, t1
, 32);
2522 gen_helper_load_psw(cpu_env
, t1
, t2
);
2523 tcg_temp_free_i64(t1
);
2524 tcg_temp_free_i64(t2
);
2525 return EXIT_NORETURN
;
2528 static ExitStatus
op_lpswe(DisasContext
*s
, DisasOps
*o
)
2532 check_privileged(s
);
2534 t1
= tcg_temp_new_i64();
2535 t2
= tcg_temp_new_i64();
2536 tcg_gen_qemu_ld64(t1
, o
->in2
, get_mem_index(s
));
2537 tcg_gen_addi_i64(o
->in2
, o
->in2
, 8);
2538 tcg_gen_qemu_ld64(t2
, o
->in2
, get_mem_index(s
));
2539 gen_helper_load_psw(cpu_env
, t1
, t2
);
2540 tcg_temp_free_i64(t1
);
2541 tcg_temp_free_i64(t2
);
2542 return EXIT_NORETURN
;
2546 static ExitStatus
op_lam(DisasContext
*s
, DisasOps
*o
)
2548 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2549 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
2550 potential_page_fault(s
);
2551 gen_helper_lam(cpu_env
, r1
, o
->in2
, r3
);
2552 tcg_temp_free_i32(r1
);
2553 tcg_temp_free_i32(r3
);
2557 static ExitStatus
op_lm32(DisasContext
*s
, DisasOps
*o
)
2559 int r1
= get_field(s
->fields
, r1
);
2560 int r3
= get_field(s
->fields
, r3
);
2563 /* Only one register to read. */
2564 t1
= tcg_temp_new_i64();
2565 if (unlikely(r1
== r3
)) {
2566 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2567 store_reg32_i64(r1
, t1
);
2572 /* First load the values of the first and last registers to trigger
2573 possible page faults. */
2574 t2
= tcg_temp_new_i64();
2575 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2576 tcg_gen_addi_i64(t2
, o
->in2
, 4 * ((r3
- r1
) & 15));
2577 tcg_gen_qemu_ld32u(t2
, t2
, get_mem_index(s
));
2578 store_reg32_i64(r1
, t1
);
2579 store_reg32_i64(r3
, t2
);
2581 /* Only two registers to read. */
2582 if (((r1
+ 1) & 15) == r3
) {
2588 /* Then load the remaining registers. Page fault can't occur. */
2590 tcg_gen_movi_i64(t2
, 4);
2593 tcg_gen_add_i64(o
->in2
, o
->in2
, t2
);
2594 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2595 store_reg32_i64(r1
, t1
);
2603 static ExitStatus
op_lmh(DisasContext
*s
, DisasOps
*o
)
2605 int r1
= get_field(s
->fields
, r1
);
2606 int r3
= get_field(s
->fields
, r3
);
2609 /* Only one register to read. */
2610 t1
= tcg_temp_new_i64();
2611 if (unlikely(r1
== r3
)) {
2612 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2613 store_reg32h_i64(r1
, t1
);
2618 /* First load the values of the first and last registers to trigger
2619 possible page faults. */
2620 t2
= tcg_temp_new_i64();
2621 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2622 tcg_gen_addi_i64(t2
, o
->in2
, 4 * ((r3
- r1
) & 15));
2623 tcg_gen_qemu_ld32u(t2
, t2
, get_mem_index(s
));
2624 store_reg32h_i64(r1
, t1
);
2625 store_reg32h_i64(r3
, t2
);
2627 /* Only two registers to read. */
2628 if (((r1
+ 1) & 15) == r3
) {
2634 /* Then load the remaining registers. Page fault can't occur. */
2636 tcg_gen_movi_i64(t2
, 4);
2639 tcg_gen_add_i64(o
->in2
, o
->in2
, t2
);
2640 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
2641 store_reg32h_i64(r1
, t1
);
2649 static ExitStatus
op_lm64(DisasContext
*s
, DisasOps
*o
)
2651 int r1
= get_field(s
->fields
, r1
);
2652 int r3
= get_field(s
->fields
, r3
);
2655 /* Only one register to read. */
2656 if (unlikely(r1
== r3
)) {
2657 tcg_gen_qemu_ld64(regs
[r1
], o
->in2
, get_mem_index(s
));
2661 /* First load the values of the first and last registers to trigger
2662 possible page faults. */
2663 t1
= tcg_temp_new_i64();
2664 t2
= tcg_temp_new_i64();
2665 tcg_gen_qemu_ld64(t1
, o
->in2
, get_mem_index(s
));
2666 tcg_gen_addi_i64(t2
, o
->in2
, 8 * ((r3
- r1
) & 15));
2667 tcg_gen_qemu_ld64(regs
[r3
], t2
, get_mem_index(s
));
2668 tcg_gen_mov_i64(regs
[r1
], t1
);
2671 /* Only two registers to read. */
2672 if (((r1
+ 1) & 15) == r3
) {
2677 /* Then load the remaining registers. Page fault can't occur. */
2679 tcg_gen_movi_i64(t1
, 8);
2682 tcg_gen_add_i64(o
->in2
, o
->in2
, t1
);
2683 tcg_gen_qemu_ld64(regs
[r1
], o
->in2
, get_mem_index(s
));
2690 #ifndef CONFIG_USER_ONLY
2691 static ExitStatus
op_lura(DisasContext
*s
, DisasOps
*o
)
2693 check_privileged(s
);
2694 potential_page_fault(s
);
2695 gen_helper_lura(o
->out
, cpu_env
, o
->in2
);
2699 static ExitStatus
op_lurag(DisasContext
*s
, DisasOps
*o
)
2701 check_privileged(s
);
2702 potential_page_fault(s
);
2703 gen_helper_lurag(o
->out
, cpu_env
, o
->in2
);
2708 static ExitStatus
op_mov2(DisasContext
*s
, DisasOps
*o
)
2711 o
->g_out
= o
->g_in2
;
2712 TCGV_UNUSED_I64(o
->in2
);
2717 static ExitStatus
op_mov2e(DisasContext
*s
, DisasOps
*o
)
2719 int b2
= get_field(s
->fields
, b2
);
2720 TCGv ar1
= tcg_temp_new_i64();
2723 o
->g_out
= o
->g_in2
;
2724 TCGV_UNUSED_I64(o
->in2
);
2727 switch (s
->tb
->flags
& FLAG_MASK_ASC
) {
2728 case PSW_ASC_PRIMARY
>> 32:
2729 tcg_gen_movi_i64(ar1
, 0);
2731 case PSW_ASC_ACCREG
>> 32:
2732 tcg_gen_movi_i64(ar1
, 1);
2734 case PSW_ASC_SECONDARY
>> 32:
2736 tcg_gen_ld32u_i64(ar1
, cpu_env
, offsetof(CPUS390XState
, aregs
[b2
]));
2738 tcg_gen_movi_i64(ar1
, 0);
2741 case PSW_ASC_HOME
>> 32:
2742 tcg_gen_movi_i64(ar1
, 2);
2746 tcg_gen_st32_i64(ar1
, cpu_env
, offsetof(CPUS390XState
, aregs
[1]));
2747 tcg_temp_free_i64(ar1
);
2752 static ExitStatus
op_movx(DisasContext
*s
, DisasOps
*o
)
2756 o
->g_out
= o
->g_in1
;
2757 o
->g_out2
= o
->g_in2
;
2758 TCGV_UNUSED_I64(o
->in1
);
2759 TCGV_UNUSED_I64(o
->in2
);
2760 o
->g_in1
= o
->g_in2
= false;
2764 static ExitStatus
op_mvc(DisasContext
*s
, DisasOps
*o
)
2766 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
2767 potential_page_fault(s
);
2768 gen_helper_mvc(cpu_env
, l
, o
->addr1
, o
->in2
);
2769 tcg_temp_free_i32(l
);
2773 static ExitStatus
op_mvcl(DisasContext
*s
, DisasOps
*o
)
2775 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2776 TCGv_i32 r2
= tcg_const_i32(get_field(s
->fields
, r2
));
2777 potential_page_fault(s
);
2778 gen_helper_mvcl(cc_op
, cpu_env
, r1
, r2
);
2779 tcg_temp_free_i32(r1
);
2780 tcg_temp_free_i32(r2
);
2785 static ExitStatus
op_mvcle(DisasContext
*s
, DisasOps
*o
)
2787 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
2788 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
2789 potential_page_fault(s
);
2790 gen_helper_mvcle(cc_op
, cpu_env
, r1
, o
->in2
, r3
);
2791 tcg_temp_free_i32(r1
);
2792 tcg_temp_free_i32(r3
);
2797 #ifndef CONFIG_USER_ONLY
2798 static ExitStatus
op_mvcp(DisasContext
*s
, DisasOps
*o
)
2800 int r1
= get_field(s
->fields
, l1
);
2801 check_privileged(s
);
2802 potential_page_fault(s
);
2803 gen_helper_mvcp(cc_op
, cpu_env
, regs
[r1
], o
->addr1
, o
->in2
);
2808 static ExitStatus
op_mvcs(DisasContext
*s
, DisasOps
*o
)
2810 int r1
= get_field(s
->fields
, l1
);
2811 check_privileged(s
);
2812 potential_page_fault(s
);
2813 gen_helper_mvcs(cc_op
, cpu_env
, regs
[r1
], o
->addr1
, o
->in2
);
2819 static ExitStatus
op_mvpg(DisasContext
*s
, DisasOps
*o
)
2821 potential_page_fault(s
);
2822 gen_helper_mvpg(cpu_env
, regs
[0], o
->in1
, o
->in2
);
2827 static ExitStatus
op_mvst(DisasContext
*s
, DisasOps
*o
)
2829 potential_page_fault(s
);
2830 gen_helper_mvst(o
->in1
, cpu_env
, regs
[0], o
->in1
, o
->in2
);
2832 return_low128(o
->in2
);
2836 static ExitStatus
op_mul(DisasContext
*s
, DisasOps
*o
)
2838 tcg_gen_mul_i64(o
->out
, o
->in1
, o
->in2
);
2842 static ExitStatus
op_mul128(DisasContext
*s
, DisasOps
*o
)
2844 tcg_gen_mulu2_i64(o
->out2
, o
->out
, o
->in1
, o
->in2
);
2848 static ExitStatus
op_meeb(DisasContext
*s
, DisasOps
*o
)
2850 gen_helper_meeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2854 static ExitStatus
op_mdeb(DisasContext
*s
, DisasOps
*o
)
2856 gen_helper_mdeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2860 static ExitStatus
op_mdb(DisasContext
*s
, DisasOps
*o
)
2862 gen_helper_mdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2866 static ExitStatus
op_mxb(DisasContext
*s
, DisasOps
*o
)
2868 gen_helper_mxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
2869 return_low128(o
->out2
);
2873 static ExitStatus
op_mxdb(DisasContext
*s
, DisasOps
*o
)
2875 gen_helper_mxdb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
2876 return_low128(o
->out2
);
2880 static ExitStatus
op_maeb(DisasContext
*s
, DisasOps
*o
)
2882 TCGv_i64 r3
= load_freg32_i64(get_field(s
->fields
, r3
));
2883 gen_helper_maeb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
2884 tcg_temp_free_i64(r3
);
2888 static ExitStatus
op_madb(DisasContext
*s
, DisasOps
*o
)
2890 int r3
= get_field(s
->fields
, r3
);
2891 gen_helper_madb(o
->out
, cpu_env
, o
->in1
, o
->in2
, fregs
[r3
]);
2895 static ExitStatus
op_mseb(DisasContext
*s
, DisasOps
*o
)
2897 TCGv_i64 r3
= load_freg32_i64(get_field(s
->fields
, r3
));
2898 gen_helper_mseb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
2899 tcg_temp_free_i64(r3
);
2903 static ExitStatus
op_msdb(DisasContext
*s
, DisasOps
*o
)
2905 int r3
= get_field(s
->fields
, r3
);
2906 gen_helper_msdb(o
->out
, cpu_env
, o
->in1
, o
->in2
, fregs
[r3
]);
2910 static ExitStatus
op_nabs(DisasContext
*s
, DisasOps
*o
)
2913 z
= tcg_const_i64(0);
2914 n
= tcg_temp_new_i64();
2915 tcg_gen_neg_i64(n
, o
->in2
);
2916 tcg_gen_movcond_i64(TCG_COND_GE
, o
->out
, o
->in2
, z
, n
, o
->in2
);
2917 tcg_temp_free_i64(n
);
2918 tcg_temp_free_i64(z
);
2922 static ExitStatus
op_nabsf32(DisasContext
*s
, DisasOps
*o
)
2924 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x80000000ull
);
2928 static ExitStatus
op_nabsf64(DisasContext
*s
, DisasOps
*o
)
2930 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
2934 static ExitStatus
op_nabsf128(DisasContext
*s
, DisasOps
*o
)
2936 tcg_gen_ori_i64(o
->out
, o
->in1
, 0x8000000000000000ull
);
2937 tcg_gen_mov_i64(o
->out2
, o
->in2
);
2941 static ExitStatus
op_nc(DisasContext
*s
, DisasOps
*o
)
2943 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
2944 potential_page_fault(s
);
2945 gen_helper_nc(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
2946 tcg_temp_free_i32(l
);
2951 static ExitStatus
op_neg(DisasContext
*s
, DisasOps
*o
)
2953 tcg_gen_neg_i64(o
->out
, o
->in2
);
2957 static ExitStatus
op_negf32(DisasContext
*s
, DisasOps
*o
)
2959 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x80000000ull
);
2963 static ExitStatus
op_negf64(DisasContext
*s
, DisasOps
*o
)
2965 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
2969 static ExitStatus
op_negf128(DisasContext
*s
, DisasOps
*o
)
2971 tcg_gen_xori_i64(o
->out
, o
->in1
, 0x8000000000000000ull
);
2972 tcg_gen_mov_i64(o
->out2
, o
->in2
);
2976 static ExitStatus
op_oc(DisasContext
*s
, DisasOps
*o
)
2978 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
2979 potential_page_fault(s
);
2980 gen_helper_oc(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
2981 tcg_temp_free_i32(l
);
2986 static ExitStatus
op_or(DisasContext
*s
, DisasOps
*o
)
2988 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
2992 static ExitStatus
op_ori(DisasContext
*s
, DisasOps
*o
)
2994 int shift
= s
->insn
->data
& 0xff;
2995 int size
= s
->insn
->data
>> 8;
2996 uint64_t mask
= ((1ull << size
) - 1) << shift
;
2999 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
3000 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
3002 /* Produce the CC from only the bits manipulated. */
3003 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
3004 set_cc_nz_u64(s
, cc_dst
);
3008 static ExitStatus
op_popcnt(DisasContext
*s
, DisasOps
*o
)
3010 gen_helper_popcnt(o
->out
, o
->in2
);
3014 #ifndef CONFIG_USER_ONLY
3015 static ExitStatus
op_ptlb(DisasContext
*s
, DisasOps
*o
)
3017 check_privileged(s
);
3018 gen_helper_ptlb(cpu_env
);
3023 static ExitStatus
op_risbg(DisasContext
*s
, DisasOps
*o
)
3025 int i3
= get_field(s
->fields
, i3
);
3026 int i4
= get_field(s
->fields
, i4
);
3027 int i5
= get_field(s
->fields
, i5
);
3028 int do_zero
= i4
& 0x80;
3029 uint64_t mask
, imask
, pmask
;
3032 /* Adjust the arguments for the specific insn. */
3033 switch (s
->fields
->op2
) {
3034 case 0x55: /* risbg */
3039 case 0x5d: /* risbhg */
3042 pmask
= 0xffffffff00000000ull
;
3044 case 0x51: /* risblg */
3047 pmask
= 0x00000000ffffffffull
;
3053 /* MASK is the set of bits to be inserted from R2.
3054 Take care for I3/I4 wraparound. */
3057 mask
^= pmask
>> i4
>> 1;
3059 mask
|= ~(pmask
>> i4
>> 1);
3063 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
3064 insns, we need to keep the other half of the register. */
3065 imask
= ~mask
| ~pmask
;
3067 if (s
->fields
->op2
== 0x55) {
3074 /* In some cases we can implement this with deposit, which can be more
3075 efficient on some hosts. */
3076 if (~mask
== imask
&& i3
<= i4
) {
3077 if (s
->fields
->op2
== 0x5d) {
3080 /* Note that we rotate the bits to be inserted to the lsb, not to
3081 the position as described in the PoO. */
3084 rot
= (i5
- pos
) & 63;
3090 /* Rotate the input as necessary. */
3091 tcg_gen_rotli_i64(o
->in2
, o
->in2
, rot
);
3093 /* Insert the selected bits into the output. */
3095 tcg_gen_deposit_i64(o
->out
, o
->out
, o
->in2
, pos
, len
);
3096 } else if (imask
== 0) {
3097 tcg_gen_andi_i64(o
->out
, o
->in2
, mask
);
3099 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3100 tcg_gen_andi_i64(o
->out
, o
->out
, imask
);
3101 tcg_gen_or_i64(o
->out
, o
->out
, o
->in2
);
3106 static ExitStatus
op_rosbg(DisasContext
*s
, DisasOps
*o
)
3108 int i3
= get_field(s
->fields
, i3
);
3109 int i4
= get_field(s
->fields
, i4
);
3110 int i5
= get_field(s
->fields
, i5
);
3113 /* If this is a test-only form, arrange to discard the result. */
3115 o
->out
= tcg_temp_new_i64();
3123 /* MASK is the set of bits to be operated on from R2.
3124 Take care for I3/I4 wraparound. */
3127 mask
^= ~0ull >> i4
>> 1;
3129 mask
|= ~(~0ull >> i4
>> 1);
3132 /* Rotate the input as necessary. */
3133 tcg_gen_rotli_i64(o
->in2
, o
->in2
, i5
);
3136 switch (s
->fields
->op2
) {
3137 case 0x55: /* AND */
3138 tcg_gen_ori_i64(o
->in2
, o
->in2
, ~mask
);
3139 tcg_gen_and_i64(o
->out
, o
->out
, o
->in2
);
3142 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3143 tcg_gen_or_i64(o
->out
, o
->out
, o
->in2
);
3145 case 0x57: /* XOR */
3146 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3147 tcg_gen_xor_i64(o
->out
, o
->out
, o
->in2
);
3154 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
3155 set_cc_nz_u64(s
, cc_dst
);
3159 static ExitStatus
op_rev16(DisasContext
*s
, DisasOps
*o
)
3161 tcg_gen_bswap16_i64(o
->out
, o
->in2
);
3165 static ExitStatus
op_rev32(DisasContext
*s
, DisasOps
*o
)
3167 tcg_gen_bswap32_i64(o
->out
, o
->in2
);
3171 static ExitStatus
op_rev64(DisasContext
*s
, DisasOps
*o
)
3173 tcg_gen_bswap64_i64(o
->out
, o
->in2
);
3177 static ExitStatus
op_rll32(DisasContext
*s
, DisasOps
*o
)
3179 TCGv_i32 t1
= tcg_temp_new_i32();
3180 TCGv_i32 t2
= tcg_temp_new_i32();
3181 TCGv_i32 to
= tcg_temp_new_i32();
3182 tcg_gen_trunc_i64_i32(t1
, o
->in1
);
3183 tcg_gen_trunc_i64_i32(t2
, o
->in2
);
3184 tcg_gen_rotl_i32(to
, t1
, t2
);
3185 tcg_gen_extu_i32_i64(o
->out
, to
);
3186 tcg_temp_free_i32(t1
);
3187 tcg_temp_free_i32(t2
);
3188 tcg_temp_free_i32(to
);
3192 static ExitStatus
op_rll64(DisasContext
*s
, DisasOps
*o
)
3194 tcg_gen_rotl_i64(o
->out
, o
->in1
, o
->in2
);
3198 #ifndef CONFIG_USER_ONLY
3199 static ExitStatus
op_rrbe(DisasContext
*s
, DisasOps
*o
)
3201 check_privileged(s
);
3202 gen_helper_rrbe(cc_op
, cpu_env
, o
->in2
);
3207 static ExitStatus
op_sacf(DisasContext
*s
, DisasOps
*o
)
3209 check_privileged(s
);
3210 gen_helper_sacf(cpu_env
, o
->in2
);
3211 /* Addressing mode has changed, so end the block. */
3212 return EXIT_PC_STALE
;
3216 static ExitStatus
op_sam(DisasContext
*s
, DisasOps
*o
)
3218 int sam
= s
->insn
->data
;
3234 /* Bizarre but true, we check the address of the current insn for the
3235 specification exception, not the next to be executed. Thus the PoO
3236 documents that Bad Things Happen two bytes before the end. */
3237 if (s
->pc
& ~mask
) {
3238 gen_program_exception(s
, PGM_SPECIFICATION
);
3239 return EXIT_NORETURN
;
3243 tsam
= tcg_const_i64(sam
);
3244 tcg_gen_deposit_i64(psw_mask
, psw_mask
, tsam
, 31, 2);
3245 tcg_temp_free_i64(tsam
);
3247 /* Always exit the TB, since we (may have) changed execution mode. */
3248 return EXIT_PC_STALE
;
3251 static ExitStatus
op_sar(DisasContext
*s
, DisasOps
*o
)
3253 int r1
= get_field(s
->fields
, r1
);
3254 tcg_gen_st32_i64(o
->in2
, cpu_env
, offsetof(CPUS390XState
, aregs
[r1
]));
3258 static ExitStatus
op_seb(DisasContext
*s
, DisasOps
*o
)
3260 gen_helper_seb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3264 static ExitStatus
op_sdb(DisasContext
*s
, DisasOps
*o
)
3266 gen_helper_sdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3270 static ExitStatus
op_sxb(DisasContext
*s
, DisasOps
*o
)
3272 gen_helper_sxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
3273 return_low128(o
->out2
);
3277 static ExitStatus
op_sqeb(DisasContext
*s
, DisasOps
*o
)
3279 gen_helper_sqeb(o
->out
, cpu_env
, o
->in2
);
3283 static ExitStatus
op_sqdb(DisasContext
*s
, DisasOps
*o
)
3285 gen_helper_sqdb(o
->out
, cpu_env
, o
->in2
);
3289 static ExitStatus
op_sqxb(DisasContext
*s
, DisasOps
*o
)
3291 gen_helper_sqxb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3292 return_low128(o
->out2
);
3296 #ifndef CONFIG_USER_ONLY
3297 static ExitStatus
op_servc(DisasContext
*s
, DisasOps
*o
)
3299 check_privileged(s
);
3300 potential_page_fault(s
);
3301 gen_helper_servc(cc_op
, cpu_env
, o
->in2
, o
->in1
);
3306 static ExitStatus
op_sigp(DisasContext
*s
, DisasOps
*o
)
3308 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
3309 check_privileged(s
);
3310 potential_page_fault(s
);
3311 gen_helper_sigp(cc_op
, cpu_env
, o
->in2
, r1
, o
->in1
);
3312 tcg_temp_free_i32(r1
);
3317 static ExitStatus
op_soc(DisasContext
*s
, DisasOps
*o
)
3324 disas_jcc(s
, &c
, get_field(s
->fields
, m3
));
3326 /* We want to store when the condition is fulfilled, so branch
3327 out when it's not */
3328 c
.cond
= tcg_invert_cond(c
.cond
);
3330 lab
= gen_new_label();
3332 tcg_gen_brcond_i64(c
.cond
, c
.u
.s64
.a
, c
.u
.s64
.b
, lab
);
3334 tcg_gen_brcond_i32(c
.cond
, c
.u
.s32
.a
, c
.u
.s32
.b
, lab
);
3338 r1
= get_field(s
->fields
, r1
);
3339 a
= get_address(s
, 0, get_field(s
->fields
, b2
), get_field(s
->fields
, d2
));
3340 if (s
->insn
->data
) {
3341 tcg_gen_qemu_st64(regs
[r1
], a
, get_mem_index(s
));
3343 tcg_gen_qemu_st32(regs
[r1
], a
, get_mem_index(s
));
3345 tcg_temp_free_i64(a
);
3351 static ExitStatus
op_sla(DisasContext
*s
, DisasOps
*o
)
3353 uint64_t sign
= 1ull << s
->insn
->data
;
3354 enum cc_op cco
= s
->insn
->data
== 31 ? CC_OP_SLA_32
: CC_OP_SLA_64
;
3355 gen_op_update2_cc_i64(s
, cco
, o
->in1
, o
->in2
);
3356 tcg_gen_shl_i64(o
->out
, o
->in1
, o
->in2
);
3357 /* The arithmetic left shift is curious in that it does not affect
3358 the sign bit. Copy that over from the source unchanged. */
3359 tcg_gen_andi_i64(o
->out
, o
->out
, ~sign
);
3360 tcg_gen_andi_i64(o
->in1
, o
->in1
, sign
);
3361 tcg_gen_or_i64(o
->out
, o
->out
, o
->in1
);
3365 static ExitStatus
op_sll(DisasContext
*s
, DisasOps
*o
)
3367 tcg_gen_shl_i64(o
->out
, o
->in1
, o
->in2
);
3371 static ExitStatus
op_sra(DisasContext
*s
, DisasOps
*o
)
3373 tcg_gen_sar_i64(o
->out
, o
->in1
, o
->in2
);
3377 static ExitStatus
op_srl(DisasContext
*s
, DisasOps
*o
)
3379 tcg_gen_shr_i64(o
->out
, o
->in1
, o
->in2
);
3383 static ExitStatus
op_sfpc(DisasContext
*s
, DisasOps
*o
)
3385 gen_helper_sfpc(cpu_env
, o
->in2
);
3389 static ExitStatus
op_sfas(DisasContext
*s
, DisasOps
*o
)
3391 gen_helper_sfas(cpu_env
, o
->in2
);
3395 static ExitStatus
op_srnm(DisasContext
*s
, DisasOps
*o
)
3397 int b2
= get_field(s
->fields
, b2
);
3398 int d2
= get_field(s
->fields
, d2
);
3399 TCGv_i64 t1
= tcg_temp_new_i64();
3400 TCGv_i64 t2
= tcg_temp_new_i64();
3403 switch (s
->fields
->op2
) {
3404 case 0x99: /* SRNM */
3407 case 0xb8: /* SRNMB */
3410 case 0xb9: /* SRNMT */
3416 mask
= (1 << len
) - 1;
3418 /* Insert the value into the appropriate field of the FPC. */
3420 tcg_gen_movi_i64(t1
, d2
& mask
);
3422 tcg_gen_addi_i64(t1
, regs
[b2
], d2
);
3423 tcg_gen_andi_i64(t1
, t1
, mask
);
3425 tcg_gen_ld32u_i64(t2
, cpu_env
, offsetof(CPUS390XState
, fpc
));
3426 tcg_gen_deposit_i64(t2
, t2
, t1
, pos
, len
);
3427 tcg_temp_free_i64(t1
);
3429 /* Then install the new FPC to set the rounding mode in fpu_status. */
3430 gen_helper_sfpc(cpu_env
, t2
);
3431 tcg_temp_free_i64(t2
);
3435 #ifndef CONFIG_USER_ONLY
3436 static ExitStatus
op_spka(DisasContext
*s
, DisasOps
*o
)
3438 check_privileged(s
);
3439 tcg_gen_shri_i64(o
->in2
, o
->in2
, 4);
3440 tcg_gen_deposit_i64(psw_mask
, psw_mask
, o
->in2
, PSW_SHIFT_KEY
- 4, 4);
3444 static ExitStatus
op_sske(DisasContext
*s
, DisasOps
*o
)
3446 check_privileged(s
);
3447 gen_helper_sske(cpu_env
, o
->in1
, o
->in2
);
3451 static ExitStatus
op_ssm(DisasContext
*s
, DisasOps
*o
)
3453 check_privileged(s
);
3454 tcg_gen_deposit_i64(psw_mask
, psw_mask
, o
->in2
, 56, 8);
3458 static ExitStatus
op_stap(DisasContext
*s
, DisasOps
*o
)
3460 check_privileged(s
);
3461 /* ??? Surely cpu address != cpu number. In any case the previous
3462 version of this stored more than the required half-word, so it
3463 is unlikely this has ever been tested. */
3464 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, cpu_num
));
3468 static ExitStatus
op_stck(DisasContext
*s
, DisasOps
*o
)
3470 gen_helper_stck(o
->out
, cpu_env
);
3471 /* ??? We don't implement clock states. */
3472 gen_op_movi_cc(s
, 0);
3476 static ExitStatus
op_stcke(DisasContext
*s
, DisasOps
*o
)
3478 TCGv_i64 c1
= tcg_temp_new_i64();
3479 TCGv_i64 c2
= tcg_temp_new_i64();
3480 gen_helper_stck(c1
, cpu_env
);
3481 /* Shift the 64-bit value into its place as a zero-extended
3482 104-bit value. Note that "bit positions 64-103 are always
3483 non-zero so that they compare differently to STCK"; we set
3484 the least significant bit to 1. */
3485 tcg_gen_shli_i64(c2
, c1
, 56);
3486 tcg_gen_shri_i64(c1
, c1
, 8);
3487 tcg_gen_ori_i64(c2
, c2
, 0x10000);
3488 tcg_gen_qemu_st64(c1
, o
->in2
, get_mem_index(s
));
3489 tcg_gen_addi_i64(o
->in2
, o
->in2
, 8);
3490 tcg_gen_qemu_st64(c2
, o
->in2
, get_mem_index(s
));
3491 tcg_temp_free_i64(c1
);
3492 tcg_temp_free_i64(c2
);
3493 /* ??? We don't implement clock states. */
3494 gen_op_movi_cc(s
, 0);
3498 static ExitStatus
op_sckc(DisasContext
*s
, DisasOps
*o
)
3500 check_privileged(s
);
3501 gen_helper_sckc(cpu_env
, o
->in2
);
3505 static ExitStatus
op_stckc(DisasContext
*s
, DisasOps
*o
)
3507 check_privileged(s
);
3508 gen_helper_stckc(o
->out
, cpu_env
);
3512 static ExitStatus
op_stctg(DisasContext
*s
, DisasOps
*o
)
3514 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
3515 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
3516 check_privileged(s
);
3517 potential_page_fault(s
);
3518 gen_helper_stctg(cpu_env
, r1
, o
->in2
, r3
);
3519 tcg_temp_free_i32(r1
);
3520 tcg_temp_free_i32(r3
);
3524 static ExitStatus
op_stctl(DisasContext
*s
, DisasOps
*o
)
3526 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
3527 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
3528 check_privileged(s
);
3529 potential_page_fault(s
);
3530 gen_helper_stctl(cpu_env
, r1
, o
->in2
, r3
);
3531 tcg_temp_free_i32(r1
);
3532 tcg_temp_free_i32(r3
);
3536 static ExitStatus
op_stidp(DisasContext
*s
, DisasOps
*o
)
3538 TCGv_i64 t1
= tcg_temp_new_i64();
3540 check_privileged(s
);
3541 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, cpu_num
));
3542 tcg_gen_ld32u_i64(t1
, cpu_env
, offsetof(CPUS390XState
, machine_type
));
3543 tcg_gen_deposit_i64(o
->out
, o
->out
, t1
, 32, 32);
3544 tcg_temp_free_i64(t1
);
3549 static ExitStatus
op_spt(DisasContext
*s
, DisasOps
*o
)
3551 check_privileged(s
);
3552 gen_helper_spt(cpu_env
, o
->in2
);
3556 static ExitStatus
op_stfl(DisasContext
*s
, DisasOps
*o
)
3559 /* We really ought to have more complete indication of facilities
3560 that we implement. Address this when STFLE is implemented. */
3561 check_privileged(s
);
3562 f
= tcg_const_i64(0xc0000000);
3563 a
= tcg_const_i64(200);
3564 tcg_gen_qemu_st32(f
, a
, get_mem_index(s
));
3565 tcg_temp_free_i64(f
);
3566 tcg_temp_free_i64(a
);
3570 static ExitStatus
op_stpt(DisasContext
*s
, DisasOps
*o
)
3572 check_privileged(s
);
3573 gen_helper_stpt(o
->out
, cpu_env
);
3577 static ExitStatus
op_stsi(DisasContext
*s
, DisasOps
*o
)
3579 check_privileged(s
);
3580 potential_page_fault(s
);
3581 gen_helper_stsi(cc_op
, cpu_env
, o
->in2
, regs
[0], regs
[1]);
3586 static ExitStatus
op_spx(DisasContext
*s
, DisasOps
*o
)
3588 check_privileged(s
);
3589 gen_helper_spx(cpu_env
, o
->in2
);
3593 static ExitStatus
op_xsch(DisasContext
*s
, DisasOps
*o
)
3595 check_privileged(s
);
3596 potential_page_fault(s
);
3597 gen_helper_xsch(cpu_env
, regs
[1]);
3602 static ExitStatus
op_csch(DisasContext
*s
, DisasOps
*o
)
3604 check_privileged(s
);
3605 potential_page_fault(s
);
3606 gen_helper_csch(cpu_env
, regs
[1]);
3611 static ExitStatus
op_hsch(DisasContext
*s
, DisasOps
*o
)
3613 check_privileged(s
);
3614 potential_page_fault(s
);
3615 gen_helper_hsch(cpu_env
, regs
[1]);
3620 static ExitStatus
op_msch(DisasContext
*s
, DisasOps
*o
)
3622 check_privileged(s
);
3623 potential_page_fault(s
);
3624 gen_helper_msch(cpu_env
, regs
[1], o
->in2
);
3629 static ExitStatus
op_rchp(DisasContext
*s
, DisasOps
*o
)
3631 check_privileged(s
);
3632 potential_page_fault(s
);
3633 gen_helper_rchp(cpu_env
, regs
[1]);
3638 static ExitStatus
op_rsch(DisasContext
*s
, DisasOps
*o
)
3640 check_privileged(s
);
3641 potential_page_fault(s
);
3642 gen_helper_rsch(cpu_env
, regs
[1]);
3647 static ExitStatus
op_ssch(DisasContext
*s
, DisasOps
*o
)
3649 check_privileged(s
);
3650 potential_page_fault(s
);
3651 gen_helper_ssch(cpu_env
, regs
[1], o
->in2
);
3656 static ExitStatus
op_stsch(DisasContext
*s
, DisasOps
*o
)
3658 check_privileged(s
);
3659 potential_page_fault(s
);
3660 gen_helper_stsch(cpu_env
, regs
[1], o
->in2
);
3665 static ExitStatus
op_tsch(DisasContext
*s
, DisasOps
*o
)
3667 check_privileged(s
);
3668 potential_page_fault(s
);
3669 gen_helper_tsch(cpu_env
, regs
[1], o
->in2
);
3674 static ExitStatus
op_chsc(DisasContext
*s
, DisasOps
*o
)
3676 check_privileged(s
);
3677 potential_page_fault(s
);
3678 gen_helper_chsc(cpu_env
, o
->in2
);
3683 static ExitStatus
op_stpx(DisasContext
*s
, DisasOps
*o
)
3685 check_privileged(s
);
3686 tcg_gen_ld_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, psa
));
3687 tcg_gen_andi_i64(o
->out
, o
->out
, 0x7fffe000);
3691 static ExitStatus
op_stnosm(DisasContext
*s
, DisasOps
*o
)
3693 uint64_t i2
= get_field(s
->fields
, i2
);
3696 check_privileged(s
);
3698 /* It is important to do what the instruction name says: STORE THEN.
3699 If we let the output hook perform the store then if we fault and
3700 restart, we'll have the wrong SYSTEM MASK in place. */
3701 t
= tcg_temp_new_i64();
3702 tcg_gen_shri_i64(t
, psw_mask
, 56);
3703 tcg_gen_qemu_st8(t
, o
->addr1
, get_mem_index(s
));
3704 tcg_temp_free_i64(t
);
3706 if (s
->fields
->op
== 0xac) {
3707 tcg_gen_andi_i64(psw_mask
, psw_mask
,
3708 (i2
<< 56) | 0x00ffffffffffffffull
);
3710 tcg_gen_ori_i64(psw_mask
, psw_mask
, i2
<< 56);
3715 static ExitStatus
op_stura(DisasContext
*s
, DisasOps
*o
)
3717 check_privileged(s
);
3718 potential_page_fault(s
);
3719 gen_helper_stura(cpu_env
, o
->in2
, o
->in1
);
3723 static ExitStatus
op_sturg(DisasContext
*s
, DisasOps
*o
)
3725 check_privileged(s
);
3726 potential_page_fault(s
);
3727 gen_helper_sturg(cpu_env
, o
->in2
, o
->in1
);
3732 static ExitStatus
op_st8(DisasContext
*s
, DisasOps
*o
)
3734 tcg_gen_qemu_st8(o
->in1
, o
->in2
, get_mem_index(s
));
3738 static ExitStatus
op_st16(DisasContext
*s
, DisasOps
*o
)
3740 tcg_gen_qemu_st16(o
->in1
, o
->in2
, get_mem_index(s
));
3744 static ExitStatus
op_st32(DisasContext
*s
, DisasOps
*o
)
3746 tcg_gen_qemu_st32(o
->in1
, o
->in2
, get_mem_index(s
));
3750 static ExitStatus
op_st64(DisasContext
*s
, DisasOps
*o
)
3752 tcg_gen_qemu_st64(o
->in1
, o
->in2
, get_mem_index(s
));
3756 static ExitStatus
op_stam(DisasContext
*s
, DisasOps
*o
)
3758 TCGv_i32 r1
= tcg_const_i32(get_field(s
->fields
, r1
));
3759 TCGv_i32 r3
= tcg_const_i32(get_field(s
->fields
, r3
));
3760 potential_page_fault(s
);
3761 gen_helper_stam(cpu_env
, r1
, o
->in2
, r3
);
3762 tcg_temp_free_i32(r1
);
3763 tcg_temp_free_i32(r3
);
3767 static ExitStatus
op_stcm(DisasContext
*s
, DisasOps
*o
)
3769 int m3
= get_field(s
->fields
, m3
);
3770 int pos
, base
= s
->insn
->data
;
3771 TCGv_i64 tmp
= tcg_temp_new_i64();
3773 pos
= base
+ ctz32(m3
) * 8;
3776 /* Effectively a 32-bit store. */
3777 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
3778 tcg_gen_qemu_st32(tmp
, o
->in2
, get_mem_index(s
));
3784 /* Effectively a 16-bit store. */
3785 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
3786 tcg_gen_qemu_st16(tmp
, o
->in2
, get_mem_index(s
));
3793 /* Effectively an 8-bit store. */
3794 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
3795 tcg_gen_qemu_st8(tmp
, o
->in2
, get_mem_index(s
));
3799 /* This is going to be a sequence of shifts and stores. */
3800 pos
= base
+ 32 - 8;
3803 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
3804 tcg_gen_qemu_st8(tmp
, o
->in2
, get_mem_index(s
));
3805 tcg_gen_addi_i64(o
->in2
, o
->in2
, 1);
3807 m3
= (m3
<< 1) & 0xf;
3812 tcg_temp_free_i64(tmp
);
3816 static ExitStatus
op_stm(DisasContext
*s
, DisasOps
*o
)
3818 int r1
= get_field(s
->fields
, r1
);
3819 int r3
= get_field(s
->fields
, r3
);
3820 int size
= s
->insn
->data
;
3821 TCGv_i64 tsize
= tcg_const_i64(size
);
3825 tcg_gen_qemu_st64(regs
[r1
], o
->in2
, get_mem_index(s
));
3827 tcg_gen_qemu_st32(regs
[r1
], o
->in2
, get_mem_index(s
));
3832 tcg_gen_add_i64(o
->in2
, o
->in2
, tsize
);
3836 tcg_temp_free_i64(tsize
);
3840 static ExitStatus
op_stmh(DisasContext
*s
, DisasOps
*o
)
3842 int r1
= get_field(s
->fields
, r1
);
3843 int r3
= get_field(s
->fields
, r3
);
3844 TCGv_i64 t
= tcg_temp_new_i64();
3845 TCGv_i64 t4
= tcg_const_i64(4);
3846 TCGv_i64 t32
= tcg_const_i64(32);
3849 tcg_gen_shl_i64(t
, regs
[r1
], t32
);
3850 tcg_gen_qemu_st32(t
, o
->in2
, get_mem_index(s
));
3854 tcg_gen_add_i64(o
->in2
, o
->in2
, t4
);
3858 tcg_temp_free_i64(t
);
3859 tcg_temp_free_i64(t4
);
3860 tcg_temp_free_i64(t32
);
3864 static ExitStatus
op_srst(DisasContext
*s
, DisasOps
*o
)
3866 potential_page_fault(s
);
3867 gen_helper_srst(o
->in1
, cpu_env
, regs
[0], o
->in1
, o
->in2
);
3869 return_low128(o
->in2
);
3873 static ExitStatus
op_sub(DisasContext
*s
, DisasOps
*o
)
3875 tcg_gen_sub_i64(o
->out
, o
->in1
, o
->in2
);
3879 static ExitStatus
op_subb(DisasContext
*s
, DisasOps
*o
)
3884 tcg_gen_sub_i64(o
->out
, o
->in1
, o
->in2
);
3886 /* The !borrow flag is the msb of CC. Since we want the inverse of
3887 that, we ask for a comparison of CC=0 | CC=1 -> mask of 8 | 4. */
3888 disas_jcc(s
, &cmp
, 8 | 4);
3889 borrow
= tcg_temp_new_i64();
3891 tcg_gen_setcond_i64(cmp
.cond
, borrow
, cmp
.u
.s64
.a
, cmp
.u
.s64
.b
);
3893 TCGv_i32 t
= tcg_temp_new_i32();
3894 tcg_gen_setcond_i32(cmp
.cond
, t
, cmp
.u
.s32
.a
, cmp
.u
.s32
.b
);
3895 tcg_gen_extu_i32_i64(borrow
, t
);
3896 tcg_temp_free_i32(t
);
3900 tcg_gen_sub_i64(o
->out
, o
->out
, borrow
);
3901 tcg_temp_free_i64(borrow
);
3905 static ExitStatus
op_svc(DisasContext
*s
, DisasOps
*o
)
3912 t
= tcg_const_i32(get_field(s
->fields
, i1
) & 0xff);
3913 tcg_gen_st_i32(t
, cpu_env
, offsetof(CPUS390XState
, int_svc_code
));
3914 tcg_temp_free_i32(t
);
3916 t
= tcg_const_i32(s
->next_pc
- s
->pc
);
3917 tcg_gen_st_i32(t
, cpu_env
, offsetof(CPUS390XState
, int_svc_ilen
));
3918 tcg_temp_free_i32(t
);
3920 gen_exception(EXCP_SVC
);
3921 return EXIT_NORETURN
;
3924 static ExitStatus
op_tceb(DisasContext
*s
, DisasOps
*o
)
3926 gen_helper_tceb(cc_op
, o
->in1
, o
->in2
);
3931 static ExitStatus
op_tcdb(DisasContext
*s
, DisasOps
*o
)
3933 gen_helper_tcdb(cc_op
, o
->in1
, o
->in2
);
3938 static ExitStatus
op_tcxb(DisasContext
*s
, DisasOps
*o
)
3940 gen_helper_tcxb(cc_op
, o
->out
, o
->out2
, o
->in2
);
3945 #ifndef CONFIG_USER_ONLY
3946 static ExitStatus
op_tprot(DisasContext
*s
, DisasOps
*o
)
3948 potential_page_fault(s
);
3949 gen_helper_tprot(cc_op
, o
->addr1
, o
->in2
);
3955 static ExitStatus
op_tr(DisasContext
*s
, DisasOps
*o
)
3957 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
3958 potential_page_fault(s
);
3959 gen_helper_tr(cpu_env
, l
, o
->addr1
, o
->in2
);
3960 tcg_temp_free_i32(l
);
3965 static ExitStatus
op_tre(DisasContext
*s
, DisasOps
*o
)
3967 potential_page_fault(s
);
3968 gen_helper_tre(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
3969 return_low128(o
->out2
);
3974 static ExitStatus
op_trt(DisasContext
*s
, DisasOps
*o
)
3976 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
3977 potential_page_fault(s
);
3978 gen_helper_trt(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
3979 tcg_temp_free_i32(l
);
3984 static ExitStatus
op_unpk(DisasContext
*s
, DisasOps
*o
)
3986 TCGv_i32 l
= tcg_const_i32(get_field(s
->fields
, l1
));
3987 potential_page_fault(s
);
3988 gen_helper_unpk(cpu_env
, l
, o
->addr1
, o
->in2
);
3989 tcg_temp_free_i32(l
);
3993 static ExitStatus
op_xc(DisasContext
*s
, DisasOps
*o
)
3995 int d1
= get_field(s
->fields
, d1
);
3996 int d2
= get_field(s
->fields
, d2
);
3997 int b1
= get_field(s
->fields
, b1
);
3998 int b2
= get_field(s
->fields
, b2
);
3999 int l
= get_field(s
->fields
, l1
);
4002 o
->addr1
= get_address(s
, 0, b1
, d1
);
4004 /* If the addresses are identical, this is a store/memset of zero. */
4005 if (b1
== b2
&& d1
== d2
&& (l
+ 1) <= 32) {
4006 o
->in2
= tcg_const_i64(0);
4010 tcg_gen_qemu_st64(o
->in2
, o
->addr1
, get_mem_index(s
));
4013 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 8);
4017 tcg_gen_qemu_st32(o
->in2
, o
->addr1
, get_mem_index(s
));
4020 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 4);
4024 tcg_gen_qemu_st16(o
->in2
, o
->addr1
, get_mem_index(s
));
4027 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 2);
4031 tcg_gen_qemu_st8(o
->in2
, o
->addr1
, get_mem_index(s
));
4033 gen_op_movi_cc(s
, 0);
4037 /* But in general we'll defer to a helper. */
4038 o
->in2
= get_address(s
, 0, b2
, d2
);
4039 t32
= tcg_const_i32(l
);
4040 potential_page_fault(s
);
4041 gen_helper_xc(cc_op
, cpu_env
, t32
, o
->addr1
, o
->in2
);
4042 tcg_temp_free_i32(t32
);
4047 static ExitStatus
op_xor(DisasContext
*s
, DisasOps
*o
)
4049 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
4053 static ExitStatus
op_xori(DisasContext
*s
, DisasOps
*o
)
4055 int shift
= s
->insn
->data
& 0xff;
4056 int size
= s
->insn
->data
>> 8;
4057 uint64_t mask
= ((1ull << size
) - 1) << shift
;
4060 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
4061 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
4063 /* Produce the CC from only the bits manipulated. */
4064 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
4065 set_cc_nz_u64(s
, cc_dst
);
4069 static ExitStatus
op_zero(DisasContext
*s
, DisasOps
*o
)
4071 o
->out
= tcg_const_i64(0);
4075 static ExitStatus
op_zero2(DisasContext
*s
, DisasOps
*o
)
4077 o
->out
= tcg_const_i64(0);
4083 /* ====================================================================== */
4084 /* The "Cc OUTput" generators. Given the generated output (and in some cases
4085 the original inputs), update the various cc data structures in order to
4086 be able to compute the new condition code. */
4088 static void cout_abs32(DisasContext
*s
, DisasOps
*o
)
4090 gen_op_update1_cc_i64(s
, CC_OP_ABS_32
, o
->out
);
4093 static void cout_abs64(DisasContext
*s
, DisasOps
*o
)
4095 gen_op_update1_cc_i64(s
, CC_OP_ABS_64
, o
->out
);
4098 static void cout_adds32(DisasContext
*s
, DisasOps
*o
)
4100 gen_op_update3_cc_i64(s
, CC_OP_ADD_32
, o
->in1
, o
->in2
, o
->out
);
4103 static void cout_adds64(DisasContext
*s
, DisasOps
*o
)
4105 gen_op_update3_cc_i64(s
, CC_OP_ADD_64
, o
->in1
, o
->in2
, o
->out
);
4108 static void cout_addu32(DisasContext
*s
, DisasOps
*o
)
4110 gen_op_update3_cc_i64(s
, CC_OP_ADDU_32
, o
->in1
, o
->in2
, o
->out
);
4113 static void cout_addu64(DisasContext
*s
, DisasOps
*o
)
4115 gen_op_update3_cc_i64(s
, CC_OP_ADDU_64
, o
->in1
, o
->in2
, o
->out
);
4118 static void cout_addc32(DisasContext
*s
, DisasOps
*o
)
4120 gen_op_update3_cc_i64(s
, CC_OP_ADDC_32
, o
->in1
, o
->in2
, o
->out
);
4123 static void cout_addc64(DisasContext
*s
, DisasOps
*o
)
4125 gen_op_update3_cc_i64(s
, CC_OP_ADDC_64
, o
->in1
, o
->in2
, o
->out
);
4128 static void cout_cmps32(DisasContext
*s
, DisasOps
*o
)
4130 gen_op_update2_cc_i64(s
, CC_OP_LTGT_32
, o
->in1
, o
->in2
);
4133 static void cout_cmps64(DisasContext
*s
, DisasOps
*o
)
4135 gen_op_update2_cc_i64(s
, CC_OP_LTGT_64
, o
->in1
, o
->in2
);
4138 static void cout_cmpu32(DisasContext
*s
, DisasOps
*o
)
4140 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_32
, o
->in1
, o
->in2
);
4143 static void cout_cmpu64(DisasContext
*s
, DisasOps
*o
)
4145 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_64
, o
->in1
, o
->in2
);
4148 static void cout_f32(DisasContext
*s
, DisasOps
*o
)
4150 gen_op_update1_cc_i64(s
, CC_OP_NZ_F32
, o
->out
);
4153 static void cout_f64(DisasContext
*s
, DisasOps
*o
)
4155 gen_op_update1_cc_i64(s
, CC_OP_NZ_F64
, o
->out
);
4158 static void cout_f128(DisasContext
*s
, DisasOps
*o
)
4160 gen_op_update2_cc_i64(s
, CC_OP_NZ_F128
, o
->out
, o
->out2
);
4163 static void cout_nabs32(DisasContext
*s
, DisasOps
*o
)
4165 gen_op_update1_cc_i64(s
, CC_OP_NABS_32
, o
->out
);
4168 static void cout_nabs64(DisasContext
*s
, DisasOps
*o
)
4170 gen_op_update1_cc_i64(s
, CC_OP_NABS_64
, o
->out
);
4173 static void cout_neg32(DisasContext
*s
, DisasOps
*o
)
4175 gen_op_update1_cc_i64(s
, CC_OP_COMP_32
, o
->out
);
4178 static void cout_neg64(DisasContext
*s
, DisasOps
*o
)
4180 gen_op_update1_cc_i64(s
, CC_OP_COMP_64
, o
->out
);
4183 static void cout_nz32(DisasContext
*s
, DisasOps
*o
)
4185 tcg_gen_ext32u_i64(cc_dst
, o
->out
);
4186 gen_op_update1_cc_i64(s
, CC_OP_NZ
, cc_dst
);
4189 static void cout_nz64(DisasContext
*s
, DisasOps
*o
)
4191 gen_op_update1_cc_i64(s
, CC_OP_NZ
, o
->out
);
4194 static void cout_s32(DisasContext
*s
, DisasOps
*o
)
4196 gen_op_update1_cc_i64(s
, CC_OP_LTGT0_32
, o
->out
);
4199 static void cout_s64(DisasContext
*s
, DisasOps
*o
)
4201 gen_op_update1_cc_i64(s
, CC_OP_LTGT0_64
, o
->out
);
4204 static void cout_subs32(DisasContext
*s
, DisasOps
*o
)
4206 gen_op_update3_cc_i64(s
, CC_OP_SUB_32
, o
->in1
, o
->in2
, o
->out
);
4209 static void cout_subs64(DisasContext
*s
, DisasOps
*o
)
4211 gen_op_update3_cc_i64(s
, CC_OP_SUB_64
, o
->in1
, o
->in2
, o
->out
);
4214 static void cout_subu32(DisasContext
*s
, DisasOps
*o
)
4216 gen_op_update3_cc_i64(s
, CC_OP_SUBU_32
, o
->in1
, o
->in2
, o
->out
);
4219 static void cout_subu64(DisasContext
*s
, DisasOps
*o
)
4221 gen_op_update3_cc_i64(s
, CC_OP_SUBU_64
, o
->in1
, o
->in2
, o
->out
);
4224 static void cout_subb32(DisasContext
*s
, DisasOps
*o
)
4226 gen_op_update3_cc_i64(s
, CC_OP_SUBB_32
, o
->in1
, o
->in2
, o
->out
);
4229 static void cout_subb64(DisasContext
*s
, DisasOps
*o
)
4231 gen_op_update3_cc_i64(s
, CC_OP_SUBB_64
, o
->in1
, o
->in2
, o
->out
);
4234 static void cout_tm32(DisasContext
*s
, DisasOps
*o
)
4236 gen_op_update2_cc_i64(s
, CC_OP_TM_32
, o
->in1
, o
->in2
);
4239 static void cout_tm64(DisasContext
*s
, DisasOps
*o
)
4241 gen_op_update2_cc_i64(s
, CC_OP_TM_64
, o
->in1
, o
->in2
);
4244 /* ====================================================================== */
4245 /* The "PREParation" generators. These initialize the DisasOps.OUT fields
4246 with the TCG register to which we will write. Used in combination with
4247 the "wout" generators, in some cases we need a new temporary, and in
4248 some cases we can write to a TCG global. */
4250 static void prep_new(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4252 o
->out
= tcg_temp_new_i64();
4254 #define SPEC_prep_new 0
4256 static void prep_new_P(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4258 o
->out
= tcg_temp_new_i64();
4259 o
->out2
= tcg_temp_new_i64();
4261 #define SPEC_prep_new_P 0
4263 static void prep_r1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4265 o
->out
= regs
[get_field(f
, r1
)];
4268 #define SPEC_prep_r1 0
4270 static void prep_r1_P(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4272 int r1
= get_field(f
, r1
);
4274 o
->out2
= regs
[r1
+ 1];
4275 o
->g_out
= o
->g_out2
= true;
4277 #define SPEC_prep_r1_P SPEC_r1_even
4279 static void prep_f1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4281 o
->out
= fregs
[get_field(f
, r1
)];
4284 #define SPEC_prep_f1 0
4286 static void prep_x1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4288 int r1
= get_field(f
, r1
);
4290 o
->out2
= fregs
[r1
+ 2];
4291 o
->g_out
= o
->g_out2
= true;
4293 #define SPEC_prep_x1 SPEC_r1_f128
4295 /* ====================================================================== */
4296 /* The "Write OUTput" generators. These generally perform some non-trivial
4297 copy of data to TCG globals, or to main memory. The trivial cases are
4298 generally handled by having a "prep" generator install the TCG global
4299 as the destination of the operation. */
4301 static void wout_r1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4303 store_reg(get_field(f
, r1
), o
->out
);
4305 #define SPEC_wout_r1 0
4307 static void wout_r1_8(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4309 int r1
= get_field(f
, r1
);
4310 tcg_gen_deposit_i64(regs
[r1
], regs
[r1
], o
->out
, 0, 8);
4312 #define SPEC_wout_r1_8 0
4314 static void wout_r1_16(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4316 int r1
= get_field(f
, r1
);
4317 tcg_gen_deposit_i64(regs
[r1
], regs
[r1
], o
->out
, 0, 16);
4319 #define SPEC_wout_r1_16 0
4321 static void wout_r1_32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4323 store_reg32_i64(get_field(f
, r1
), o
->out
);
4325 #define SPEC_wout_r1_32 0
4327 static void wout_r1_32h(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4329 store_reg32h_i64(get_field(f
, r1
), o
->out
);
4331 #define SPEC_wout_r1_32h 0
4333 static void wout_r1_P32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4335 int r1
= get_field(f
, r1
);
4336 store_reg32_i64(r1
, o
->out
);
4337 store_reg32_i64(r1
+ 1, o
->out2
);
4339 #define SPEC_wout_r1_P32 SPEC_r1_even
4341 static void wout_r1_D32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4343 int r1
= get_field(f
, r1
);
4344 store_reg32_i64(r1
+ 1, o
->out
);
4345 tcg_gen_shri_i64(o
->out
, o
->out
, 32);
4346 store_reg32_i64(r1
, o
->out
);
4348 #define SPEC_wout_r1_D32 SPEC_r1_even
4350 static void wout_e1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4352 store_freg32_i64(get_field(f
, r1
), o
->out
);
4354 #define SPEC_wout_e1 0
4356 static void wout_f1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4358 store_freg(get_field(f
, r1
), o
->out
);
4360 #define SPEC_wout_f1 0
4362 static void wout_x1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4364 int f1
= get_field(s
->fields
, r1
);
4365 store_freg(f1
, o
->out
);
4366 store_freg(f1
+ 2, o
->out2
);
4368 #define SPEC_wout_x1 SPEC_r1_f128
4370 static void wout_cond_r1r2_32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4372 if (get_field(f
, r1
) != get_field(f
, r2
)) {
4373 store_reg32_i64(get_field(f
, r1
), o
->out
);
4376 #define SPEC_wout_cond_r1r2_32 0
4378 static void wout_cond_e1e2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4380 if (get_field(f
, r1
) != get_field(f
, r2
)) {
4381 store_freg32_i64(get_field(f
, r1
), o
->out
);
4384 #define SPEC_wout_cond_e1e2 0
4386 static void wout_m1_8(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4388 tcg_gen_qemu_st8(o
->out
, o
->addr1
, get_mem_index(s
));
4390 #define SPEC_wout_m1_8 0
4392 static void wout_m1_16(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4394 tcg_gen_qemu_st16(o
->out
, o
->addr1
, get_mem_index(s
));
4396 #define SPEC_wout_m1_16 0
4398 static void wout_m1_32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4400 tcg_gen_qemu_st32(o
->out
, o
->addr1
, get_mem_index(s
));
4402 #define SPEC_wout_m1_32 0
4404 static void wout_m1_64(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4406 tcg_gen_qemu_st64(o
->out
, o
->addr1
, get_mem_index(s
));
4408 #define SPEC_wout_m1_64 0
4410 static void wout_m2_32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4412 tcg_gen_qemu_st32(o
->out
, o
->in2
, get_mem_index(s
));
4414 #define SPEC_wout_m2_32 0
4416 static void wout_m2_32_r1_atomic(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4418 /* XXX release reservation */
4419 tcg_gen_qemu_st32(o
->out
, o
->addr1
, get_mem_index(s
));
4420 store_reg32_i64(get_field(f
, r1
), o
->in2
);
4422 #define SPEC_wout_m2_32_r1_atomic 0
4424 static void wout_m2_64_r1_atomic(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4426 /* XXX release reservation */
4427 tcg_gen_qemu_st64(o
->out
, o
->addr1
, get_mem_index(s
));
4428 store_reg(get_field(f
, r1
), o
->in2
);
4430 #define SPEC_wout_m2_64_r1_atomic 0
4432 /* ====================================================================== */
4433 /* The "INput 1" generators. These load the first operand to an insn. */
4435 static void in1_r1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4437 o
->in1
= load_reg(get_field(f
, r1
));
4439 #define SPEC_in1_r1 0
4441 static void in1_r1_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4443 o
->in1
= regs
[get_field(f
, r1
)];
4446 #define SPEC_in1_r1_o 0
4448 static void in1_r1_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4450 o
->in1
= tcg_temp_new_i64();
4451 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(f
, r1
)]);
4453 #define SPEC_in1_r1_32s 0
4455 static void in1_r1_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4457 o
->in1
= tcg_temp_new_i64();
4458 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(f
, r1
)]);
4460 #define SPEC_in1_r1_32u 0
4462 static void in1_r1_sr32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4464 o
->in1
= tcg_temp_new_i64();
4465 tcg_gen_shri_i64(o
->in1
, regs
[get_field(f
, r1
)], 32);
4467 #define SPEC_in1_r1_sr32 0
4469 static void in1_r1p1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4471 o
->in1
= load_reg(get_field(f
, r1
) + 1);
4473 #define SPEC_in1_r1p1 SPEC_r1_even
4475 static void in1_r1p1_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4477 o
->in1
= tcg_temp_new_i64();
4478 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(f
, r1
) + 1]);
4480 #define SPEC_in1_r1p1_32s SPEC_r1_even
4482 static void in1_r1p1_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4484 o
->in1
= tcg_temp_new_i64();
4485 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(f
, r1
) + 1]);
4487 #define SPEC_in1_r1p1_32u SPEC_r1_even
4489 static void in1_r1_D32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4491 int r1
= get_field(f
, r1
);
4492 o
->in1
= tcg_temp_new_i64();
4493 tcg_gen_concat32_i64(o
->in1
, regs
[r1
+ 1], regs
[r1
]);
4495 #define SPEC_in1_r1_D32 SPEC_r1_even
4497 static void in1_r2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4499 o
->in1
= load_reg(get_field(f
, r2
));
4501 #define SPEC_in1_r2 0
4503 static void in1_r2_sr32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4505 o
->in1
= tcg_temp_new_i64();
4506 tcg_gen_shri_i64(o
->in1
, regs
[get_field(f
, r2
)], 32);
4508 #define SPEC_in1_r2_sr32 0
4510 static void in1_r3(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4512 o
->in1
= load_reg(get_field(f
, r3
));
4514 #define SPEC_in1_r3 0
4516 static void in1_r3_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4518 o
->in1
= regs
[get_field(f
, r3
)];
4521 #define SPEC_in1_r3_o 0
4523 static void in1_r3_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4525 o
->in1
= tcg_temp_new_i64();
4526 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(f
, r3
)]);
4528 #define SPEC_in1_r3_32s 0
4530 static void in1_r3_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4532 o
->in1
= tcg_temp_new_i64();
4533 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(f
, r3
)]);
4535 #define SPEC_in1_r3_32u 0
4537 static void in1_r3_D32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4539 int r3
= get_field(f
, r3
);
4540 o
->in1
= tcg_temp_new_i64();
4541 tcg_gen_concat32_i64(o
->in1
, regs
[r3
+ 1], regs
[r3
]);
4543 #define SPEC_in1_r3_D32 SPEC_r3_even
4545 static void in1_e1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4547 o
->in1
= load_freg32_i64(get_field(f
, r1
));
4549 #define SPEC_in1_e1 0
4551 static void in1_f1_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4553 o
->in1
= fregs
[get_field(f
, r1
)];
4556 #define SPEC_in1_f1_o 0
4558 static void in1_x1_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4560 int r1
= get_field(f
, r1
);
4562 o
->out2
= fregs
[r1
+ 2];
4563 o
->g_out
= o
->g_out2
= true;
4565 #define SPEC_in1_x1_o SPEC_r1_f128
4567 static void in1_f3_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4569 o
->in1
= fregs
[get_field(f
, r3
)];
4572 #define SPEC_in1_f3_o 0
4574 static void in1_la1(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4576 o
->addr1
= get_address(s
, 0, get_field(f
, b1
), get_field(f
, d1
));
4578 #define SPEC_in1_la1 0
4580 static void in1_la2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4582 int x2
= have_field(f
, x2
) ? get_field(f
, x2
) : 0;
4583 o
->addr1
= get_address(s
, x2
, get_field(f
, b2
), get_field(f
, d2
));
4585 #define SPEC_in1_la2 0
4587 static void in1_m1_8u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4590 o
->in1
= tcg_temp_new_i64();
4591 tcg_gen_qemu_ld8u(o
->in1
, o
->addr1
, get_mem_index(s
));
4593 #define SPEC_in1_m1_8u 0
4595 static void in1_m1_16s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4598 o
->in1
= tcg_temp_new_i64();
4599 tcg_gen_qemu_ld16s(o
->in1
, o
->addr1
, get_mem_index(s
));
4601 #define SPEC_in1_m1_16s 0
4603 static void in1_m1_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4606 o
->in1
= tcg_temp_new_i64();
4607 tcg_gen_qemu_ld16u(o
->in1
, o
->addr1
, get_mem_index(s
));
4609 #define SPEC_in1_m1_16u 0
4611 static void in1_m1_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4614 o
->in1
= tcg_temp_new_i64();
4615 tcg_gen_qemu_ld32s(o
->in1
, o
->addr1
, get_mem_index(s
));
4617 #define SPEC_in1_m1_32s 0
4619 static void in1_m1_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4622 o
->in1
= tcg_temp_new_i64();
4623 tcg_gen_qemu_ld32u(o
->in1
, o
->addr1
, get_mem_index(s
));
4625 #define SPEC_in1_m1_32u 0
4627 static void in1_m1_64(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4630 o
->in1
= tcg_temp_new_i64();
4631 tcg_gen_qemu_ld64(o
->in1
, o
->addr1
, get_mem_index(s
));
4633 #define SPEC_in1_m1_64 0
4635 /* ====================================================================== */
4636 /* The "INput 2" generators. These load the second operand to an insn. */
4638 static void in2_r1_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4640 o
->in2
= regs
[get_field(f
, r1
)];
4643 #define SPEC_in2_r1_o 0
4645 static void in2_r1_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4647 o
->in2
= tcg_temp_new_i64();
4648 tcg_gen_ext16u_i64(o
->in2
, regs
[get_field(f
, r1
)]);
4650 #define SPEC_in2_r1_16u 0
4652 static void in2_r1_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4654 o
->in2
= tcg_temp_new_i64();
4655 tcg_gen_ext32u_i64(o
->in2
, regs
[get_field(f
, r1
)]);
4657 #define SPEC_in2_r1_32u 0
4659 static void in2_r1_D32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4661 int r1
= get_field(f
, r1
);
4662 o
->in2
= tcg_temp_new_i64();
4663 tcg_gen_concat32_i64(o
->in2
, regs
[r1
+ 1], regs
[r1
]);
4665 #define SPEC_in2_r1_D32 SPEC_r1_even
4667 static void in2_r2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4669 o
->in2
= load_reg(get_field(f
, r2
));
4671 #define SPEC_in2_r2 0
4673 static void in2_r2_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4675 o
->in2
= regs
[get_field(f
, r2
)];
4678 #define SPEC_in2_r2_o 0
4680 static void in2_r2_nz(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4682 int r2
= get_field(f
, r2
);
4684 o
->in2
= load_reg(r2
);
4687 #define SPEC_in2_r2_nz 0
4689 static void in2_r2_8s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4691 o
->in2
= tcg_temp_new_i64();
4692 tcg_gen_ext8s_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4694 #define SPEC_in2_r2_8s 0
4696 static void in2_r2_8u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4698 o
->in2
= tcg_temp_new_i64();
4699 tcg_gen_ext8u_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4701 #define SPEC_in2_r2_8u 0
4703 static void in2_r2_16s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4705 o
->in2
= tcg_temp_new_i64();
4706 tcg_gen_ext16s_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4708 #define SPEC_in2_r2_16s 0
4710 static void in2_r2_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4712 o
->in2
= tcg_temp_new_i64();
4713 tcg_gen_ext16u_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4715 #define SPEC_in2_r2_16u 0
4717 static void in2_r3(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4719 o
->in2
= load_reg(get_field(f
, r3
));
4721 #define SPEC_in2_r3 0
4723 static void in2_r3_sr32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4725 o
->in2
= tcg_temp_new_i64();
4726 tcg_gen_shri_i64(o
->in2
, regs
[get_field(f
, r3
)], 32);
4728 #define SPEC_in2_r3_sr32 0
4730 static void in2_r2_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4732 o
->in2
= tcg_temp_new_i64();
4733 tcg_gen_ext32s_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4735 #define SPEC_in2_r2_32s 0
4737 static void in2_r2_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4739 o
->in2
= tcg_temp_new_i64();
4740 tcg_gen_ext32u_i64(o
->in2
, regs
[get_field(f
, r2
)]);
4742 #define SPEC_in2_r2_32u 0
4744 static void in2_r2_sr32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4746 o
->in2
= tcg_temp_new_i64();
4747 tcg_gen_shri_i64(o
->in2
, regs
[get_field(f
, r2
)], 32);
4749 #define SPEC_in2_r2_sr32 0
4751 static void in2_e2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4753 o
->in2
= load_freg32_i64(get_field(f
, r2
));
4755 #define SPEC_in2_e2 0
4757 static void in2_f2_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4759 o
->in2
= fregs
[get_field(f
, r2
)];
4762 #define SPEC_in2_f2_o 0
4764 static void in2_x2_o(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4766 int r2
= get_field(f
, r2
);
4768 o
->in2
= fregs
[r2
+ 2];
4769 o
->g_in1
= o
->g_in2
= true;
4771 #define SPEC_in2_x2_o SPEC_r2_f128
4773 static void in2_ra2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4775 o
->in2
= get_address(s
, 0, get_field(f
, r2
), 0);
4777 #define SPEC_in2_ra2 0
4779 static void in2_a2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4781 int x2
= have_field(f
, x2
) ? get_field(f
, x2
) : 0;
4782 o
->in2
= get_address(s
, x2
, get_field(f
, b2
), get_field(f
, d2
));
4784 #define SPEC_in2_a2 0
4786 static void in2_ri2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4788 o
->in2
= tcg_const_i64(s
->pc
+ (int64_t)get_field(f
, i2
) * 2);
4790 #define SPEC_in2_ri2 0
4792 static void in2_sh32(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4794 help_l2_shift(s
, f
, o
, 31);
4796 #define SPEC_in2_sh32 0
4798 static void in2_sh64(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4800 help_l2_shift(s
, f
, o
, 63);
4802 #define SPEC_in2_sh64 0
4804 static void in2_m2_8u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4807 tcg_gen_qemu_ld8u(o
->in2
, o
->in2
, get_mem_index(s
));
4809 #define SPEC_in2_m2_8u 0
4811 static void in2_m2_16s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4814 tcg_gen_qemu_ld16s(o
->in2
, o
->in2
, get_mem_index(s
));
4816 #define SPEC_in2_m2_16s 0
4818 static void in2_m2_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4821 tcg_gen_qemu_ld16u(o
->in2
, o
->in2
, get_mem_index(s
));
4823 #define SPEC_in2_m2_16u 0
4825 static void in2_m2_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4828 tcg_gen_qemu_ld32s(o
->in2
, o
->in2
, get_mem_index(s
));
4830 #define SPEC_in2_m2_32s 0
4832 static void in2_m2_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4835 tcg_gen_qemu_ld32u(o
->in2
, o
->in2
, get_mem_index(s
));
4837 #define SPEC_in2_m2_32u 0
4839 static void in2_m2_64(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4842 tcg_gen_qemu_ld64(o
->in2
, o
->in2
, get_mem_index(s
));
4844 #define SPEC_in2_m2_64 0
4846 static void in2_mri2_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4849 tcg_gen_qemu_ld16u(o
->in2
, o
->in2
, get_mem_index(s
));
4851 #define SPEC_in2_mri2_16u 0
4853 static void in2_mri2_32s(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4856 tcg_gen_qemu_ld32s(o
->in2
, o
->in2
, get_mem_index(s
));
4858 #define SPEC_in2_mri2_32s 0
4860 static void in2_mri2_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4863 tcg_gen_qemu_ld32u(o
->in2
, o
->in2
, get_mem_index(s
));
4865 #define SPEC_in2_mri2_32u 0
4867 static void in2_mri2_64(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4870 tcg_gen_qemu_ld64(o
->in2
, o
->in2
, get_mem_index(s
));
4872 #define SPEC_in2_mri2_64 0
4874 static void in2_m2_32s_atomic(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4876 /* XXX should reserve the address */
4878 o
->in2
= tcg_temp_new_i64();
4879 tcg_gen_qemu_ld32s(o
->in2
, o
->addr1
, get_mem_index(s
));
4881 #define SPEC_in2_m2_32s_atomic 0
4883 static void in2_m2_64_atomic(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4885 /* XXX should reserve the address */
4887 o
->in2
= tcg_temp_new_i64();
4888 tcg_gen_qemu_ld64(o
->in2
, o
->addr1
, get_mem_index(s
));
4890 #define SPEC_in2_m2_64_atomic 0
4892 static void in2_i2(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4894 o
->in2
= tcg_const_i64(get_field(f
, i2
));
4896 #define SPEC_in2_i2 0
4898 static void in2_i2_8u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4900 o
->in2
= tcg_const_i64((uint8_t)get_field(f
, i2
));
4902 #define SPEC_in2_i2_8u 0
4904 static void in2_i2_16u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4906 o
->in2
= tcg_const_i64((uint16_t)get_field(f
, i2
));
4908 #define SPEC_in2_i2_16u 0
4910 static void in2_i2_32u(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4912 o
->in2
= tcg_const_i64((uint32_t)get_field(f
, i2
));
4914 #define SPEC_in2_i2_32u 0
4916 static void in2_i2_16u_shl(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4918 uint64_t i2
= (uint16_t)get_field(f
, i2
);
4919 o
->in2
= tcg_const_i64(i2
<< s
->insn
->data
);
4921 #define SPEC_in2_i2_16u_shl 0
4923 static void in2_i2_32u_shl(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4925 uint64_t i2
= (uint32_t)get_field(f
, i2
);
4926 o
->in2
= tcg_const_i64(i2
<< s
->insn
->data
);
4928 #define SPEC_in2_i2_32u_shl 0
4930 #ifndef CONFIG_USER_ONLY
4931 static void in2_insn(DisasContext
*s
, DisasFields
*f
, DisasOps
*o
)
4933 o
->in2
= tcg_const_i64(s
->fields
->raw_insn
);
4935 #define SPEC_in2_insn 0
4938 /* ====================================================================== */
4940 /* Find opc within the table of insns. This is formulated as a switch
4941 statement so that (1) we get compile-time notice of cut-paste errors
4942 for duplicated opcodes, and (2) the compiler generates the binary
4943 search tree, rather than us having to post-process the table. */
4945 #define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
4946 D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0)
4948 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) insn_ ## NM,
4950 enum DisasInsnEnum
{
4951 #include "insn-data.def"
4955 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) { \
4959 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
4961 .help_in1 = in1_##I1, \
4962 .help_in2 = in2_##I2, \
4963 .help_prep = prep_##P, \
4964 .help_wout = wout_##W, \
4965 .help_cout = cout_##CC, \
4966 .help_op = op_##OP, \
4970 /* Allow 0 to be used for NULL in the table below. */
4978 #define SPEC_in1_0 0
4979 #define SPEC_in2_0 0
4980 #define SPEC_prep_0 0
4981 #define SPEC_wout_0 0
4983 static const DisasInsn insn_info
[] = {
4984 #include "insn-data.def"
4988 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
4989 case OPC: return &insn_info[insn_ ## NM];
4991 static const DisasInsn
*lookup_opc(uint16_t opc
)
4994 #include "insn-data.def"
5003 /* Extract a field from the insn. The INSN should be left-aligned in
5004 the uint64_t so that we can more easily utilize the big-bit-endian
5005 definitions we extract from the Principals of Operation. */
5007 static void extract_field(DisasFields
*o
, const DisasField
*f
, uint64_t insn
)
5015 /* Zero extract the field from the insn. */
5016 r
= (insn
<< f
->beg
) >> (64 - f
->size
);
5018 /* Sign-extend, or un-swap the field as necessary. */
5020 case 0: /* unsigned */
5022 case 1: /* signed */
5023 assert(f
->size
<= 32);
5024 m
= 1u << (f
->size
- 1);
5027 case 2: /* dl+dh split, signed 20 bit. */
5028 r
= ((int8_t)r
<< 12) | (r
>> 8);
5034 /* Validate that the "compressed" encoding we selected above is valid.
5035 I.e. we havn't make two different original fields overlap. */
5036 assert(((o
->presentC
>> f
->indexC
) & 1) == 0);
5037 o
->presentC
|= 1 << f
->indexC
;
5038 o
->presentO
|= 1 << f
->indexO
;
5040 o
->c
[f
->indexC
] = r
;
5043 /* Lookup the insn at the current PC, extracting the operands into O and
5044 returning the info struct for the insn. Returns NULL for invalid insn. */
5046 static const DisasInsn
*extract_insn(CPUS390XState
*env
, DisasContext
*s
,
5049 uint64_t insn
, pc
= s
->pc
;
5051 const DisasInsn
*info
;
5053 insn
= ld_code2(env
, pc
);
5054 op
= (insn
>> 8) & 0xff;
5055 ilen
= get_ilen(op
);
5056 s
->next_pc
= s
->pc
+ ilen
;
5063 insn
= ld_code4(env
, pc
) << 32;
5066 insn
= (insn
<< 48) | (ld_code4(env
, pc
+ 2) << 16);
5072 /* We can't actually determine the insn format until we've looked up
5073 the full insn opcode. Which we can't do without locating the
5074 secondary opcode. Assume by default that OP2 is at bit 40; for
5075 those smaller insns that don't actually have a secondary opcode
5076 this will correctly result in OP2 = 0. */
5082 case 0xb2: /* S, RRF, RRE */
5083 case 0xb3: /* RRE, RRD, RRF */
5084 case 0xb9: /* RRE, RRF */
5085 case 0xe5: /* SSE, SIL */
5086 op2
= (insn
<< 8) >> 56;
5090 case 0xc0: /* RIL */
5091 case 0xc2: /* RIL */
5092 case 0xc4: /* RIL */
5093 case 0xc6: /* RIL */
5094 case 0xc8: /* SSF */
5095 case 0xcc: /* RIL */
5096 op2
= (insn
<< 12) >> 60;
5098 case 0xd0 ... 0xdf: /* SS */
5104 case 0xee ... 0xf3: /* SS */
5105 case 0xf8 ... 0xfd: /* SS */
5109 op2
= (insn
<< 40) >> 56;
5113 memset(f
, 0, sizeof(*f
));
5118 /* Lookup the instruction. */
5119 info
= lookup_opc(op
<< 8 | op2
);
5121 /* If we found it, extract the operands. */
5123 DisasFormat fmt
= info
->fmt
;
5126 for (i
= 0; i
< NUM_C_FIELD
; ++i
) {
5127 extract_field(f
, &format_info
[fmt
].op
[i
], insn
);
5133 static ExitStatus
translate_one(CPUS390XState
*env
, DisasContext
*s
)
5135 const DisasInsn
*insn
;
5136 ExitStatus ret
= NO_EXIT
;
5140 /* Search for the insn in the table. */
5141 insn
= extract_insn(env
, s
, &f
);
5143 /* Not found means unimplemented/illegal opcode. */
5145 qemu_log_mask(LOG_UNIMP
, "unimplemented opcode 0x%02x%02x\n",
5147 gen_illegal_opcode(s
);
5148 return EXIT_NORETURN
;
5151 /* Check for insn specification exceptions. */
5153 int spec
= insn
->spec
, excp
= 0, r
;
5155 if (spec
& SPEC_r1_even
) {
5156 r
= get_field(&f
, r1
);
5158 excp
= PGM_SPECIFICATION
;
5161 if (spec
& SPEC_r2_even
) {
5162 r
= get_field(&f
, r2
);
5164 excp
= PGM_SPECIFICATION
;
5167 if (spec
& SPEC_r3_even
) {
5168 r
= get_field(&f
, r3
);
5170 excp
= PGM_SPECIFICATION
;
5173 if (spec
& SPEC_r1_f128
) {
5174 r
= get_field(&f
, r1
);
5176 excp
= PGM_SPECIFICATION
;
5179 if (spec
& SPEC_r2_f128
) {
5180 r
= get_field(&f
, r2
);
5182 excp
= PGM_SPECIFICATION
;
5186 gen_program_exception(s
, excp
);
5187 return EXIT_NORETURN
;
5191 /* Set up the strutures we use to communicate with the helpers. */
5194 o
.g_out
= o
.g_out2
= o
.g_in1
= o
.g_in2
= false;
5195 TCGV_UNUSED_I64(o
.out
);
5196 TCGV_UNUSED_I64(o
.out2
);
5197 TCGV_UNUSED_I64(o
.in1
);
5198 TCGV_UNUSED_I64(o
.in2
);
5199 TCGV_UNUSED_I64(o
.addr1
);
5201 /* Implement the instruction. */
5202 if (insn
->help_in1
) {
5203 insn
->help_in1(s
, &f
, &o
);
5205 if (insn
->help_in2
) {
5206 insn
->help_in2(s
, &f
, &o
);
5208 if (insn
->help_prep
) {
5209 insn
->help_prep(s
, &f
, &o
);
5211 if (insn
->help_op
) {
5212 ret
= insn
->help_op(s
, &o
);
5214 if (insn
->help_wout
) {
5215 insn
->help_wout(s
, &f
, &o
);
5217 if (insn
->help_cout
) {
5218 insn
->help_cout(s
, &o
);
5221 /* Free any temporaries created by the helpers. */
5222 if (!TCGV_IS_UNUSED_I64(o
.out
) && !o
.g_out
) {
5223 tcg_temp_free_i64(o
.out
);
5225 if (!TCGV_IS_UNUSED_I64(o
.out2
) && !o
.g_out2
) {
5226 tcg_temp_free_i64(o
.out2
);
5228 if (!TCGV_IS_UNUSED_I64(o
.in1
) && !o
.g_in1
) {
5229 tcg_temp_free_i64(o
.in1
);
5231 if (!TCGV_IS_UNUSED_I64(o
.in2
) && !o
.g_in2
) {
5232 tcg_temp_free_i64(o
.in2
);
5234 if (!TCGV_IS_UNUSED_I64(o
.addr1
)) {
5235 tcg_temp_free_i64(o
.addr1
);
5238 #ifndef CONFIG_USER_ONLY
5239 if (s
->tb
->flags
& FLAG_MASK_PER
) {
5240 /* An exception might be triggered, save PSW if not already done. */
5241 if (ret
== NO_EXIT
|| ret
== EXIT_PC_STALE
) {
5242 tcg_gen_movi_i64(psw_addr
, s
->next_pc
);
5248 /* Call the helper to check for a possible PER exception. */
5249 gen_helper_per_check_exception(cpu_env
);
5253 /* Advance to the next instruction. */
5258 static inline void gen_intermediate_code_internal(S390CPU
*cpu
,
5259 TranslationBlock
*tb
,
5262 CPUState
*cs
= CPU(cpu
);
5263 CPUS390XState
*env
= &cpu
->env
;
5265 target_ulong pc_start
;
5266 uint64_t next_page_start
;
5268 int num_insns
, max_insns
;
5276 if (!(tb
->flags
& FLAG_MASK_64
)) {
5277 pc_start
&= 0x7fffffff;
5282 dc
.cc_op
= CC_OP_DYNAMIC
;
5283 do_debug
= dc
.singlestep_enabled
= cs
->singlestep_enabled
;
5285 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
5288 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
5289 if (max_insns
== 0) {
5290 max_insns
= CF_COUNT_MASK
;
5297 j
= tcg_op_buf_count();
5301 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
5304 tcg_ctx
.gen_opc_pc
[lj
] = dc
.pc
;
5305 gen_opc_cc_op
[lj
] = dc
.cc_op
;
5306 tcg_ctx
.gen_opc_instr_start
[lj
] = 1;
5307 tcg_ctx
.gen_opc_icount
[lj
] = num_insns
;
5309 if (++num_insns
== max_insns
&& (tb
->cflags
& CF_LAST_IO
)) {
5313 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
5314 tcg_gen_debug_insn_start(dc
.pc
);
5318 if (unlikely(!QTAILQ_EMPTY(&cs
->breakpoints
))) {
5319 QTAILQ_FOREACH(bp
, &cs
->breakpoints
, entry
) {
5320 if (bp
->pc
== dc
.pc
) {
5321 status
= EXIT_PC_STALE
;
5327 if (status
== NO_EXIT
) {
5328 status
= translate_one(env
, &dc
);
5331 /* If we reach a page boundary, are single stepping,
5332 or exhaust instruction count, stop generation. */
5333 if (status
== NO_EXIT
5334 && (dc
.pc
>= next_page_start
5335 || tcg_op_buf_full()
5336 || num_insns
>= max_insns
5338 || cs
->singlestep_enabled
)) {
5339 status
= EXIT_PC_STALE
;
5341 } while (status
== NO_EXIT
);
5343 if (tb
->cflags
& CF_LAST_IO
) {
5352 update_psw_addr(&dc
);
5354 case EXIT_PC_UPDATED
:
5355 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
5356 cc op type is in env */
5358 /* Exit the TB, either by raising a debug exception or by return. */
5360 gen_exception(EXCP_DEBUG
);
5369 gen_tb_end(tb
, num_insns
);
5372 j
= tcg_op_buf_count();
5375 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
5378 tb
->size
= dc
.pc
- pc_start
;
5379 tb
->icount
= num_insns
;
5382 #if defined(S390X_DEBUG_DISAS)
5383 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
5384 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
5385 log_target_disas(env
, pc_start
, dc
.pc
- pc_start
, 1);
5391 void gen_intermediate_code (CPUS390XState
*env
, struct TranslationBlock
*tb
)
5393 gen_intermediate_code_internal(s390_env_get_cpu(env
), tb
, false);
5396 void gen_intermediate_code_pc (CPUS390XState
*env
, struct TranslationBlock
*tb
)
5398 gen_intermediate_code_internal(s390_env_get_cpu(env
), tb
, true);
5401 void restore_state_to_opc(CPUS390XState
*env
, TranslationBlock
*tb
, int pc_pos
)
5404 env
->psw
.addr
= tcg_ctx
.gen_opc_pc
[pc_pos
];
5405 cc_op
= gen_opc_cc_op
[pc_pos
];
5406 if ((cc_op
!= CC_OP_DYNAMIC
) && (cc_op
!= CC_OP_STATIC
)) {