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.1 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)
31 #include "qemu/osdep.h"
33 #include "s390x-internal.h"
34 #include "disas/disas.h"
35 #include "exec/exec-all.h"
36 #include "tcg/tcg-op.h"
37 #include "tcg/tcg-op-gvec.h"
39 #include "qemu/host-utils.h"
40 #include "exec/cpu_ldst.h"
41 #include "exec/gen-icount.h"
42 #include "exec/helper-proto.h"
43 #include "exec/helper-gen.h"
45 #include "exec/translator.h"
47 #include "qemu/atomic128.h"
50 /* Information that (most) every instruction needs to manipulate. */
51 typedef struct DisasContext DisasContext
;
52 typedef struct DisasInsn DisasInsn
;
53 typedef struct DisasFields DisasFields
;
56 * Define a structure to hold the decoded fields. We'll store each inside
57 * an array indexed by an enum. In order to conserve memory, we'll arrange
58 * for fields that do not exist at the same time to overlap, thus the "C"
59 * for compact. For checking purposes there is an "O" for original index
60 * as well that will be applied to availability bitmaps.
63 enum DisasFieldIndexO
{
92 enum DisasFieldIndexC
{
133 unsigned presentC
:16;
134 unsigned int presentO
;
138 struct DisasContext
{
139 DisasContextBase base
;
140 const DisasInsn
*insn
;
145 * During translate_one(), pc_tmp is used to determine the instruction
146 * to be executed after base.pc_next - e.g. next sequential instruction
147 * or a branch target.
154 /* Information carried about a condition to be evaluated. */
161 struct { TCGv_i64 a
, b
; } s64
;
162 struct { TCGv_i32 a
, b
; } s32
;
166 #ifdef DEBUG_INLINE_BRANCHES
167 static uint64_t inline_branch_hit
[CC_OP_MAX
];
168 static uint64_t inline_branch_miss
[CC_OP_MAX
];
171 static void pc_to_link_info(TCGv_i64 out
, DisasContext
*s
, uint64_t pc
)
175 if (s
->base
.tb
->flags
& FLAG_MASK_32
) {
176 if (s
->base
.tb
->flags
& FLAG_MASK_64
) {
177 tcg_gen_movi_i64(out
, pc
);
182 assert(!(s
->base
.tb
->flags
& FLAG_MASK_64
));
183 tmp
= tcg_const_i64(pc
);
184 tcg_gen_deposit_i64(out
, out
, tmp
, 0, 32);
185 tcg_temp_free_i64(tmp
);
188 static TCGv_i64 psw_addr
;
189 static TCGv_i64 psw_mask
;
190 static TCGv_i64 gbea
;
192 static TCGv_i32 cc_op
;
193 static TCGv_i64 cc_src
;
194 static TCGv_i64 cc_dst
;
195 static TCGv_i64 cc_vr
;
197 static char cpu_reg_names
[16][4];
198 static TCGv_i64 regs
[16];
200 void s390x_translate_init(void)
204 psw_addr
= tcg_global_mem_new_i64(cpu_env
,
205 offsetof(CPUS390XState
, psw
.addr
),
207 psw_mask
= tcg_global_mem_new_i64(cpu_env
,
208 offsetof(CPUS390XState
, psw
.mask
),
210 gbea
= tcg_global_mem_new_i64(cpu_env
,
211 offsetof(CPUS390XState
, gbea
),
214 cc_op
= tcg_global_mem_new_i32(cpu_env
, offsetof(CPUS390XState
, cc_op
),
216 cc_src
= tcg_global_mem_new_i64(cpu_env
, offsetof(CPUS390XState
, cc_src
),
218 cc_dst
= tcg_global_mem_new_i64(cpu_env
, offsetof(CPUS390XState
, cc_dst
),
220 cc_vr
= tcg_global_mem_new_i64(cpu_env
, offsetof(CPUS390XState
, cc_vr
),
223 for (i
= 0; i
< 16; i
++) {
224 snprintf(cpu_reg_names
[i
], sizeof(cpu_reg_names
[0]), "r%d", i
);
225 regs
[i
] = tcg_global_mem_new(cpu_env
,
226 offsetof(CPUS390XState
, regs
[i
]),
231 static inline int vec_full_reg_offset(uint8_t reg
)
234 return offsetof(CPUS390XState
, vregs
[reg
][0]);
237 static inline int vec_reg_offset(uint8_t reg
, uint8_t enr
, MemOp es
)
239 /* Convert element size (es) - e.g. MO_8 - to bytes */
240 const uint8_t bytes
= 1 << es
;
241 int offs
= enr
* bytes
;
244 * vregs[n][0] is the lowest 8 byte and vregs[n][1] the highest 8 byte
245 * of the 16 byte vector, on both, little and big endian systems.
247 * Big Endian (target/possible host)
248 * B: [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
249 * HW: [ 0][ 1][ 2][ 3] - [ 4][ 5][ 6][ 7]
250 * W: [ 0][ 1] - [ 2][ 3]
253 * Little Endian (possible host)
254 * B: [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
255 * HW: [ 3][ 2][ 1][ 0] - [ 7][ 6][ 5][ 4]
256 * W: [ 1][ 0] - [ 3][ 2]
259 * For 16 byte elements, the two 8 byte halves will not form a host
260 * int128 if the host is little endian, since they're in the wrong order.
261 * Some operations (e.g. xor) do not care. For operations like addition,
262 * the two 8 byte elements have to be loaded separately. Let's force all
263 * 16 byte operations to handle it in a special way.
265 g_assert(es
<= MO_64
);
266 #ifndef HOST_WORDS_BIGENDIAN
269 return offs
+ vec_full_reg_offset(reg
);
272 static inline int freg64_offset(uint8_t reg
)
275 return vec_reg_offset(reg
, 0, MO_64
);
278 static inline int freg32_offset(uint8_t reg
)
281 return vec_reg_offset(reg
, 0, MO_32
);
284 static TCGv_i64
load_reg(int reg
)
286 TCGv_i64 r
= tcg_temp_new_i64();
287 tcg_gen_mov_i64(r
, regs
[reg
]);
291 static TCGv_i64
load_freg(int reg
)
293 TCGv_i64 r
= tcg_temp_new_i64();
295 tcg_gen_ld_i64(r
, cpu_env
, freg64_offset(reg
));
299 static TCGv_i64
load_freg32_i64(int reg
)
301 TCGv_i64 r
= tcg_temp_new_i64();
303 tcg_gen_ld32u_i64(r
, cpu_env
, freg32_offset(reg
));
307 static void store_reg(int reg
, TCGv_i64 v
)
309 tcg_gen_mov_i64(regs
[reg
], v
);
312 static void store_freg(int reg
, TCGv_i64 v
)
314 tcg_gen_st_i64(v
, cpu_env
, freg64_offset(reg
));
317 static void store_reg32_i64(int reg
, TCGv_i64 v
)
319 /* 32 bit register writes keep the upper half */
320 tcg_gen_deposit_i64(regs
[reg
], regs
[reg
], v
, 0, 32);
323 static void store_reg32h_i64(int reg
, TCGv_i64 v
)
325 tcg_gen_deposit_i64(regs
[reg
], regs
[reg
], v
, 32, 32);
328 static void store_freg32_i64(int reg
, TCGv_i64 v
)
330 tcg_gen_st32_i64(v
, cpu_env
, freg32_offset(reg
));
333 static void return_low128(TCGv_i64 dest
)
335 tcg_gen_ld_i64(dest
, cpu_env
, offsetof(CPUS390XState
, retxl
));
338 static void update_psw_addr(DisasContext
*s
)
341 tcg_gen_movi_i64(psw_addr
, s
->base
.pc_next
);
344 static void per_branch(DisasContext
*s
, bool to_next
)
346 #ifndef CONFIG_USER_ONLY
347 tcg_gen_movi_i64(gbea
, s
->base
.pc_next
);
349 if (s
->base
.tb
->flags
& FLAG_MASK_PER
) {
350 TCGv_i64 next_pc
= to_next
? tcg_const_i64(s
->pc_tmp
) : psw_addr
;
351 gen_helper_per_branch(cpu_env
, gbea
, next_pc
);
353 tcg_temp_free_i64(next_pc
);
359 static void per_branch_cond(DisasContext
*s
, TCGCond cond
,
360 TCGv_i64 arg1
, TCGv_i64 arg2
)
362 #ifndef CONFIG_USER_ONLY
363 if (s
->base
.tb
->flags
& FLAG_MASK_PER
) {
364 TCGLabel
*lab
= gen_new_label();
365 tcg_gen_brcond_i64(tcg_invert_cond(cond
), arg1
, arg2
, lab
);
367 tcg_gen_movi_i64(gbea
, s
->base
.pc_next
);
368 gen_helper_per_branch(cpu_env
, gbea
, psw_addr
);
372 TCGv_i64 pc
= tcg_const_i64(s
->base
.pc_next
);
373 tcg_gen_movcond_i64(cond
, gbea
, arg1
, arg2
, gbea
, pc
);
374 tcg_temp_free_i64(pc
);
379 static void per_breaking_event(DisasContext
*s
)
381 tcg_gen_movi_i64(gbea
, s
->base
.pc_next
);
384 static void update_cc_op(DisasContext
*s
)
386 if (s
->cc_op
!= CC_OP_DYNAMIC
&& s
->cc_op
!= CC_OP_STATIC
) {
387 tcg_gen_movi_i32(cc_op
, s
->cc_op
);
391 static inline uint64_t ld_code2(CPUS390XState
*env
, DisasContext
*s
,
394 return (uint64_t)translator_lduw(env
, &s
->base
, pc
);
397 static inline uint64_t ld_code4(CPUS390XState
*env
, DisasContext
*s
,
400 return (uint64_t)(uint32_t)translator_ldl(env
, &s
->base
, pc
);
403 static int get_mem_index(DisasContext
*s
)
405 #ifdef CONFIG_USER_ONLY
408 if (!(s
->base
.tb
->flags
& FLAG_MASK_DAT
)) {
412 switch (s
->base
.tb
->flags
& FLAG_MASK_ASC
) {
413 case PSW_ASC_PRIMARY
>> FLAG_MASK_PSW_SHIFT
:
414 return MMU_PRIMARY_IDX
;
415 case PSW_ASC_SECONDARY
>> FLAG_MASK_PSW_SHIFT
:
416 return MMU_SECONDARY_IDX
;
417 case PSW_ASC_HOME
>> FLAG_MASK_PSW_SHIFT
:
426 static void gen_exception(int excp
)
428 TCGv_i32 tmp
= tcg_const_i32(excp
);
429 gen_helper_exception(cpu_env
, tmp
);
430 tcg_temp_free_i32(tmp
);
433 static void gen_program_exception(DisasContext
*s
, int code
)
437 /* Remember what pgm exeption this was. */
438 tmp
= tcg_const_i32(code
);
439 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUS390XState
, int_pgm_code
));
440 tcg_temp_free_i32(tmp
);
442 tmp
= tcg_const_i32(s
->ilen
);
443 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUS390XState
, int_pgm_ilen
));
444 tcg_temp_free_i32(tmp
);
452 /* Trigger exception. */
453 gen_exception(EXCP_PGM
);
456 static inline void gen_illegal_opcode(DisasContext
*s
)
458 gen_program_exception(s
, PGM_OPERATION
);
461 static inline void gen_data_exception(uint8_t dxc
)
463 TCGv_i32 tmp
= tcg_const_i32(dxc
);
464 gen_helper_data_exception(cpu_env
, tmp
);
465 tcg_temp_free_i32(tmp
);
468 static inline void gen_trap(DisasContext
*s
)
470 /* Set DXC to 0xff */
471 gen_data_exception(0xff);
474 static void gen_addi_and_wrap_i64(DisasContext
*s
, TCGv_i64 dst
, TCGv_i64 src
,
477 tcg_gen_addi_i64(dst
, src
, imm
);
478 if (!(s
->base
.tb
->flags
& FLAG_MASK_64
)) {
479 if (s
->base
.tb
->flags
& FLAG_MASK_32
) {
480 tcg_gen_andi_i64(dst
, dst
, 0x7fffffff);
482 tcg_gen_andi_i64(dst
, dst
, 0x00ffffff);
487 static TCGv_i64
get_address(DisasContext
*s
, int x2
, int b2
, int d2
)
489 TCGv_i64 tmp
= tcg_temp_new_i64();
492 * Note that d2 is limited to 20 bits, signed. If we crop negative
493 * displacements early we create larger immedate addends.
496 tcg_gen_add_i64(tmp
, regs
[b2
], regs
[x2
]);
497 gen_addi_and_wrap_i64(s
, tmp
, tmp
, d2
);
499 gen_addi_and_wrap_i64(s
, tmp
, regs
[b2
], d2
);
501 gen_addi_and_wrap_i64(s
, tmp
, regs
[x2
], d2
);
502 } else if (!(s
->base
.tb
->flags
& FLAG_MASK_64
)) {
503 if (s
->base
.tb
->flags
& FLAG_MASK_32
) {
504 tcg_gen_movi_i64(tmp
, d2
& 0x7fffffff);
506 tcg_gen_movi_i64(tmp
, d2
& 0x00ffffff);
509 tcg_gen_movi_i64(tmp
, d2
);
515 static inline bool live_cc_data(DisasContext
*s
)
517 return (s
->cc_op
!= CC_OP_DYNAMIC
518 && s
->cc_op
!= CC_OP_STATIC
522 static inline void gen_op_movi_cc(DisasContext
*s
, uint32_t val
)
524 if (live_cc_data(s
)) {
525 tcg_gen_discard_i64(cc_src
);
526 tcg_gen_discard_i64(cc_dst
);
527 tcg_gen_discard_i64(cc_vr
);
529 s
->cc_op
= CC_OP_CONST0
+ val
;
532 static void gen_op_update1_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 dst
)
534 if (live_cc_data(s
)) {
535 tcg_gen_discard_i64(cc_src
);
536 tcg_gen_discard_i64(cc_vr
);
538 tcg_gen_mov_i64(cc_dst
, dst
);
542 static void gen_op_update2_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 src
,
545 if (live_cc_data(s
)) {
546 tcg_gen_discard_i64(cc_vr
);
548 tcg_gen_mov_i64(cc_src
, src
);
549 tcg_gen_mov_i64(cc_dst
, dst
);
553 static void gen_op_update3_cc_i64(DisasContext
*s
, enum cc_op op
, TCGv_i64 src
,
554 TCGv_i64 dst
, TCGv_i64 vr
)
556 tcg_gen_mov_i64(cc_src
, src
);
557 tcg_gen_mov_i64(cc_dst
, dst
);
558 tcg_gen_mov_i64(cc_vr
, vr
);
562 static void set_cc_nz_u64(DisasContext
*s
, TCGv_i64 val
)
564 gen_op_update1_cc_i64(s
, CC_OP_NZ
, val
);
567 /* CC value is in env->cc_op */
568 static void set_cc_static(DisasContext
*s
)
570 if (live_cc_data(s
)) {
571 tcg_gen_discard_i64(cc_src
);
572 tcg_gen_discard_i64(cc_dst
);
573 tcg_gen_discard_i64(cc_vr
);
575 s
->cc_op
= CC_OP_STATIC
;
578 /* calculates cc into cc_op */
579 static void gen_op_calc_cc(DisasContext
*s
)
581 TCGv_i32 local_cc_op
= NULL
;
582 TCGv_i64 dummy
= NULL
;
586 dummy
= tcg_const_i64(0);
592 local_cc_op
= tcg_const_i32(s
->cc_op
);
608 /* s->cc_op is the cc value */
609 tcg_gen_movi_i32(cc_op
, s
->cc_op
- CC_OP_CONST0
);
612 /* env->cc_op already is the cc value */
629 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, dummy
, cc_dst
, dummy
);
635 case CC_OP_LTUGTU_32
:
636 case CC_OP_LTUGTU_64
:
645 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, dummy
);
652 gen_helper_calc_cc(cc_op
, cpu_env
, local_cc_op
, cc_src
, cc_dst
, cc_vr
);
655 /* unknown operation - assume 3 arguments and cc_op in env */
656 gen_helper_calc_cc(cc_op
, cpu_env
, cc_op
, cc_src
, cc_dst
, cc_vr
);
663 tcg_temp_free_i32(local_cc_op
);
666 tcg_temp_free_i64(dummy
);
669 /* We now have cc in cc_op as constant */
673 static bool use_goto_tb(DisasContext
*s
, uint64_t dest
)
675 if (unlikely(s
->base
.tb
->flags
& FLAG_MASK_PER
)) {
678 return translator_use_goto_tb(&s
->base
, dest
);
681 static void account_noninline_branch(DisasContext
*s
, int cc_op
)
683 #ifdef DEBUG_INLINE_BRANCHES
684 inline_branch_miss
[cc_op
]++;
688 static void account_inline_branch(DisasContext
*s
, int cc_op
)
690 #ifdef DEBUG_INLINE_BRANCHES
691 inline_branch_hit
[cc_op
]++;
695 /* Table of mask values to comparison codes, given a comparison as input.
696 For such, CC=3 should not be possible. */
697 static const TCGCond ltgt_cond
[16] = {
698 TCG_COND_NEVER
, TCG_COND_NEVER
, /* | | | x */
699 TCG_COND_GT
, TCG_COND_GT
, /* | | GT | x */
700 TCG_COND_LT
, TCG_COND_LT
, /* | LT | | x */
701 TCG_COND_NE
, TCG_COND_NE
, /* | LT | GT | x */
702 TCG_COND_EQ
, TCG_COND_EQ
, /* EQ | | | x */
703 TCG_COND_GE
, TCG_COND_GE
, /* EQ | | GT | x */
704 TCG_COND_LE
, TCG_COND_LE
, /* EQ | LT | | x */
705 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
, /* EQ | LT | GT | x */
708 /* Table of mask values to comparison codes, given a logic op as input.
709 For such, only CC=0 and CC=1 should be possible. */
710 static const TCGCond nz_cond
[16] = {
711 TCG_COND_NEVER
, TCG_COND_NEVER
, /* | | x | x */
712 TCG_COND_NEVER
, TCG_COND_NEVER
,
713 TCG_COND_NE
, TCG_COND_NE
, /* | NE | x | x */
714 TCG_COND_NE
, TCG_COND_NE
,
715 TCG_COND_EQ
, TCG_COND_EQ
, /* EQ | | x | x */
716 TCG_COND_EQ
, TCG_COND_EQ
,
717 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
, /* EQ | NE | x | x */
718 TCG_COND_ALWAYS
, TCG_COND_ALWAYS
,
721 /* Interpret MASK in terms of S->CC_OP, and fill in C with all the
722 details required to generate a TCG comparison. */
723 static void disas_jcc(DisasContext
*s
, DisasCompare
*c
, uint32_t mask
)
726 enum cc_op old_cc_op
= s
->cc_op
;
728 if (mask
== 15 || mask
== 0) {
729 c
->cond
= (mask
? TCG_COND_ALWAYS
: TCG_COND_NEVER
);
732 c
->g1
= c
->g2
= true;
737 /* Find the TCG condition for the mask + cc op. */
743 cond
= ltgt_cond
[mask
];
744 if (cond
== TCG_COND_NEVER
) {
747 account_inline_branch(s
, old_cc_op
);
750 case CC_OP_LTUGTU_32
:
751 case CC_OP_LTUGTU_64
:
752 cond
= tcg_unsigned_cond(ltgt_cond
[mask
]);
753 if (cond
== TCG_COND_NEVER
) {
756 account_inline_branch(s
, old_cc_op
);
760 cond
= nz_cond
[mask
];
761 if (cond
== TCG_COND_NEVER
) {
764 account_inline_branch(s
, old_cc_op
);
779 account_inline_branch(s
, old_cc_op
);
794 account_inline_branch(s
, old_cc_op
);
798 switch (mask
& 0xa) {
799 case 8: /* src == 0 -> no one bit found */
802 case 2: /* src != 0 -> one bit found */
808 account_inline_branch(s
, old_cc_op
);
814 case 8 | 2: /* result == 0 */
817 case 4 | 1: /* result != 0 */
820 case 8 | 4: /* !carry (borrow) */
821 cond
= old_cc_op
== CC_OP_ADDU
? TCG_COND_EQ
: TCG_COND_NE
;
823 case 2 | 1: /* carry (!borrow) */
824 cond
= old_cc_op
== CC_OP_ADDU
? TCG_COND_NE
: TCG_COND_EQ
;
829 account_inline_branch(s
, old_cc_op
);
834 /* Calculate cc value. */
839 /* Jump based on CC. We'll load up the real cond below;
840 the assignment here merely avoids a compiler warning. */
841 account_noninline_branch(s
, old_cc_op
);
842 old_cc_op
= CC_OP_STATIC
;
843 cond
= TCG_COND_NEVER
;
847 /* Load up the arguments of the comparison. */
849 c
->g1
= c
->g2
= false;
853 c
->u
.s32
.a
= tcg_temp_new_i32();
854 tcg_gen_extrl_i64_i32(c
->u
.s32
.a
, cc_dst
);
855 c
->u
.s32
.b
= tcg_const_i32(0);
858 case CC_OP_LTUGTU_32
:
860 c
->u
.s32
.a
= tcg_temp_new_i32();
861 tcg_gen_extrl_i64_i32(c
->u
.s32
.a
, cc_src
);
862 c
->u
.s32
.b
= tcg_temp_new_i32();
863 tcg_gen_extrl_i64_i32(c
->u
.s32
.b
, cc_dst
);
870 c
->u
.s64
.b
= tcg_const_i64(0);
874 case CC_OP_LTUGTU_64
:
877 c
->g1
= c
->g2
= true;
883 c
->u
.s64
.a
= tcg_temp_new_i64();
884 c
->u
.s64
.b
= tcg_const_i64(0);
885 tcg_gen_and_i64(c
->u
.s64
.a
, cc_src
, cc_dst
);
891 c
->u
.s64
.b
= tcg_const_i64(0);
895 case 4 | 1: /* result */
899 case 2 | 1: /* carry */
903 g_assert_not_reached();
912 case 0x8 | 0x4 | 0x2: /* cc != 3 */
914 c
->u
.s32
.b
= tcg_const_i32(3);
916 case 0x8 | 0x4 | 0x1: /* cc != 2 */
918 c
->u
.s32
.b
= tcg_const_i32(2);
920 case 0x8 | 0x2 | 0x1: /* cc != 1 */
922 c
->u
.s32
.b
= tcg_const_i32(1);
924 case 0x8 | 0x2: /* cc == 0 || cc == 2 => (cc & 1) == 0 */
927 c
->u
.s32
.a
= tcg_temp_new_i32();
928 c
->u
.s32
.b
= tcg_const_i32(0);
929 tcg_gen_andi_i32(c
->u
.s32
.a
, cc_op
, 1);
931 case 0x8 | 0x4: /* cc < 2 */
933 c
->u
.s32
.b
= tcg_const_i32(2);
935 case 0x8: /* cc == 0 */
937 c
->u
.s32
.b
= tcg_const_i32(0);
939 case 0x4 | 0x2 | 0x1: /* cc != 0 */
941 c
->u
.s32
.b
= tcg_const_i32(0);
943 case 0x4 | 0x1: /* cc == 1 || cc == 3 => (cc & 1) != 0 */
946 c
->u
.s32
.a
= tcg_temp_new_i32();
947 c
->u
.s32
.b
= tcg_const_i32(0);
948 tcg_gen_andi_i32(c
->u
.s32
.a
, cc_op
, 1);
950 case 0x4: /* cc == 1 */
952 c
->u
.s32
.b
= tcg_const_i32(1);
954 case 0x2 | 0x1: /* cc > 1 */
956 c
->u
.s32
.b
= tcg_const_i32(1);
958 case 0x2: /* cc == 2 */
960 c
->u
.s32
.b
= tcg_const_i32(2);
962 case 0x1: /* cc == 3 */
964 c
->u
.s32
.b
= tcg_const_i32(3);
967 /* CC is masked by something else: (8 >> cc) & mask. */
970 c
->u
.s32
.a
= tcg_const_i32(8);
971 c
->u
.s32
.b
= tcg_const_i32(0);
972 tcg_gen_shr_i32(c
->u
.s32
.a
, c
->u
.s32
.a
, cc_op
);
973 tcg_gen_andi_i32(c
->u
.s32
.a
, c
->u
.s32
.a
, mask
);
984 static void free_compare(DisasCompare
*c
)
988 tcg_temp_free_i64(c
->u
.s64
.a
);
990 tcg_temp_free_i32(c
->u
.s32
.a
);
995 tcg_temp_free_i64(c
->u
.s64
.b
);
997 tcg_temp_free_i32(c
->u
.s32
.b
);
1002 /* ====================================================================== */
1003 /* Define the insn format enumeration. */
1004 #define F0(N) FMT_##N,
1005 #define F1(N, X1) F0(N)
1006 #define F2(N, X1, X2) F0(N)
1007 #define F3(N, X1, X2, X3) F0(N)
1008 #define F4(N, X1, X2, X3, X4) F0(N)
1009 #define F5(N, X1, X2, X3, X4, X5) F0(N)
1010 #define F6(N, X1, X2, X3, X4, X5, X6) F0(N)
1013 #include "insn-format.def"
1024 /* This is the way fields are to be accessed out of DisasFields. */
1025 #define have_field(S, F) have_field1((S), FLD_O_##F)
1026 #define get_field(S, F) get_field1((S), FLD_O_##F, FLD_C_##F)
1028 static bool have_field1(const DisasContext
*s
, enum DisasFieldIndexO c
)
1030 return (s
->fields
.presentO
>> c
) & 1;
1033 static int get_field1(const DisasContext
*s
, enum DisasFieldIndexO o
,
1034 enum DisasFieldIndexC c
)
1036 assert(have_field1(s
, o
));
1037 return s
->fields
.c
[c
];
1040 /* Describe the layout of each field in each format. */
1041 typedef struct DisasField
{
1043 unsigned int size
:8;
1044 unsigned int type
:2;
1045 unsigned int indexC
:6;
1046 enum DisasFieldIndexO indexO
:8;
1049 typedef struct DisasFormatInfo
{
1050 DisasField op
[NUM_C_FIELD
];
1053 #define R(N, B) { B, 4, 0, FLD_C_r##N, FLD_O_r##N }
1054 #define M(N, B) { B, 4, 0, FLD_C_m##N, FLD_O_m##N }
1055 #define V(N, B) { B, 4, 3, FLD_C_v##N, FLD_O_v##N }
1056 #define BD(N, BB, BD) { BB, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1057 { BD, 12, 0, FLD_C_d##N, FLD_O_d##N }
1058 #define BXD(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1059 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1060 { 20, 12, 0, FLD_C_d##N, FLD_O_d##N }
1061 #define BDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1062 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1063 #define BXDL(N) { 16, 4, 0, FLD_C_b##N, FLD_O_b##N }, \
1064 { 12, 4, 0, FLD_C_x##N, FLD_O_x##N }, \
1065 { 20, 20, 2, FLD_C_d##N, FLD_O_d##N }
1066 #define I(N, B, S) { B, S, 1, FLD_C_i##N, FLD_O_i##N }
1067 #define L(N, B, S) { B, S, 0, FLD_C_l##N, FLD_O_l##N }
1069 #define F0(N) { { } },
1070 #define F1(N, X1) { { X1 } },
1071 #define F2(N, X1, X2) { { X1, X2 } },
1072 #define F3(N, X1, X2, X3) { { X1, X2, X3 } },
1073 #define F4(N, X1, X2, X3, X4) { { X1, X2, X3, X4 } },
1074 #define F5(N, X1, X2, X3, X4, X5) { { X1, X2, X3, X4, X5 } },
1075 #define F6(N, X1, X2, X3, X4, X5, X6) { { X1, X2, X3, X4, X5, X6 } },
1077 static const DisasFormatInfo format_info
[] = {
1078 #include "insn-format.def"
1098 /* Generally, we'll extract operands into this structures, operate upon
1099 them, and store them back. See the "in1", "in2", "prep", "wout" sets
1100 of routines below for more details. */
1102 bool g_out
, g_out2
, g_in1
, g_in2
;
1103 TCGv_i64 out
, out2
, in1
, in2
;
1107 /* Instructions can place constraints on their operands, raising specification
1108 exceptions if they are violated. To make this easy to automate, each "in1",
1109 "in2", "prep", "wout" helper will have a SPEC_<name> define that equals one
1110 of the following, or 0. To make this easy to document, we'll put the
1111 SPEC_<name> defines next to <name>. */
1113 #define SPEC_r1_even 1
1114 #define SPEC_r2_even 2
1115 #define SPEC_r3_even 4
1116 #define SPEC_r1_f128 8
1117 #define SPEC_r2_f128 16
1119 /* Return values from translate_one, indicating the state of the TB. */
1121 /* We are not using a goto_tb (for whatever reason), but have updated
1122 the PC (for whatever reason), so there's no need to do it again on
1124 #define DISAS_PC_UPDATED DISAS_TARGET_0
1126 /* We have emitted one or more goto_tb. No fixup required. */
1127 #define DISAS_GOTO_TB DISAS_TARGET_1
1129 /* We have updated the PC and CC values. */
1130 #define DISAS_PC_CC_UPDATED DISAS_TARGET_2
1132 /* We are exiting the TB, but have neither emitted a goto_tb, nor
1133 updated the PC for the next instruction to be executed. */
1134 #define DISAS_PC_STALE DISAS_TARGET_3
1136 /* We are exiting the TB to the main loop. */
1137 #define DISAS_PC_STALE_NOCHAIN DISAS_TARGET_4
1140 /* Instruction flags */
1141 #define IF_AFP1 0x0001 /* r1 is a fp reg for HFP/FPS instructions */
1142 #define IF_AFP2 0x0002 /* r2 is a fp reg for HFP/FPS instructions */
1143 #define IF_AFP3 0x0004 /* r3 is a fp reg for HFP/FPS instructions */
1144 #define IF_BFP 0x0008 /* binary floating point instruction */
1145 #define IF_DFP 0x0010 /* decimal floating point instruction */
1146 #define IF_PRIV 0x0020 /* privileged instruction */
1147 #define IF_VEC 0x0040 /* vector instruction */
1148 #define IF_IO 0x0080 /* input/output instruction */
1159 /* Pre-process arguments before HELP_OP. */
1160 void (*help_in1
)(DisasContext
*, DisasOps
*);
1161 void (*help_in2
)(DisasContext
*, DisasOps
*);
1162 void (*help_prep
)(DisasContext
*, DisasOps
*);
1165 * Post-process output after HELP_OP.
1166 * Note that these are not called if HELP_OP returns DISAS_NORETURN.
1168 void (*help_wout
)(DisasContext
*, DisasOps
*);
1169 void (*help_cout
)(DisasContext
*, DisasOps
*);
1171 /* Implement the operation itself. */
1172 DisasJumpType (*help_op
)(DisasContext
*, DisasOps
*);
1177 /* ====================================================================== */
1178 /* Miscellaneous helpers, used by several operations. */
1180 static DisasJumpType
help_goto_direct(DisasContext
*s
, uint64_t dest
)
1182 if (dest
== s
->pc_tmp
) {
1183 per_branch(s
, true);
1186 if (use_goto_tb(s
, dest
)) {
1188 per_breaking_event(s
);
1190 tcg_gen_movi_i64(psw_addr
, dest
);
1191 tcg_gen_exit_tb(s
->base
.tb
, 0);
1192 return DISAS_GOTO_TB
;
1194 tcg_gen_movi_i64(psw_addr
, dest
);
1195 per_branch(s
, false);
1196 return DISAS_PC_UPDATED
;
1200 static DisasJumpType
help_branch(DisasContext
*s
, DisasCompare
*c
,
1201 bool is_imm
, int imm
, TCGv_i64 cdest
)
1204 uint64_t dest
= s
->base
.pc_next
+ 2 * imm
;
1207 /* Take care of the special cases first. */
1208 if (c
->cond
== TCG_COND_NEVER
) {
1213 if (dest
== s
->pc_tmp
) {
1214 /* Branch to next. */
1215 per_branch(s
, true);
1219 if (c
->cond
== TCG_COND_ALWAYS
) {
1220 ret
= help_goto_direct(s
, dest
);
1225 /* E.g. bcr %r0 -> no branch. */
1229 if (c
->cond
== TCG_COND_ALWAYS
) {
1230 tcg_gen_mov_i64(psw_addr
, cdest
);
1231 per_branch(s
, false);
1232 ret
= DISAS_PC_UPDATED
;
1237 if (use_goto_tb(s
, s
->pc_tmp
)) {
1238 if (is_imm
&& use_goto_tb(s
, dest
)) {
1239 /* Both exits can use goto_tb. */
1242 lab
= gen_new_label();
1244 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1246 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1249 /* Branch not taken. */
1251 tcg_gen_movi_i64(psw_addr
, s
->pc_tmp
);
1252 tcg_gen_exit_tb(s
->base
.tb
, 0);
1256 per_breaking_event(s
);
1258 tcg_gen_movi_i64(psw_addr
, dest
);
1259 tcg_gen_exit_tb(s
->base
.tb
, 1);
1261 ret
= DISAS_GOTO_TB
;
1263 /* Fallthru can use goto_tb, but taken branch cannot. */
1264 /* Store taken branch destination before the brcond. This
1265 avoids having to allocate a new local temp to hold it.
1266 We'll overwrite this in the not taken case anyway. */
1268 tcg_gen_mov_i64(psw_addr
, cdest
);
1271 lab
= gen_new_label();
1273 tcg_gen_brcond_i64(c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
, lab
);
1275 tcg_gen_brcond_i32(c
->cond
, c
->u
.s32
.a
, c
->u
.s32
.b
, lab
);
1278 /* Branch not taken. */
1281 tcg_gen_movi_i64(psw_addr
, s
->pc_tmp
);
1282 tcg_gen_exit_tb(s
->base
.tb
, 0);
1286 tcg_gen_movi_i64(psw_addr
, dest
);
1288 per_breaking_event(s
);
1289 ret
= DISAS_PC_UPDATED
;
1292 /* Fallthru cannot use goto_tb. This by itself is vanishingly rare.
1293 Most commonly we're single-stepping or some other condition that
1294 disables all use of goto_tb. Just update the PC and exit. */
1296 TCGv_i64 next
= tcg_const_i64(s
->pc_tmp
);
1298 cdest
= tcg_const_i64(dest
);
1302 tcg_gen_movcond_i64(c
->cond
, psw_addr
, c
->u
.s64
.a
, c
->u
.s64
.b
,
1304 per_branch_cond(s
, c
->cond
, c
->u
.s64
.a
, c
->u
.s64
.b
);
1306 TCGv_i32 t0
= tcg_temp_new_i32();
1307 TCGv_i64 t1
= tcg_temp_new_i64();
1308 TCGv_i64 z
= tcg_const_i64(0);
1309 tcg_gen_setcond_i32(c
->cond
, t0
, c
->u
.s32
.a
, c
->u
.s32
.b
);
1310 tcg_gen_extu_i32_i64(t1
, t0
);
1311 tcg_temp_free_i32(t0
);
1312 tcg_gen_movcond_i64(TCG_COND_NE
, psw_addr
, t1
, z
, cdest
, next
);
1313 per_branch_cond(s
, TCG_COND_NE
, t1
, z
);
1314 tcg_temp_free_i64(t1
);
1315 tcg_temp_free_i64(z
);
1319 tcg_temp_free_i64(cdest
);
1321 tcg_temp_free_i64(next
);
1323 ret
= DISAS_PC_UPDATED
;
1331 /* ====================================================================== */
1332 /* The operations. These perform the bulk of the work for any insn,
1333 usually after the operands have been loaded and output initialized. */
1335 static DisasJumpType
op_abs(DisasContext
*s
, DisasOps
*o
)
1337 tcg_gen_abs_i64(o
->out
, o
->in2
);
1341 static DisasJumpType
op_absf32(DisasContext
*s
, DisasOps
*o
)
1343 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffull
);
1347 static DisasJumpType
op_absf64(DisasContext
*s
, DisasOps
*o
)
1349 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffffffffffull
);
1353 static DisasJumpType
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 DisasJumpType
op_add(DisasContext
*s
, DisasOps
*o
)
1362 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1366 static DisasJumpType
op_addu64(DisasContext
*s
, DisasOps
*o
)
1368 tcg_gen_movi_i64(cc_src
, 0);
1369 tcg_gen_add2_i64(o
->out
, cc_src
, o
->in1
, cc_src
, o
->in2
, cc_src
);
1373 /* Compute carry into cc_src. */
1374 static void compute_carry(DisasContext
*s
)
1378 /* The carry value is already in cc_src (1,0). */
1381 tcg_gen_addi_i64(cc_src
, cc_src
, 1);
1387 /* The carry flag is the msb of CC; compute into cc_src. */
1388 tcg_gen_extu_i32_i64(cc_src
, cc_op
);
1389 tcg_gen_shri_i64(cc_src
, cc_src
, 1);
1394 static DisasJumpType
op_addc32(DisasContext
*s
, DisasOps
*o
)
1397 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1398 tcg_gen_add_i64(o
->out
, o
->out
, cc_src
);
1402 static DisasJumpType
op_addc64(DisasContext
*s
, DisasOps
*o
)
1406 TCGv_i64 zero
= tcg_const_i64(0);
1407 tcg_gen_add2_i64(o
->out
, cc_src
, o
->in1
, zero
, cc_src
, zero
);
1408 tcg_gen_add2_i64(o
->out
, cc_src
, o
->out
, cc_src
, o
->in2
, zero
);
1409 tcg_temp_free_i64(zero
);
1414 static DisasJumpType
op_asi(DisasContext
*s
, DisasOps
*o
)
1416 bool non_atomic
= !s390_has_feat(S390_FEAT_STFLE_45
);
1418 o
->in1
= tcg_temp_new_i64();
1420 tcg_gen_qemu_ld_tl(o
->in1
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1422 /* Perform the atomic addition in memory. */
1423 tcg_gen_atomic_fetch_add_i64(o
->in1
, o
->addr1
, o
->in2
, get_mem_index(s
),
1427 /* Recompute also for atomic case: needed for setting CC. */
1428 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
1431 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1436 static DisasJumpType
op_asiu64(DisasContext
*s
, DisasOps
*o
)
1438 bool non_atomic
= !s390_has_feat(S390_FEAT_STFLE_45
);
1440 o
->in1
= tcg_temp_new_i64();
1442 tcg_gen_qemu_ld_tl(o
->in1
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1444 /* Perform the atomic addition in memory. */
1445 tcg_gen_atomic_fetch_add_i64(o
->in1
, o
->addr1
, o
->in2
, get_mem_index(s
),
1449 /* Recompute also for atomic case: needed for setting CC. */
1450 tcg_gen_movi_i64(cc_src
, 0);
1451 tcg_gen_add2_i64(o
->out
, cc_src
, o
->in1
, cc_src
, o
->in2
, cc_src
);
1454 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1459 static DisasJumpType
op_aeb(DisasContext
*s
, DisasOps
*o
)
1461 gen_helper_aeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
1465 static DisasJumpType
op_adb(DisasContext
*s
, DisasOps
*o
)
1467 gen_helper_adb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
1471 static DisasJumpType
op_axb(DisasContext
*s
, DisasOps
*o
)
1473 gen_helper_axb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
1474 return_low128(o
->out2
);
1478 static DisasJumpType
op_and(DisasContext
*s
, DisasOps
*o
)
1480 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
1484 static DisasJumpType
op_andi(DisasContext
*s
, DisasOps
*o
)
1486 int shift
= s
->insn
->data
& 0xff;
1487 int size
= s
->insn
->data
>> 8;
1488 uint64_t mask
= ((1ull << size
) - 1) << shift
;
1491 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
1492 tcg_gen_ori_i64(o
->in2
, o
->in2
, ~mask
);
1493 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
1495 /* Produce the CC from only the bits manipulated. */
1496 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
1497 set_cc_nz_u64(s
, cc_dst
);
1501 static DisasJumpType
op_andc(DisasContext
*s
, DisasOps
*o
)
1503 tcg_gen_andc_i64(o
->out
, o
->in1
, o
->in2
);
1507 static DisasJumpType
op_orc(DisasContext
*s
, DisasOps
*o
)
1509 tcg_gen_orc_i64(o
->out
, o
->in1
, o
->in2
);
1513 static DisasJumpType
op_nand(DisasContext
*s
, DisasOps
*o
)
1515 tcg_gen_nand_i64(o
->out
, o
->in1
, o
->in2
);
1519 static DisasJumpType
op_nor(DisasContext
*s
, DisasOps
*o
)
1521 tcg_gen_nor_i64(o
->out
, o
->in1
, o
->in2
);
1525 static DisasJumpType
op_nxor(DisasContext
*s
, DisasOps
*o
)
1527 tcg_gen_eqv_i64(o
->out
, o
->in1
, o
->in2
);
1531 static DisasJumpType
op_ni(DisasContext
*s
, DisasOps
*o
)
1533 o
->in1
= tcg_temp_new_i64();
1535 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
1536 tcg_gen_qemu_ld_tl(o
->in1
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1538 /* Perform the atomic operation in memory. */
1539 tcg_gen_atomic_fetch_and_i64(o
->in1
, o
->addr1
, o
->in2
, get_mem_index(s
),
1543 /* Recompute also for atomic case: needed for setting CC. */
1544 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
1546 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
1547 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
1552 static DisasJumpType
op_bas(DisasContext
*s
, DisasOps
*o
)
1554 pc_to_link_info(o
->out
, s
, s
->pc_tmp
);
1556 tcg_gen_mov_i64(psw_addr
, o
->in2
);
1557 per_branch(s
, false);
1558 return DISAS_PC_UPDATED
;
1564 static void save_link_info(DisasContext
*s
, DisasOps
*o
)
1568 if (s
->base
.tb
->flags
& (FLAG_MASK_32
| FLAG_MASK_64
)) {
1569 pc_to_link_info(o
->out
, s
, s
->pc_tmp
);
1573 tcg_gen_andi_i64(o
->out
, o
->out
, 0xffffffff00000000ull
);
1574 tcg_gen_ori_i64(o
->out
, o
->out
, ((s
->ilen
/ 2) << 30) | s
->pc_tmp
);
1575 t
= tcg_temp_new_i64();
1576 tcg_gen_shri_i64(t
, psw_mask
, 16);
1577 tcg_gen_andi_i64(t
, t
, 0x0f000000);
1578 tcg_gen_or_i64(o
->out
, o
->out
, t
);
1579 tcg_gen_extu_i32_i64(t
, cc_op
);
1580 tcg_gen_shli_i64(t
, t
, 28);
1581 tcg_gen_or_i64(o
->out
, o
->out
, t
);
1582 tcg_temp_free_i64(t
);
1585 static DisasJumpType
op_bal(DisasContext
*s
, DisasOps
*o
)
1587 save_link_info(s
, o
);
1589 tcg_gen_mov_i64(psw_addr
, o
->in2
);
1590 per_branch(s
, false);
1591 return DISAS_PC_UPDATED
;
1597 static DisasJumpType
op_basi(DisasContext
*s
, DisasOps
*o
)
1599 pc_to_link_info(o
->out
, s
, s
->pc_tmp
);
1600 return help_goto_direct(s
, s
->base
.pc_next
+ 2 * get_field(s
, i2
));
1603 static DisasJumpType
op_bc(DisasContext
*s
, DisasOps
*o
)
1605 int m1
= get_field(s
, m1
);
1606 bool is_imm
= have_field(s
, i2
);
1607 int imm
= is_imm
? get_field(s
, i2
) : 0;
1610 /* BCR with R2 = 0 causes no branching */
1611 if (have_field(s
, r2
) && get_field(s
, r2
) == 0) {
1613 /* Perform serialization */
1614 /* FIXME: check for fast-BCR-serialization facility */
1615 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
1618 /* Perform serialization */
1619 /* FIXME: perform checkpoint-synchronisation */
1620 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
1625 disas_jcc(s
, &c
, m1
);
1626 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1629 static DisasJumpType
op_bct32(DisasContext
*s
, DisasOps
*o
)
1631 int r1
= get_field(s
, r1
);
1632 bool is_imm
= have_field(s
, i2
);
1633 int imm
= is_imm
? get_field(s
, i2
) : 0;
1637 c
.cond
= TCG_COND_NE
;
1642 t
= tcg_temp_new_i64();
1643 tcg_gen_subi_i64(t
, regs
[r1
], 1);
1644 store_reg32_i64(r1
, t
);
1645 c
.u
.s32
.a
= tcg_temp_new_i32();
1646 c
.u
.s32
.b
= tcg_const_i32(0);
1647 tcg_gen_extrl_i64_i32(c
.u
.s32
.a
, t
);
1648 tcg_temp_free_i64(t
);
1650 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1653 static DisasJumpType
op_bcth(DisasContext
*s
, DisasOps
*o
)
1655 int r1
= get_field(s
, r1
);
1656 int imm
= get_field(s
, i2
);
1660 c
.cond
= TCG_COND_NE
;
1665 t
= tcg_temp_new_i64();
1666 tcg_gen_shri_i64(t
, regs
[r1
], 32);
1667 tcg_gen_subi_i64(t
, t
, 1);
1668 store_reg32h_i64(r1
, t
);
1669 c
.u
.s32
.a
= tcg_temp_new_i32();
1670 c
.u
.s32
.b
= tcg_const_i32(0);
1671 tcg_gen_extrl_i64_i32(c
.u
.s32
.a
, t
);
1672 tcg_temp_free_i64(t
);
1674 return help_branch(s
, &c
, 1, imm
, o
->in2
);
1677 static DisasJumpType
op_bct64(DisasContext
*s
, DisasOps
*o
)
1679 int r1
= get_field(s
, r1
);
1680 bool is_imm
= have_field(s
, i2
);
1681 int imm
= is_imm
? get_field(s
, i2
) : 0;
1684 c
.cond
= TCG_COND_NE
;
1689 tcg_gen_subi_i64(regs
[r1
], regs
[r1
], 1);
1690 c
.u
.s64
.a
= regs
[r1
];
1691 c
.u
.s64
.b
= tcg_const_i64(0);
1693 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1696 static DisasJumpType
op_bx32(DisasContext
*s
, DisasOps
*o
)
1698 int r1
= get_field(s
, r1
);
1699 int r3
= get_field(s
, r3
);
1700 bool is_imm
= have_field(s
, i2
);
1701 int imm
= is_imm
? get_field(s
, i2
) : 0;
1705 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
1710 t
= tcg_temp_new_i64();
1711 tcg_gen_add_i64(t
, regs
[r1
], regs
[r3
]);
1712 c
.u
.s32
.a
= tcg_temp_new_i32();
1713 c
.u
.s32
.b
= tcg_temp_new_i32();
1714 tcg_gen_extrl_i64_i32(c
.u
.s32
.a
, t
);
1715 tcg_gen_extrl_i64_i32(c
.u
.s32
.b
, regs
[r3
| 1]);
1716 store_reg32_i64(r1
, t
);
1717 tcg_temp_free_i64(t
);
1719 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1722 static DisasJumpType
op_bx64(DisasContext
*s
, DisasOps
*o
)
1724 int r1
= get_field(s
, r1
);
1725 int r3
= get_field(s
, r3
);
1726 bool is_imm
= have_field(s
, i2
);
1727 int imm
= is_imm
? get_field(s
, i2
) : 0;
1730 c
.cond
= (s
->insn
->data
? TCG_COND_LE
: TCG_COND_GT
);
1733 if (r1
== (r3
| 1)) {
1734 c
.u
.s64
.b
= load_reg(r3
| 1);
1737 c
.u
.s64
.b
= regs
[r3
| 1];
1741 tcg_gen_add_i64(regs
[r1
], regs
[r1
], regs
[r3
]);
1742 c
.u
.s64
.a
= regs
[r1
];
1745 return help_branch(s
, &c
, is_imm
, imm
, o
->in2
);
1748 static DisasJumpType
op_cj(DisasContext
*s
, DisasOps
*o
)
1750 int imm
, m3
= get_field(s
, m3
);
1754 c
.cond
= ltgt_cond
[m3
];
1755 if (s
->insn
->data
) {
1756 c
.cond
= tcg_unsigned_cond(c
.cond
);
1758 c
.is_64
= c
.g1
= c
.g2
= true;
1762 is_imm
= have_field(s
, i4
);
1764 imm
= get_field(s
, i4
);
1767 o
->out
= get_address(s
, 0, get_field(s
, b4
),
1771 return help_branch(s
, &c
, is_imm
, imm
, o
->out
);
1774 static DisasJumpType
op_ceb(DisasContext
*s
, DisasOps
*o
)
1776 gen_helper_ceb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
1781 static DisasJumpType
op_cdb(DisasContext
*s
, DisasOps
*o
)
1783 gen_helper_cdb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
1788 static DisasJumpType
op_cxb(DisasContext
*s
, DisasOps
*o
)
1790 gen_helper_cxb(cc_op
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
1795 static TCGv_i32
fpinst_extract_m34(DisasContext
*s
, bool m3_with_fpe
,
1798 const bool fpe
= s390_has_feat(S390_FEAT_FLOATING_POINT_EXT
);
1799 uint8_t m3
= get_field(s
, m3
);
1800 uint8_t m4
= get_field(s
, m4
);
1802 /* m3 field was introduced with FPE */
1803 if (!fpe
&& m3_with_fpe
) {
1806 /* m4 field was introduced with FPE */
1807 if (!fpe
&& m4_with_fpe
) {
1811 /* Check for valid rounding modes. Mode 3 was introduced later. */
1812 if (m3
== 2 || m3
> 7 || (!fpe
&& m3
== 3)) {
1813 gen_program_exception(s
, PGM_SPECIFICATION
);
1817 return tcg_const_i32(deposit32(m3
, 4, 4, m4
));
1820 static DisasJumpType
op_cfeb(DisasContext
*s
, DisasOps
*o
)
1822 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1825 return DISAS_NORETURN
;
1827 gen_helper_cfeb(o
->out
, cpu_env
, o
->in2
, m34
);
1828 tcg_temp_free_i32(m34
);
1833 static DisasJumpType
op_cfdb(DisasContext
*s
, DisasOps
*o
)
1835 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1838 return DISAS_NORETURN
;
1840 gen_helper_cfdb(o
->out
, cpu_env
, o
->in2
, m34
);
1841 tcg_temp_free_i32(m34
);
1846 static DisasJumpType
op_cfxb(DisasContext
*s
, DisasOps
*o
)
1848 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1851 return DISAS_NORETURN
;
1853 gen_helper_cfxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
1854 tcg_temp_free_i32(m34
);
1859 static DisasJumpType
op_cgeb(DisasContext
*s
, DisasOps
*o
)
1861 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1864 return DISAS_NORETURN
;
1866 gen_helper_cgeb(o
->out
, cpu_env
, o
->in2
, m34
);
1867 tcg_temp_free_i32(m34
);
1872 static DisasJumpType
op_cgdb(DisasContext
*s
, DisasOps
*o
)
1874 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1877 return DISAS_NORETURN
;
1879 gen_helper_cgdb(o
->out
, cpu_env
, o
->in2
, m34
);
1880 tcg_temp_free_i32(m34
);
1885 static DisasJumpType
op_cgxb(DisasContext
*s
, DisasOps
*o
)
1887 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
1890 return DISAS_NORETURN
;
1892 gen_helper_cgxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
1893 tcg_temp_free_i32(m34
);
1898 static DisasJumpType
op_clfeb(DisasContext
*s
, DisasOps
*o
)
1900 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1903 return DISAS_NORETURN
;
1905 gen_helper_clfeb(o
->out
, cpu_env
, o
->in2
, m34
);
1906 tcg_temp_free_i32(m34
);
1911 static DisasJumpType
op_clfdb(DisasContext
*s
, DisasOps
*o
)
1913 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1916 return DISAS_NORETURN
;
1918 gen_helper_clfdb(o
->out
, cpu_env
, o
->in2
, m34
);
1919 tcg_temp_free_i32(m34
);
1924 static DisasJumpType
op_clfxb(DisasContext
*s
, DisasOps
*o
)
1926 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1929 return DISAS_NORETURN
;
1931 gen_helper_clfxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
1932 tcg_temp_free_i32(m34
);
1937 static DisasJumpType
op_clgeb(DisasContext
*s
, DisasOps
*o
)
1939 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1942 return DISAS_NORETURN
;
1944 gen_helper_clgeb(o
->out
, cpu_env
, o
->in2
, m34
);
1945 tcg_temp_free_i32(m34
);
1950 static DisasJumpType
op_clgdb(DisasContext
*s
, DisasOps
*o
)
1952 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1955 return DISAS_NORETURN
;
1957 gen_helper_clgdb(o
->out
, cpu_env
, o
->in2
, m34
);
1958 tcg_temp_free_i32(m34
);
1963 static DisasJumpType
op_clgxb(DisasContext
*s
, DisasOps
*o
)
1965 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
1968 return DISAS_NORETURN
;
1970 gen_helper_clgxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
1971 tcg_temp_free_i32(m34
);
1976 static DisasJumpType
op_cegb(DisasContext
*s
, DisasOps
*o
)
1978 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
1981 return DISAS_NORETURN
;
1983 gen_helper_cegb(o
->out
, cpu_env
, o
->in2
, m34
);
1984 tcg_temp_free_i32(m34
);
1988 static DisasJumpType
op_cdgb(DisasContext
*s
, DisasOps
*o
)
1990 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
1993 return DISAS_NORETURN
;
1995 gen_helper_cdgb(o
->out
, cpu_env
, o
->in2
, m34
);
1996 tcg_temp_free_i32(m34
);
2000 static DisasJumpType
op_cxgb(DisasContext
*s
, DisasOps
*o
)
2002 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
2005 return DISAS_NORETURN
;
2007 gen_helper_cxgb(o
->out
, cpu_env
, o
->in2
, m34
);
2008 tcg_temp_free_i32(m34
);
2009 return_low128(o
->out2
);
2013 static DisasJumpType
op_celgb(DisasContext
*s
, DisasOps
*o
)
2015 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
2018 return DISAS_NORETURN
;
2020 gen_helper_celgb(o
->out
, cpu_env
, o
->in2
, m34
);
2021 tcg_temp_free_i32(m34
);
2025 static DisasJumpType
op_cdlgb(DisasContext
*s
, DisasOps
*o
)
2027 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
2030 return DISAS_NORETURN
;
2032 gen_helper_cdlgb(o
->out
, cpu_env
, o
->in2
, m34
);
2033 tcg_temp_free_i32(m34
);
2037 static DisasJumpType
op_cxlgb(DisasContext
*s
, DisasOps
*o
)
2039 TCGv_i32 m34
= fpinst_extract_m34(s
, false, false);
2042 return DISAS_NORETURN
;
2044 gen_helper_cxlgb(o
->out
, cpu_env
, o
->in2
, m34
);
2045 tcg_temp_free_i32(m34
);
2046 return_low128(o
->out2
);
2050 static DisasJumpType
op_cksm(DisasContext
*s
, DisasOps
*o
)
2052 int r2
= get_field(s
, r2
);
2053 TCGv_i64 len
= tcg_temp_new_i64();
2055 gen_helper_cksm(len
, cpu_env
, o
->in1
, o
->in2
, regs
[r2
+ 1]);
2057 return_low128(o
->out
);
2059 tcg_gen_add_i64(regs
[r2
], regs
[r2
], len
);
2060 tcg_gen_sub_i64(regs
[r2
+ 1], regs
[r2
+ 1], len
);
2061 tcg_temp_free_i64(len
);
2066 static DisasJumpType
op_clc(DisasContext
*s
, DisasOps
*o
)
2068 int l
= get_field(s
, l1
);
2073 tcg_gen_qemu_ld8u(cc_src
, o
->addr1
, get_mem_index(s
));
2074 tcg_gen_qemu_ld8u(cc_dst
, o
->in2
, get_mem_index(s
));
2077 tcg_gen_qemu_ld16u(cc_src
, o
->addr1
, get_mem_index(s
));
2078 tcg_gen_qemu_ld16u(cc_dst
, o
->in2
, get_mem_index(s
));
2081 tcg_gen_qemu_ld32u(cc_src
, o
->addr1
, get_mem_index(s
));
2082 tcg_gen_qemu_ld32u(cc_dst
, o
->in2
, get_mem_index(s
));
2085 tcg_gen_qemu_ld64(cc_src
, o
->addr1
, get_mem_index(s
));
2086 tcg_gen_qemu_ld64(cc_dst
, o
->in2
, get_mem_index(s
));
2089 vl
= tcg_const_i32(l
);
2090 gen_helper_clc(cc_op
, cpu_env
, vl
, o
->addr1
, o
->in2
);
2091 tcg_temp_free_i32(vl
);
2095 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_64
, cc_src
, cc_dst
);
2099 static DisasJumpType
op_clcl(DisasContext
*s
, DisasOps
*o
)
2101 int r1
= get_field(s
, r1
);
2102 int r2
= get_field(s
, r2
);
2105 /* r1 and r2 must be even. */
2106 if (r1
& 1 || r2
& 1) {
2107 gen_program_exception(s
, PGM_SPECIFICATION
);
2108 return DISAS_NORETURN
;
2111 t1
= tcg_const_i32(r1
);
2112 t2
= tcg_const_i32(r2
);
2113 gen_helper_clcl(cc_op
, cpu_env
, t1
, t2
);
2114 tcg_temp_free_i32(t1
);
2115 tcg_temp_free_i32(t2
);
2120 static DisasJumpType
op_clcle(DisasContext
*s
, DisasOps
*o
)
2122 int r1
= get_field(s
, r1
);
2123 int r3
= get_field(s
, r3
);
2126 /* r1 and r3 must be even. */
2127 if (r1
& 1 || r3
& 1) {
2128 gen_program_exception(s
, PGM_SPECIFICATION
);
2129 return DISAS_NORETURN
;
2132 t1
= tcg_const_i32(r1
);
2133 t3
= tcg_const_i32(r3
);
2134 gen_helper_clcle(cc_op
, cpu_env
, t1
, o
->in2
, t3
);
2135 tcg_temp_free_i32(t1
);
2136 tcg_temp_free_i32(t3
);
2141 static DisasJumpType
op_clclu(DisasContext
*s
, DisasOps
*o
)
2143 int r1
= get_field(s
, r1
);
2144 int r3
= get_field(s
, r3
);
2147 /* r1 and r3 must be even. */
2148 if (r1
& 1 || r3
& 1) {
2149 gen_program_exception(s
, PGM_SPECIFICATION
);
2150 return DISAS_NORETURN
;
2153 t1
= tcg_const_i32(r1
);
2154 t3
= tcg_const_i32(r3
);
2155 gen_helper_clclu(cc_op
, cpu_env
, t1
, o
->in2
, t3
);
2156 tcg_temp_free_i32(t1
);
2157 tcg_temp_free_i32(t3
);
2162 static DisasJumpType
op_clm(DisasContext
*s
, DisasOps
*o
)
2164 TCGv_i32 m3
= tcg_const_i32(get_field(s
, m3
));
2165 TCGv_i32 t1
= tcg_temp_new_i32();
2166 tcg_gen_extrl_i64_i32(t1
, o
->in1
);
2167 gen_helper_clm(cc_op
, cpu_env
, t1
, m3
, o
->in2
);
2169 tcg_temp_free_i32(t1
);
2170 tcg_temp_free_i32(m3
);
2174 static DisasJumpType
op_clst(DisasContext
*s
, DisasOps
*o
)
2176 gen_helper_clst(o
->in1
, cpu_env
, regs
[0], o
->in1
, o
->in2
);
2178 return_low128(o
->in2
);
2182 static DisasJumpType
op_cps(DisasContext
*s
, DisasOps
*o
)
2184 TCGv_i64 t
= tcg_temp_new_i64();
2185 tcg_gen_andi_i64(t
, o
->in1
, 0x8000000000000000ull
);
2186 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffffffffffffull
);
2187 tcg_gen_or_i64(o
->out
, o
->out
, t
);
2188 tcg_temp_free_i64(t
);
2192 static DisasJumpType
op_cs(DisasContext
*s
, DisasOps
*o
)
2194 int d2
= get_field(s
, d2
);
2195 int b2
= get_field(s
, b2
);
2198 /* Note that in1 = R3 (new value) and
2199 in2 = (zero-extended) R1 (expected value). */
2201 addr
= get_address(s
, 0, b2
, d2
);
2202 tcg_gen_atomic_cmpxchg_i64(o
->out
, addr
, o
->in2
, o
->in1
,
2203 get_mem_index(s
), s
->insn
->data
| MO_ALIGN
);
2204 tcg_temp_free_i64(addr
);
2206 /* Are the memory and expected values (un)equal? Note that this setcond
2207 produces the output CC value, thus the NE sense of the test. */
2208 cc
= tcg_temp_new_i64();
2209 tcg_gen_setcond_i64(TCG_COND_NE
, cc
, o
->in2
, o
->out
);
2210 tcg_gen_extrl_i64_i32(cc_op
, cc
);
2211 tcg_temp_free_i64(cc
);
2217 static DisasJumpType
op_cdsg(DisasContext
*s
, DisasOps
*o
)
2219 int r1
= get_field(s
, r1
);
2220 int r3
= get_field(s
, r3
);
2221 int d2
= get_field(s
, d2
);
2222 int b2
= get_field(s
, b2
);
2223 DisasJumpType ret
= DISAS_NEXT
;
2225 TCGv_i32 t_r1
, t_r3
;
2227 /* Note that R1:R1+1 = expected value and R3:R3+1 = new value. */
2228 addr
= get_address(s
, 0, b2
, d2
);
2229 t_r1
= tcg_const_i32(r1
);
2230 t_r3
= tcg_const_i32(r3
);
2231 if (!(tb_cflags(s
->base
.tb
) & CF_PARALLEL
)) {
2232 gen_helper_cdsg(cpu_env
, addr
, t_r1
, t_r3
);
2233 } else if (HAVE_CMPXCHG128
) {
2234 gen_helper_cdsg_parallel(cpu_env
, addr
, t_r1
, t_r3
);
2236 gen_helper_exit_atomic(cpu_env
);
2237 ret
= DISAS_NORETURN
;
2239 tcg_temp_free_i64(addr
);
2240 tcg_temp_free_i32(t_r1
);
2241 tcg_temp_free_i32(t_r3
);
2247 static DisasJumpType
op_csst(DisasContext
*s
, DisasOps
*o
)
2249 int r3
= get_field(s
, r3
);
2250 TCGv_i32 t_r3
= tcg_const_i32(r3
);
2252 if (tb_cflags(s
->base
.tb
) & CF_PARALLEL
) {
2253 gen_helper_csst_parallel(cc_op
, cpu_env
, t_r3
, o
->addr1
, o
->in2
);
2255 gen_helper_csst(cc_op
, cpu_env
, t_r3
, o
->addr1
, o
->in2
);
2257 tcg_temp_free_i32(t_r3
);
2263 #ifndef CONFIG_USER_ONLY
2264 static DisasJumpType
op_csp(DisasContext
*s
, DisasOps
*o
)
2266 MemOp mop
= s
->insn
->data
;
2267 TCGv_i64 addr
, old
, cc
;
2268 TCGLabel
*lab
= gen_new_label();
2270 /* Note that in1 = R1 (zero-extended expected value),
2271 out = R1 (original reg), out2 = R1+1 (new value). */
2273 addr
= tcg_temp_new_i64();
2274 old
= tcg_temp_new_i64();
2275 tcg_gen_andi_i64(addr
, o
->in2
, -1ULL << (mop
& MO_SIZE
));
2276 tcg_gen_atomic_cmpxchg_i64(old
, addr
, o
->in1
, o
->out2
,
2277 get_mem_index(s
), mop
| MO_ALIGN
);
2278 tcg_temp_free_i64(addr
);
2280 /* Are the memory and expected values (un)equal? */
2281 cc
= tcg_temp_new_i64();
2282 tcg_gen_setcond_i64(TCG_COND_NE
, cc
, o
->in1
, old
);
2283 tcg_gen_extrl_i64_i32(cc_op
, cc
);
2285 /* Write back the output now, so that it happens before the
2286 following branch, so that we don't need local temps. */
2287 if ((mop
& MO_SIZE
) == MO_32
) {
2288 tcg_gen_deposit_i64(o
->out
, o
->out
, old
, 0, 32);
2290 tcg_gen_mov_i64(o
->out
, old
);
2292 tcg_temp_free_i64(old
);
2294 /* If the comparison was equal, and the LSB of R2 was set,
2295 then we need to flush the TLB (for all cpus). */
2296 tcg_gen_xori_i64(cc
, cc
, 1);
2297 tcg_gen_and_i64(cc
, cc
, o
->in2
);
2298 tcg_gen_brcondi_i64(TCG_COND_EQ
, cc
, 0, lab
);
2299 tcg_temp_free_i64(cc
);
2301 gen_helper_purge(cpu_env
);
2308 static DisasJumpType
op_cvd(DisasContext
*s
, DisasOps
*o
)
2310 TCGv_i64 t1
= tcg_temp_new_i64();
2311 TCGv_i32 t2
= tcg_temp_new_i32();
2312 tcg_gen_extrl_i64_i32(t2
, o
->in1
);
2313 gen_helper_cvd(t1
, t2
);
2314 tcg_temp_free_i32(t2
);
2315 tcg_gen_qemu_st64(t1
, o
->in2
, get_mem_index(s
));
2316 tcg_temp_free_i64(t1
);
2320 static DisasJumpType
op_ct(DisasContext
*s
, DisasOps
*o
)
2322 int m3
= get_field(s
, m3
);
2323 TCGLabel
*lab
= gen_new_label();
2326 c
= tcg_invert_cond(ltgt_cond
[m3
]);
2327 if (s
->insn
->data
) {
2328 c
= tcg_unsigned_cond(c
);
2330 tcg_gen_brcond_i64(c
, o
->in1
, o
->in2
, lab
);
2339 static DisasJumpType
op_cuXX(DisasContext
*s
, DisasOps
*o
)
2341 int m3
= get_field(s
, m3
);
2342 int r1
= get_field(s
, r1
);
2343 int r2
= get_field(s
, r2
);
2344 TCGv_i32 tr1
, tr2
, chk
;
2346 /* R1 and R2 must both be even. */
2347 if ((r1
| r2
) & 1) {
2348 gen_program_exception(s
, PGM_SPECIFICATION
);
2349 return DISAS_NORETURN
;
2351 if (!s390_has_feat(S390_FEAT_ETF3_ENH
)) {
2355 tr1
= tcg_const_i32(r1
);
2356 tr2
= tcg_const_i32(r2
);
2357 chk
= tcg_const_i32(m3
);
2359 switch (s
->insn
->data
) {
2361 gen_helper_cu12(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2364 gen_helper_cu14(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2367 gen_helper_cu21(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2370 gen_helper_cu24(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2373 gen_helper_cu41(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2376 gen_helper_cu42(cc_op
, cpu_env
, tr1
, tr2
, chk
);
2379 g_assert_not_reached();
2382 tcg_temp_free_i32(tr1
);
2383 tcg_temp_free_i32(tr2
);
2384 tcg_temp_free_i32(chk
);
2389 #ifndef CONFIG_USER_ONLY
2390 static DisasJumpType
op_diag(DisasContext
*s
, DisasOps
*o
)
2392 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
2393 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
2394 TCGv_i32 func_code
= tcg_const_i32(get_field(s
, i2
));
2396 gen_helper_diag(cpu_env
, r1
, r3
, func_code
);
2398 tcg_temp_free_i32(func_code
);
2399 tcg_temp_free_i32(r3
);
2400 tcg_temp_free_i32(r1
);
2405 static DisasJumpType
op_divs32(DisasContext
*s
, DisasOps
*o
)
2407 gen_helper_divs32(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2408 return_low128(o
->out
);
2412 static DisasJumpType
op_divu32(DisasContext
*s
, DisasOps
*o
)
2414 gen_helper_divu32(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2415 return_low128(o
->out
);
2419 static DisasJumpType
op_divs64(DisasContext
*s
, DisasOps
*o
)
2421 gen_helper_divs64(o
->out2
, cpu_env
, o
->in1
, o
->in2
);
2422 return_low128(o
->out
);
2426 static DisasJumpType
op_divu64(DisasContext
*s
, DisasOps
*o
)
2428 gen_helper_divu64(o
->out2
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
2429 return_low128(o
->out
);
2433 static DisasJumpType
op_deb(DisasContext
*s
, DisasOps
*o
)
2435 gen_helper_deb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2439 static DisasJumpType
op_ddb(DisasContext
*s
, DisasOps
*o
)
2441 gen_helper_ddb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
2445 static DisasJumpType
op_dxb(DisasContext
*s
, DisasOps
*o
)
2447 gen_helper_dxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
2448 return_low128(o
->out2
);
2452 static DisasJumpType
op_ear(DisasContext
*s
, DisasOps
*o
)
2454 int r2
= get_field(s
, r2
);
2455 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, aregs
[r2
]));
2459 static DisasJumpType
op_ecag(DisasContext
*s
, DisasOps
*o
)
2461 /* No cache information provided. */
2462 tcg_gen_movi_i64(o
->out
, -1);
2466 static DisasJumpType
op_efpc(DisasContext
*s
, DisasOps
*o
)
2468 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, fpc
));
2472 static DisasJumpType
op_epsw(DisasContext
*s
, DisasOps
*o
)
2474 int r1
= get_field(s
, r1
);
2475 int r2
= get_field(s
, r2
);
2476 TCGv_i64 t
= tcg_temp_new_i64();
2478 /* Note the "subsequently" in the PoO, which implies a defined result
2479 if r1 == r2. Thus we cannot defer these writes to an output hook. */
2480 tcg_gen_shri_i64(t
, psw_mask
, 32);
2481 store_reg32_i64(r1
, t
);
2483 store_reg32_i64(r2
, psw_mask
);
2486 tcg_temp_free_i64(t
);
2490 static DisasJumpType
op_ex(DisasContext
*s
, DisasOps
*o
)
2492 int r1
= get_field(s
, r1
);
2496 /* Nested EXECUTE is not allowed. */
2497 if (unlikely(s
->ex_value
)) {
2498 gen_program_exception(s
, PGM_EXECUTE
);
2499 return DISAS_NORETURN
;
2506 v1
= tcg_const_i64(0);
2511 ilen
= tcg_const_i32(s
->ilen
);
2512 gen_helper_ex(cpu_env
, ilen
, v1
, o
->in2
);
2513 tcg_temp_free_i32(ilen
);
2516 tcg_temp_free_i64(v1
);
2519 return DISAS_PC_CC_UPDATED
;
2522 static DisasJumpType
op_fieb(DisasContext
*s
, DisasOps
*o
)
2524 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
2527 return DISAS_NORETURN
;
2529 gen_helper_fieb(o
->out
, cpu_env
, o
->in2
, m34
);
2530 tcg_temp_free_i32(m34
);
2534 static DisasJumpType
op_fidb(DisasContext
*s
, DisasOps
*o
)
2536 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
2539 return DISAS_NORETURN
;
2541 gen_helper_fidb(o
->out
, cpu_env
, o
->in2
, m34
);
2542 tcg_temp_free_i32(m34
);
2546 static DisasJumpType
op_fixb(DisasContext
*s
, DisasOps
*o
)
2548 TCGv_i32 m34
= fpinst_extract_m34(s
, false, true);
2551 return DISAS_NORETURN
;
2553 gen_helper_fixb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
2554 return_low128(o
->out2
);
2555 tcg_temp_free_i32(m34
);
2559 static DisasJumpType
op_flogr(DisasContext
*s
, DisasOps
*o
)
2561 /* We'll use the original input for cc computation, since we get to
2562 compare that against 0, which ought to be better than comparing
2563 the real output against 64. It also lets cc_dst be a convenient
2564 temporary during our computation. */
2565 gen_op_update1_cc_i64(s
, CC_OP_FLOGR
, o
->in2
);
2567 /* R1 = IN ? CLZ(IN) : 64. */
2568 tcg_gen_clzi_i64(o
->out
, o
->in2
, 64);
2570 /* R1+1 = IN & ~(found bit). Note that we may attempt to shift this
2571 value by 64, which is undefined. But since the shift is 64 iff the
2572 input is zero, we still get the correct result after and'ing. */
2573 tcg_gen_movi_i64(o
->out2
, 0x8000000000000000ull
);
2574 tcg_gen_shr_i64(o
->out2
, o
->out2
, o
->out
);
2575 tcg_gen_andc_i64(o
->out2
, cc_dst
, o
->out2
);
2579 static DisasJumpType
op_icm(DisasContext
*s
, DisasOps
*o
)
2581 int m3
= get_field(s
, m3
);
2582 int pos
, len
, base
= s
->insn
->data
;
2583 TCGv_i64 tmp
= tcg_temp_new_i64();
2588 /* Effectively a 32-bit load. */
2589 tcg_gen_qemu_ld32u(tmp
, o
->in2
, get_mem_index(s
));
2596 /* Effectively a 16-bit load. */
2597 tcg_gen_qemu_ld16u(tmp
, o
->in2
, get_mem_index(s
));
2605 /* Effectively an 8-bit load. */
2606 tcg_gen_qemu_ld8u(tmp
, o
->in2
, get_mem_index(s
));
2611 pos
= base
+ ctz32(m3
) * 8;
2612 tcg_gen_deposit_i64(o
->out
, o
->out
, tmp
, pos
, len
);
2613 ccm
= ((1ull << len
) - 1) << pos
;
2617 /* This is going to be a sequence of loads and inserts. */
2618 pos
= base
+ 32 - 8;
2622 tcg_gen_qemu_ld8u(tmp
, o
->in2
, get_mem_index(s
));
2623 tcg_gen_addi_i64(o
->in2
, o
->in2
, 1);
2624 tcg_gen_deposit_i64(o
->out
, o
->out
, tmp
, pos
, 8);
2627 m3
= (m3
<< 1) & 0xf;
2633 tcg_gen_movi_i64(tmp
, ccm
);
2634 gen_op_update2_cc_i64(s
, CC_OP_ICM
, tmp
, o
->out
);
2635 tcg_temp_free_i64(tmp
);
2639 static DisasJumpType
op_insi(DisasContext
*s
, DisasOps
*o
)
2641 int shift
= s
->insn
->data
& 0xff;
2642 int size
= s
->insn
->data
>> 8;
2643 tcg_gen_deposit_i64(o
->out
, o
->in1
, o
->in2
, shift
, size
);
2647 static DisasJumpType
op_ipm(DisasContext
*s
, DisasOps
*o
)
2652 t1
= tcg_temp_new_i64();
2653 tcg_gen_extract_i64(t1
, psw_mask
, 40, 4);
2654 t2
= tcg_temp_new_i64();
2655 tcg_gen_extu_i32_i64(t2
, cc_op
);
2656 tcg_gen_deposit_i64(t1
, t1
, t2
, 4, 60);
2657 tcg_gen_deposit_i64(o
->out
, o
->out
, t1
, 24, 8);
2658 tcg_temp_free_i64(t1
);
2659 tcg_temp_free_i64(t2
);
2663 #ifndef CONFIG_USER_ONLY
2664 static DisasJumpType
op_idte(DisasContext
*s
, DisasOps
*o
)
2668 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING
)) {
2669 m4
= tcg_const_i32(get_field(s
, m4
));
2671 m4
= tcg_const_i32(0);
2673 gen_helper_idte(cpu_env
, o
->in1
, o
->in2
, m4
);
2674 tcg_temp_free_i32(m4
);
2678 static DisasJumpType
op_ipte(DisasContext
*s
, DisasOps
*o
)
2682 if (s390_has_feat(S390_FEAT_LOCAL_TLB_CLEARING
)) {
2683 m4
= tcg_const_i32(get_field(s
, m4
));
2685 m4
= tcg_const_i32(0);
2687 gen_helper_ipte(cpu_env
, o
->in1
, o
->in2
, m4
);
2688 tcg_temp_free_i32(m4
);
2692 static DisasJumpType
op_iske(DisasContext
*s
, DisasOps
*o
)
2694 gen_helper_iske(o
->out
, cpu_env
, o
->in2
);
2699 static DisasJumpType
op_msa(DisasContext
*s
, DisasOps
*o
)
2701 int r1
= have_field(s
, r1
) ? get_field(s
, r1
) : 0;
2702 int r2
= have_field(s
, r2
) ? get_field(s
, r2
) : 0;
2703 int r3
= have_field(s
, r3
) ? get_field(s
, r3
) : 0;
2704 TCGv_i32 t_r1
, t_r2
, t_r3
, type
;
2706 switch (s
->insn
->data
) {
2707 case S390_FEAT_TYPE_KMA
:
2708 if (r3
== r1
|| r3
== r2
) {
2709 gen_program_exception(s
, PGM_SPECIFICATION
);
2710 return DISAS_NORETURN
;
2713 case S390_FEAT_TYPE_KMCTR
:
2714 if (r3
& 1 || !r3
) {
2715 gen_program_exception(s
, PGM_SPECIFICATION
);
2716 return DISAS_NORETURN
;
2719 case S390_FEAT_TYPE_PPNO
:
2720 case S390_FEAT_TYPE_KMF
:
2721 case S390_FEAT_TYPE_KMC
:
2722 case S390_FEAT_TYPE_KMO
:
2723 case S390_FEAT_TYPE_KM
:
2724 if (r1
& 1 || !r1
) {
2725 gen_program_exception(s
, PGM_SPECIFICATION
);
2726 return DISAS_NORETURN
;
2729 case S390_FEAT_TYPE_KMAC
:
2730 case S390_FEAT_TYPE_KIMD
:
2731 case S390_FEAT_TYPE_KLMD
:
2732 if (r2
& 1 || !r2
) {
2733 gen_program_exception(s
, PGM_SPECIFICATION
);
2734 return DISAS_NORETURN
;
2737 case S390_FEAT_TYPE_PCKMO
:
2738 case S390_FEAT_TYPE_PCC
:
2741 g_assert_not_reached();
2744 t_r1
= tcg_const_i32(r1
);
2745 t_r2
= tcg_const_i32(r2
);
2746 t_r3
= tcg_const_i32(r3
);
2747 type
= tcg_const_i32(s
->insn
->data
);
2748 gen_helper_msa(cc_op
, cpu_env
, t_r1
, t_r2
, t_r3
, type
);
2750 tcg_temp_free_i32(t_r1
);
2751 tcg_temp_free_i32(t_r2
);
2752 tcg_temp_free_i32(t_r3
);
2753 tcg_temp_free_i32(type
);
2757 static DisasJumpType
op_keb(DisasContext
*s
, DisasOps
*o
)
2759 gen_helper_keb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
2764 static DisasJumpType
op_kdb(DisasContext
*s
, DisasOps
*o
)
2766 gen_helper_kdb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
2771 static DisasJumpType
op_kxb(DisasContext
*s
, DisasOps
*o
)
2773 gen_helper_kxb(cc_op
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
2778 static DisasJumpType
op_laa(DisasContext
*s
, DisasOps
*o
)
2780 /* The real output is indeed the original value in memory;
2781 recompute the addition for the computation of CC. */
2782 tcg_gen_atomic_fetch_add_i64(o
->in2
, o
->in2
, o
->in1
, get_mem_index(s
),
2783 s
->insn
->data
| MO_ALIGN
);
2784 /* However, we need to recompute the addition for setting CC. */
2785 tcg_gen_add_i64(o
->out
, o
->in1
, o
->in2
);
2789 static DisasJumpType
op_lan(DisasContext
*s
, DisasOps
*o
)
2791 /* The real output is indeed the original value in memory;
2792 recompute the addition for the computation of CC. */
2793 tcg_gen_atomic_fetch_and_i64(o
->in2
, o
->in2
, o
->in1
, get_mem_index(s
),
2794 s
->insn
->data
| MO_ALIGN
);
2795 /* However, we need to recompute the operation for setting CC. */
2796 tcg_gen_and_i64(o
->out
, o
->in1
, o
->in2
);
2800 static DisasJumpType
op_lao(DisasContext
*s
, DisasOps
*o
)
2802 /* The real output is indeed the original value in memory;
2803 recompute the addition for the computation of CC. */
2804 tcg_gen_atomic_fetch_or_i64(o
->in2
, o
->in2
, o
->in1
, get_mem_index(s
),
2805 s
->insn
->data
| MO_ALIGN
);
2806 /* However, we need to recompute the operation for setting CC. */
2807 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
2811 static DisasJumpType
op_lax(DisasContext
*s
, DisasOps
*o
)
2813 /* The real output is indeed the original value in memory;
2814 recompute the addition for the computation of CC. */
2815 tcg_gen_atomic_fetch_xor_i64(o
->in2
, o
->in2
, o
->in1
, get_mem_index(s
),
2816 s
->insn
->data
| MO_ALIGN
);
2817 /* However, we need to recompute the operation for setting CC. */
2818 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
2822 static DisasJumpType
op_ldeb(DisasContext
*s
, DisasOps
*o
)
2824 gen_helper_ldeb(o
->out
, cpu_env
, o
->in2
);
2828 static DisasJumpType
op_ledb(DisasContext
*s
, DisasOps
*o
)
2830 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
2833 return DISAS_NORETURN
;
2835 gen_helper_ledb(o
->out
, cpu_env
, o
->in2
, m34
);
2836 tcg_temp_free_i32(m34
);
2840 static DisasJumpType
op_ldxb(DisasContext
*s
, DisasOps
*o
)
2842 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
2845 return DISAS_NORETURN
;
2847 gen_helper_ldxb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
2848 tcg_temp_free_i32(m34
);
2852 static DisasJumpType
op_lexb(DisasContext
*s
, DisasOps
*o
)
2854 TCGv_i32 m34
= fpinst_extract_m34(s
, true, true);
2857 return DISAS_NORETURN
;
2859 gen_helper_lexb(o
->out
, cpu_env
, o
->in1
, o
->in2
, m34
);
2860 tcg_temp_free_i32(m34
);
2864 static DisasJumpType
op_lxdb(DisasContext
*s
, DisasOps
*o
)
2866 gen_helper_lxdb(o
->out
, cpu_env
, o
->in2
);
2867 return_low128(o
->out2
);
2871 static DisasJumpType
op_lxeb(DisasContext
*s
, DisasOps
*o
)
2873 gen_helper_lxeb(o
->out
, cpu_env
, o
->in2
);
2874 return_low128(o
->out2
);
2878 static DisasJumpType
op_lde(DisasContext
*s
, DisasOps
*o
)
2880 tcg_gen_shli_i64(o
->out
, o
->in2
, 32);
2884 static DisasJumpType
op_llgt(DisasContext
*s
, DisasOps
*o
)
2886 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffff);
2890 static DisasJumpType
op_ld8s(DisasContext
*s
, DisasOps
*o
)
2892 tcg_gen_qemu_ld8s(o
->out
, o
->in2
, get_mem_index(s
));
2896 static DisasJumpType
op_ld8u(DisasContext
*s
, DisasOps
*o
)
2898 tcg_gen_qemu_ld8u(o
->out
, o
->in2
, get_mem_index(s
));
2902 static DisasJumpType
op_ld16s(DisasContext
*s
, DisasOps
*o
)
2904 tcg_gen_qemu_ld16s(o
->out
, o
->in2
, get_mem_index(s
));
2908 static DisasJumpType
op_ld16u(DisasContext
*s
, DisasOps
*o
)
2910 tcg_gen_qemu_ld16u(o
->out
, o
->in2
, get_mem_index(s
));
2914 static DisasJumpType
op_ld32s(DisasContext
*s
, DisasOps
*o
)
2916 tcg_gen_qemu_ld32s(o
->out
, o
->in2
, get_mem_index(s
));
2920 static DisasJumpType
op_ld32u(DisasContext
*s
, DisasOps
*o
)
2922 tcg_gen_qemu_ld32u(o
->out
, o
->in2
, get_mem_index(s
));
2926 static DisasJumpType
op_ld64(DisasContext
*s
, DisasOps
*o
)
2928 tcg_gen_qemu_ld64(o
->out
, o
->in2
, get_mem_index(s
));
2932 static DisasJumpType
op_lat(DisasContext
*s
, DisasOps
*o
)
2934 TCGLabel
*lab
= gen_new_label();
2935 store_reg32_i64(get_field(s
, r1
), o
->in2
);
2936 /* The value is stored even in case of trap. */
2937 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->in2
, 0, lab
);
2943 static DisasJumpType
op_lgat(DisasContext
*s
, DisasOps
*o
)
2945 TCGLabel
*lab
= gen_new_label();
2946 tcg_gen_qemu_ld64(o
->out
, o
->in2
, get_mem_index(s
));
2947 /* The value is stored even in case of trap. */
2948 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2954 static DisasJumpType
op_lfhat(DisasContext
*s
, DisasOps
*o
)
2956 TCGLabel
*lab
= gen_new_label();
2957 store_reg32h_i64(get_field(s
, r1
), o
->in2
);
2958 /* The value is stored even in case of trap. */
2959 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->in2
, 0, lab
);
2965 static DisasJumpType
op_llgfat(DisasContext
*s
, DisasOps
*o
)
2967 TCGLabel
*lab
= gen_new_label();
2968 tcg_gen_qemu_ld32u(o
->out
, o
->in2
, get_mem_index(s
));
2969 /* The value is stored even in case of trap. */
2970 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2976 static DisasJumpType
op_llgtat(DisasContext
*s
, DisasOps
*o
)
2978 TCGLabel
*lab
= gen_new_label();
2979 tcg_gen_andi_i64(o
->out
, o
->in2
, 0x7fffffff);
2980 /* The value is stored even in case of trap. */
2981 tcg_gen_brcondi_i64(TCG_COND_NE
, o
->out
, 0, lab
);
2987 static DisasJumpType
op_loc(DisasContext
*s
, DisasOps
*o
)
2991 if (have_field(s
, m3
)) {
2992 /* LOAD * ON CONDITION */
2993 disas_jcc(s
, &c
, get_field(s
, m3
));
2996 disas_jcc(s
, &c
, get_field(s
, m4
));
3000 tcg_gen_movcond_i64(c
.cond
, o
->out
, c
.u
.s64
.a
, c
.u
.s64
.b
,
3004 TCGv_i32 t32
= tcg_temp_new_i32();
3007 tcg_gen_setcond_i32(c
.cond
, t32
, c
.u
.s32
.a
, c
.u
.s32
.b
);
3010 t
= tcg_temp_new_i64();
3011 tcg_gen_extu_i32_i64(t
, t32
);
3012 tcg_temp_free_i32(t32
);
3014 z
= tcg_const_i64(0);
3015 tcg_gen_movcond_i64(TCG_COND_NE
, o
->out
, t
, z
, o
->in2
, o
->in1
);
3016 tcg_temp_free_i64(t
);
3017 tcg_temp_free_i64(z
);
3023 #ifndef CONFIG_USER_ONLY
3024 static DisasJumpType
op_lctl(DisasContext
*s
, DisasOps
*o
)
3026 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
3027 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
3028 gen_helper_lctl(cpu_env
, r1
, o
->in2
, r3
);
3029 tcg_temp_free_i32(r1
);
3030 tcg_temp_free_i32(r3
);
3031 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
3032 return DISAS_PC_STALE_NOCHAIN
;
3035 static DisasJumpType
op_lctlg(DisasContext
*s
, DisasOps
*o
)
3037 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
3038 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
3039 gen_helper_lctlg(cpu_env
, r1
, o
->in2
, r3
);
3040 tcg_temp_free_i32(r1
);
3041 tcg_temp_free_i32(r3
);
3042 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
3043 return DISAS_PC_STALE_NOCHAIN
;
3046 static DisasJumpType
op_lra(DisasContext
*s
, DisasOps
*o
)
3048 gen_helper_lra(o
->out
, cpu_env
, o
->in2
);
3053 static DisasJumpType
op_lpp(DisasContext
*s
, DisasOps
*o
)
3055 tcg_gen_st_i64(o
->in2
, cpu_env
, offsetof(CPUS390XState
, pp
));
3059 static DisasJumpType
op_lpsw(DisasContext
*s
, DisasOps
*o
)
3063 per_breaking_event(s
);
3065 t1
= tcg_temp_new_i64();
3066 t2
= tcg_temp_new_i64();
3067 tcg_gen_qemu_ld_i64(t1
, o
->in2
, get_mem_index(s
),
3068 MO_TEUL
| MO_ALIGN_8
);
3069 tcg_gen_addi_i64(o
->in2
, o
->in2
, 4);
3070 tcg_gen_qemu_ld32u(t2
, o
->in2
, get_mem_index(s
));
3071 /* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */
3072 tcg_gen_shli_i64(t1
, t1
, 32);
3073 gen_helper_load_psw(cpu_env
, t1
, t2
);
3074 tcg_temp_free_i64(t1
);
3075 tcg_temp_free_i64(t2
);
3076 return DISAS_NORETURN
;
3079 static DisasJumpType
op_lpswe(DisasContext
*s
, DisasOps
*o
)
3083 per_breaking_event(s
);
3085 t1
= tcg_temp_new_i64();
3086 t2
= tcg_temp_new_i64();
3087 tcg_gen_qemu_ld_i64(t1
, o
->in2
, get_mem_index(s
),
3088 MO_TEUQ
| MO_ALIGN_8
);
3089 tcg_gen_addi_i64(o
->in2
, o
->in2
, 8);
3090 tcg_gen_qemu_ld64(t2
, o
->in2
, get_mem_index(s
));
3091 gen_helper_load_psw(cpu_env
, t1
, t2
);
3092 tcg_temp_free_i64(t1
);
3093 tcg_temp_free_i64(t2
);
3094 return DISAS_NORETURN
;
3098 static DisasJumpType
op_lam(DisasContext
*s
, DisasOps
*o
)
3100 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
3101 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
3102 gen_helper_lam(cpu_env
, r1
, o
->in2
, r3
);
3103 tcg_temp_free_i32(r1
);
3104 tcg_temp_free_i32(r3
);
3108 static DisasJumpType
op_lm32(DisasContext
*s
, DisasOps
*o
)
3110 int r1
= get_field(s
, r1
);
3111 int r3
= get_field(s
, r3
);
3114 /* Only one register to read. */
3115 t1
= tcg_temp_new_i64();
3116 if (unlikely(r1
== r3
)) {
3117 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3118 store_reg32_i64(r1
, t1
);
3123 /* First load the values of the first and last registers to trigger
3124 possible page faults. */
3125 t2
= tcg_temp_new_i64();
3126 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3127 tcg_gen_addi_i64(t2
, o
->in2
, 4 * ((r3
- r1
) & 15));
3128 tcg_gen_qemu_ld32u(t2
, t2
, get_mem_index(s
));
3129 store_reg32_i64(r1
, t1
);
3130 store_reg32_i64(r3
, t2
);
3132 /* Only two registers to read. */
3133 if (((r1
+ 1) & 15) == r3
) {
3139 /* Then load the remaining registers. Page fault can't occur. */
3141 tcg_gen_movi_i64(t2
, 4);
3144 tcg_gen_add_i64(o
->in2
, o
->in2
, t2
);
3145 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3146 store_reg32_i64(r1
, t1
);
3154 static DisasJumpType
op_lmh(DisasContext
*s
, DisasOps
*o
)
3156 int r1
= get_field(s
, r1
);
3157 int r3
= get_field(s
, r3
);
3160 /* Only one register to read. */
3161 t1
= tcg_temp_new_i64();
3162 if (unlikely(r1
== r3
)) {
3163 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3164 store_reg32h_i64(r1
, t1
);
3169 /* First load the values of the first and last registers to trigger
3170 possible page faults. */
3171 t2
= tcg_temp_new_i64();
3172 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3173 tcg_gen_addi_i64(t2
, o
->in2
, 4 * ((r3
- r1
) & 15));
3174 tcg_gen_qemu_ld32u(t2
, t2
, get_mem_index(s
));
3175 store_reg32h_i64(r1
, t1
);
3176 store_reg32h_i64(r3
, t2
);
3178 /* Only two registers to read. */
3179 if (((r1
+ 1) & 15) == r3
) {
3185 /* Then load the remaining registers. Page fault can't occur. */
3187 tcg_gen_movi_i64(t2
, 4);
3190 tcg_gen_add_i64(o
->in2
, o
->in2
, t2
);
3191 tcg_gen_qemu_ld32u(t1
, o
->in2
, get_mem_index(s
));
3192 store_reg32h_i64(r1
, t1
);
3200 static DisasJumpType
op_lm64(DisasContext
*s
, DisasOps
*o
)
3202 int r1
= get_field(s
, r1
);
3203 int r3
= get_field(s
, r3
);
3206 /* Only one register to read. */
3207 if (unlikely(r1
== r3
)) {
3208 tcg_gen_qemu_ld64(regs
[r1
], o
->in2
, get_mem_index(s
));
3212 /* First load the values of the first and last registers to trigger
3213 possible page faults. */
3214 t1
= tcg_temp_new_i64();
3215 t2
= tcg_temp_new_i64();
3216 tcg_gen_qemu_ld64(t1
, o
->in2
, get_mem_index(s
));
3217 tcg_gen_addi_i64(t2
, o
->in2
, 8 * ((r3
- r1
) & 15));
3218 tcg_gen_qemu_ld64(regs
[r3
], t2
, get_mem_index(s
));
3219 tcg_gen_mov_i64(regs
[r1
], t1
);
3222 /* Only two registers to read. */
3223 if (((r1
+ 1) & 15) == r3
) {
3228 /* Then load the remaining registers. Page fault can't occur. */
3230 tcg_gen_movi_i64(t1
, 8);
3233 tcg_gen_add_i64(o
->in2
, o
->in2
, t1
);
3234 tcg_gen_qemu_ld64(regs
[r1
], o
->in2
, get_mem_index(s
));
3241 static DisasJumpType
op_lpd(DisasContext
*s
, DisasOps
*o
)
3244 MemOp mop
= s
->insn
->data
;
3246 /* In a parallel context, stop the world and single step. */
3247 if (tb_cflags(s
->base
.tb
) & CF_PARALLEL
) {
3250 gen_exception(EXCP_ATOMIC
);
3251 return DISAS_NORETURN
;
3254 /* In a serial context, perform the two loads ... */
3255 a1
= get_address(s
, 0, get_field(s
, b1
), get_field(s
, d1
));
3256 a2
= get_address(s
, 0, get_field(s
, b2
), get_field(s
, d2
));
3257 tcg_gen_qemu_ld_i64(o
->out
, a1
, get_mem_index(s
), mop
| MO_ALIGN
);
3258 tcg_gen_qemu_ld_i64(o
->out2
, a2
, get_mem_index(s
), mop
| MO_ALIGN
);
3259 tcg_temp_free_i64(a1
);
3260 tcg_temp_free_i64(a2
);
3262 /* ... and indicate that we performed them while interlocked. */
3263 gen_op_movi_cc(s
, 0);
3267 static DisasJumpType
op_lpq(DisasContext
*s
, DisasOps
*o
)
3269 if (!(tb_cflags(s
->base
.tb
) & CF_PARALLEL
)) {
3270 gen_helper_lpq(o
->out
, cpu_env
, o
->in2
);
3271 } else if (HAVE_ATOMIC128
) {
3272 gen_helper_lpq_parallel(o
->out
, cpu_env
, o
->in2
);
3274 gen_helper_exit_atomic(cpu_env
);
3275 return DISAS_NORETURN
;
3277 return_low128(o
->out2
);
3281 #ifndef CONFIG_USER_ONLY
3282 static DisasJumpType
op_lura(DisasContext
*s
, DisasOps
*o
)
3284 tcg_gen_qemu_ld_tl(o
->out
, o
->in2
, MMU_REAL_IDX
, s
->insn
->data
);
3289 static DisasJumpType
op_lzrb(DisasContext
*s
, DisasOps
*o
)
3291 tcg_gen_andi_i64(o
->out
, o
->in2
, -256);
3295 static DisasJumpType
op_lcbb(DisasContext
*s
, DisasOps
*o
)
3297 const int64_t block_size
= (1ull << (get_field(s
, m3
) + 6));
3299 if (get_field(s
, m3
) > 6) {
3300 gen_program_exception(s
, PGM_SPECIFICATION
);
3301 return DISAS_NORETURN
;
3304 tcg_gen_ori_i64(o
->addr1
, o
->addr1
, -block_size
);
3305 tcg_gen_neg_i64(o
->addr1
, o
->addr1
);
3306 tcg_gen_movi_i64(o
->out
, 16);
3307 tcg_gen_umin_i64(o
->out
, o
->out
, o
->addr1
);
3308 gen_op_update1_cc_i64(s
, CC_OP_LCBB
, o
->out
);
3312 static DisasJumpType
op_mc(DisasContext
*s
, DisasOps
*o
)
3314 #if !defined(CONFIG_USER_ONLY)
3317 const uint16_t monitor_class
= get_field(s
, i2
);
3319 if (monitor_class
& 0xff00) {
3320 gen_program_exception(s
, PGM_SPECIFICATION
);
3321 return DISAS_NORETURN
;
3324 #if !defined(CONFIG_USER_ONLY)
3325 i2
= tcg_const_i32(monitor_class
);
3326 gen_helper_monitor_call(cpu_env
, o
->addr1
, i2
);
3327 tcg_temp_free_i32(i2
);
3329 /* Defaults to a NOP. */
3333 static DisasJumpType
op_mov2(DisasContext
*s
, DisasOps
*o
)
3336 o
->g_out
= o
->g_in2
;
3342 static DisasJumpType
op_mov2e(DisasContext
*s
, DisasOps
*o
)
3344 int b2
= get_field(s
, b2
);
3345 TCGv ar1
= tcg_temp_new_i64();
3348 o
->g_out
= o
->g_in2
;
3352 switch (s
->base
.tb
->flags
& FLAG_MASK_ASC
) {
3353 case PSW_ASC_PRIMARY
>> FLAG_MASK_PSW_SHIFT
:
3354 tcg_gen_movi_i64(ar1
, 0);
3356 case PSW_ASC_ACCREG
>> FLAG_MASK_PSW_SHIFT
:
3357 tcg_gen_movi_i64(ar1
, 1);
3359 case PSW_ASC_SECONDARY
>> FLAG_MASK_PSW_SHIFT
:
3361 tcg_gen_ld32u_i64(ar1
, cpu_env
, offsetof(CPUS390XState
, aregs
[b2
]));
3363 tcg_gen_movi_i64(ar1
, 0);
3366 case PSW_ASC_HOME
>> FLAG_MASK_PSW_SHIFT
:
3367 tcg_gen_movi_i64(ar1
, 2);
3371 tcg_gen_st32_i64(ar1
, cpu_env
, offsetof(CPUS390XState
, aregs
[1]));
3372 tcg_temp_free_i64(ar1
);
3377 static DisasJumpType
op_movx(DisasContext
*s
, DisasOps
*o
)
3381 o
->g_out
= o
->g_in1
;
3382 o
->g_out2
= o
->g_in2
;
3385 o
->g_in1
= o
->g_in2
= false;
3389 static DisasJumpType
op_mvc(DisasContext
*s
, DisasOps
*o
)
3391 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3392 gen_helper_mvc(cpu_env
, l
, o
->addr1
, o
->in2
);
3393 tcg_temp_free_i32(l
);
3397 static DisasJumpType
op_mvcrl(DisasContext
*s
, DisasOps
*o
)
3399 gen_helper_mvcrl(cpu_env
, regs
[0], o
->addr1
, o
->in2
);
3403 static DisasJumpType
op_mvcin(DisasContext
*s
, DisasOps
*o
)
3405 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3406 gen_helper_mvcin(cpu_env
, l
, o
->addr1
, o
->in2
);
3407 tcg_temp_free_i32(l
);
3411 static DisasJumpType
op_mvcl(DisasContext
*s
, DisasOps
*o
)
3413 int r1
= get_field(s
, r1
);
3414 int r2
= get_field(s
, r2
);
3417 /* r1 and r2 must be even. */
3418 if (r1
& 1 || r2
& 1) {
3419 gen_program_exception(s
, PGM_SPECIFICATION
);
3420 return DISAS_NORETURN
;
3423 t1
= tcg_const_i32(r1
);
3424 t2
= tcg_const_i32(r2
);
3425 gen_helper_mvcl(cc_op
, cpu_env
, t1
, t2
);
3426 tcg_temp_free_i32(t1
);
3427 tcg_temp_free_i32(t2
);
3432 static DisasJumpType
op_mvcle(DisasContext
*s
, DisasOps
*o
)
3434 int r1
= get_field(s
, r1
);
3435 int r3
= get_field(s
, r3
);
3438 /* r1 and r3 must be even. */
3439 if (r1
& 1 || r3
& 1) {
3440 gen_program_exception(s
, PGM_SPECIFICATION
);
3441 return DISAS_NORETURN
;
3444 t1
= tcg_const_i32(r1
);
3445 t3
= tcg_const_i32(r3
);
3446 gen_helper_mvcle(cc_op
, cpu_env
, t1
, o
->in2
, t3
);
3447 tcg_temp_free_i32(t1
);
3448 tcg_temp_free_i32(t3
);
3453 static DisasJumpType
op_mvclu(DisasContext
*s
, DisasOps
*o
)
3455 int r1
= get_field(s
, r1
);
3456 int r3
= get_field(s
, r3
);
3459 /* r1 and r3 must be even. */
3460 if (r1
& 1 || r3
& 1) {
3461 gen_program_exception(s
, PGM_SPECIFICATION
);
3462 return DISAS_NORETURN
;
3465 t1
= tcg_const_i32(r1
);
3466 t3
= tcg_const_i32(r3
);
3467 gen_helper_mvclu(cc_op
, cpu_env
, t1
, o
->in2
, t3
);
3468 tcg_temp_free_i32(t1
);
3469 tcg_temp_free_i32(t3
);
3474 static DisasJumpType
op_mvcos(DisasContext
*s
, DisasOps
*o
)
3476 int r3
= get_field(s
, r3
);
3477 gen_helper_mvcos(cc_op
, cpu_env
, o
->addr1
, o
->in2
, regs
[r3
]);
3482 #ifndef CONFIG_USER_ONLY
3483 static DisasJumpType
op_mvcp(DisasContext
*s
, DisasOps
*o
)
3485 int r1
= get_field(s
, l1
);
3486 gen_helper_mvcp(cc_op
, cpu_env
, regs
[r1
], o
->addr1
, o
->in2
);
3491 static DisasJumpType
op_mvcs(DisasContext
*s
, DisasOps
*o
)
3493 int r1
= get_field(s
, l1
);
3494 gen_helper_mvcs(cc_op
, cpu_env
, regs
[r1
], o
->addr1
, o
->in2
);
3500 static DisasJumpType
op_mvn(DisasContext
*s
, DisasOps
*o
)
3502 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3503 gen_helper_mvn(cpu_env
, l
, o
->addr1
, o
->in2
);
3504 tcg_temp_free_i32(l
);
3508 static DisasJumpType
op_mvo(DisasContext
*s
, DisasOps
*o
)
3510 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3511 gen_helper_mvo(cpu_env
, l
, o
->addr1
, o
->in2
);
3512 tcg_temp_free_i32(l
);
3516 static DisasJumpType
op_mvpg(DisasContext
*s
, DisasOps
*o
)
3518 TCGv_i32 t1
= tcg_const_i32(get_field(s
, r1
));
3519 TCGv_i32 t2
= tcg_const_i32(get_field(s
, r2
));
3521 gen_helper_mvpg(cc_op
, cpu_env
, regs
[0], t1
, t2
);
3522 tcg_temp_free_i32(t1
);
3523 tcg_temp_free_i32(t2
);
3528 static DisasJumpType
op_mvst(DisasContext
*s
, DisasOps
*o
)
3530 TCGv_i32 t1
= tcg_const_i32(get_field(s
, r1
));
3531 TCGv_i32 t2
= tcg_const_i32(get_field(s
, r2
));
3533 gen_helper_mvst(cc_op
, cpu_env
, t1
, t2
);
3534 tcg_temp_free_i32(t1
);
3535 tcg_temp_free_i32(t2
);
3540 static DisasJumpType
op_mvz(DisasContext
*s
, DisasOps
*o
)
3542 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3543 gen_helper_mvz(cpu_env
, l
, o
->addr1
, o
->in2
);
3544 tcg_temp_free_i32(l
);
3548 static DisasJumpType
op_mul(DisasContext
*s
, DisasOps
*o
)
3550 tcg_gen_mul_i64(o
->out
, o
->in1
, o
->in2
);
3554 static DisasJumpType
op_mul128(DisasContext
*s
, DisasOps
*o
)
3556 tcg_gen_mulu2_i64(o
->out2
, o
->out
, o
->in1
, o
->in2
);
3560 static DisasJumpType
op_muls128(DisasContext
*s
, DisasOps
*o
)
3562 tcg_gen_muls2_i64(o
->out2
, o
->out
, o
->in1
, o
->in2
);
3566 static DisasJumpType
op_meeb(DisasContext
*s
, DisasOps
*o
)
3568 gen_helper_meeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3572 static DisasJumpType
op_mdeb(DisasContext
*s
, DisasOps
*o
)
3574 gen_helper_mdeb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3578 static DisasJumpType
op_mdb(DisasContext
*s
, DisasOps
*o
)
3580 gen_helper_mdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
3584 static DisasJumpType
op_mxb(DisasContext
*s
, DisasOps
*o
)
3586 gen_helper_mxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
3587 return_low128(o
->out2
);
3591 static DisasJumpType
op_mxdb(DisasContext
*s
, DisasOps
*o
)
3593 gen_helper_mxdb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
3594 return_low128(o
->out2
);
3598 static DisasJumpType
op_maeb(DisasContext
*s
, DisasOps
*o
)
3600 TCGv_i64 r3
= load_freg32_i64(get_field(s
, r3
));
3601 gen_helper_maeb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
3602 tcg_temp_free_i64(r3
);
3606 static DisasJumpType
op_madb(DisasContext
*s
, DisasOps
*o
)
3608 TCGv_i64 r3
= load_freg(get_field(s
, r3
));
3609 gen_helper_madb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
3610 tcg_temp_free_i64(r3
);
3614 static DisasJumpType
op_mseb(DisasContext
*s
, DisasOps
*o
)
3616 TCGv_i64 r3
= load_freg32_i64(get_field(s
, r3
));
3617 gen_helper_mseb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
3618 tcg_temp_free_i64(r3
);
3622 static DisasJumpType
op_msdb(DisasContext
*s
, DisasOps
*o
)
3624 TCGv_i64 r3
= load_freg(get_field(s
, r3
));
3625 gen_helper_msdb(o
->out
, cpu_env
, o
->in1
, o
->in2
, r3
);
3626 tcg_temp_free_i64(r3
);
3630 static DisasJumpType
op_nabs(DisasContext
*s
, DisasOps
*o
)
3633 z
= tcg_const_i64(0);
3634 n
= tcg_temp_new_i64();
3635 tcg_gen_neg_i64(n
, o
->in2
);
3636 tcg_gen_movcond_i64(TCG_COND_GE
, o
->out
, o
->in2
, z
, n
, o
->in2
);
3637 tcg_temp_free_i64(n
);
3638 tcg_temp_free_i64(z
);
3642 static DisasJumpType
op_nabsf32(DisasContext
*s
, DisasOps
*o
)
3644 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x80000000ull
);
3648 static DisasJumpType
op_nabsf64(DisasContext
*s
, DisasOps
*o
)
3650 tcg_gen_ori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
3654 static DisasJumpType
op_nabsf128(DisasContext
*s
, DisasOps
*o
)
3656 tcg_gen_ori_i64(o
->out
, o
->in1
, 0x8000000000000000ull
);
3657 tcg_gen_mov_i64(o
->out2
, o
->in2
);
3661 static DisasJumpType
op_nc(DisasContext
*s
, DisasOps
*o
)
3663 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3664 gen_helper_nc(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
3665 tcg_temp_free_i32(l
);
3670 static DisasJumpType
op_neg(DisasContext
*s
, DisasOps
*o
)
3672 tcg_gen_neg_i64(o
->out
, o
->in2
);
3676 static DisasJumpType
op_negf32(DisasContext
*s
, DisasOps
*o
)
3678 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x80000000ull
);
3682 static DisasJumpType
op_negf64(DisasContext
*s
, DisasOps
*o
)
3684 tcg_gen_xori_i64(o
->out
, o
->in2
, 0x8000000000000000ull
);
3688 static DisasJumpType
op_negf128(DisasContext
*s
, DisasOps
*o
)
3690 tcg_gen_xori_i64(o
->out
, o
->in1
, 0x8000000000000000ull
);
3691 tcg_gen_mov_i64(o
->out2
, o
->in2
);
3695 static DisasJumpType
op_oc(DisasContext
*s
, DisasOps
*o
)
3697 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3698 gen_helper_oc(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
3699 tcg_temp_free_i32(l
);
3704 static DisasJumpType
op_or(DisasContext
*s
, DisasOps
*o
)
3706 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
3710 static DisasJumpType
op_ori(DisasContext
*s
, DisasOps
*o
)
3712 int shift
= s
->insn
->data
& 0xff;
3713 int size
= s
->insn
->data
>> 8;
3714 uint64_t mask
= ((1ull << size
) - 1) << shift
;
3717 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
3718 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
3720 /* Produce the CC from only the bits manipulated. */
3721 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
3722 set_cc_nz_u64(s
, cc_dst
);
3726 static DisasJumpType
op_oi(DisasContext
*s
, DisasOps
*o
)
3728 o
->in1
= tcg_temp_new_i64();
3730 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
3731 tcg_gen_qemu_ld_tl(o
->in1
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
3733 /* Perform the atomic operation in memory. */
3734 tcg_gen_atomic_fetch_or_i64(o
->in1
, o
->addr1
, o
->in2
, get_mem_index(s
),
3738 /* Recompute also for atomic case: needed for setting CC. */
3739 tcg_gen_or_i64(o
->out
, o
->in1
, o
->in2
);
3741 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
3742 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
3747 static DisasJumpType
op_pack(DisasContext
*s
, DisasOps
*o
)
3749 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
3750 gen_helper_pack(cpu_env
, l
, o
->addr1
, o
->in2
);
3751 tcg_temp_free_i32(l
);
3755 static DisasJumpType
op_pka(DisasContext
*s
, DisasOps
*o
)
3757 int l2
= get_field(s
, l2
) + 1;
3760 /* The length must not exceed 32 bytes. */
3762 gen_program_exception(s
, PGM_SPECIFICATION
);
3763 return DISAS_NORETURN
;
3765 l
= tcg_const_i32(l2
);
3766 gen_helper_pka(cpu_env
, o
->addr1
, o
->in2
, l
);
3767 tcg_temp_free_i32(l
);
3771 static DisasJumpType
op_pku(DisasContext
*s
, DisasOps
*o
)
3773 int l2
= get_field(s
, l2
) + 1;
3776 /* The length must be even and should not exceed 64 bytes. */
3777 if ((l2
& 1) || (l2
> 64)) {
3778 gen_program_exception(s
, PGM_SPECIFICATION
);
3779 return DISAS_NORETURN
;
3781 l
= tcg_const_i32(l2
);
3782 gen_helper_pku(cpu_env
, o
->addr1
, o
->in2
, l
);
3783 tcg_temp_free_i32(l
);
3787 static DisasJumpType
op_popcnt(DisasContext
*s
, DisasOps
*o
)
3789 const uint8_t m3
= get_field(s
, m3
);
3791 if ((m3
& 8) && s390_has_feat(S390_FEAT_MISC_INSTRUCTION_EXT3
)) {
3792 tcg_gen_ctpop_i64(o
->out
, o
->in2
);
3794 gen_helper_popcnt(o
->out
, o
->in2
);
3799 #ifndef CONFIG_USER_ONLY
3800 static DisasJumpType
op_ptlb(DisasContext
*s
, DisasOps
*o
)
3802 gen_helper_ptlb(cpu_env
);
3807 static DisasJumpType
op_risbg(DisasContext
*s
, DisasOps
*o
)
3809 int i3
= get_field(s
, i3
);
3810 int i4
= get_field(s
, i4
);
3811 int i5
= get_field(s
, i5
);
3812 int do_zero
= i4
& 0x80;
3813 uint64_t mask
, imask
, pmask
;
3816 /* Adjust the arguments for the specific insn. */
3817 switch (s
->fields
.op2
) {
3818 case 0x55: /* risbg */
3819 case 0x59: /* risbgn */
3824 case 0x5d: /* risbhg */
3827 pmask
= 0xffffffff00000000ull
;
3829 case 0x51: /* risblg */
3830 i3
= (i3
& 31) + 32;
3831 i4
= (i4
& 31) + 32;
3832 pmask
= 0x00000000ffffffffull
;
3835 g_assert_not_reached();
3838 /* MASK is the set of bits to be inserted from R2. */
3840 /* [0...i3---i4...63] */
3841 mask
= (-1ull >> i3
) & (-1ull << (63 - i4
));
3843 /* [0---i4...i3---63] */
3844 mask
= (-1ull >> i3
) | (-1ull << (63 - i4
));
3846 /* For RISBLG/RISBHG, the wrapping is limited to the high/low doubleword. */
3849 /* IMASK is the set of bits to be kept from R1. In the case of the high/low
3850 insns, we need to keep the other half of the register. */
3851 imask
= ~mask
| ~pmask
;
3860 /* In some cases we can implement this with extract. */
3861 if (imask
== 0 && pos
== 0 && len
> 0 && len
<= rot
) {
3862 tcg_gen_extract_i64(o
->out
, o
->in2
, 64 - rot
, len
);
3866 /* In some cases we can implement this with deposit. */
3867 if (len
> 0 && (imask
== 0 || ~mask
== imask
)) {
3868 /* Note that we rotate the bits to be inserted to the lsb, not to
3869 the position as described in the PoO. */
3870 rot
= (rot
- pos
) & 63;
3875 /* Rotate the input as necessary. */
3876 tcg_gen_rotli_i64(o
->in2
, o
->in2
, rot
);
3878 /* Insert the selected bits into the output. */
3881 tcg_gen_deposit_z_i64(o
->out
, o
->in2
, pos
, len
);
3883 tcg_gen_deposit_i64(o
->out
, o
->out
, o
->in2
, pos
, len
);
3885 } else if (imask
== 0) {
3886 tcg_gen_andi_i64(o
->out
, o
->in2
, mask
);
3888 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3889 tcg_gen_andi_i64(o
->out
, o
->out
, imask
);
3890 tcg_gen_or_i64(o
->out
, o
->out
, o
->in2
);
3895 static DisasJumpType
op_rosbg(DisasContext
*s
, DisasOps
*o
)
3897 int i3
= get_field(s
, i3
);
3898 int i4
= get_field(s
, i4
);
3899 int i5
= get_field(s
, i5
);
3902 /* If this is a test-only form, arrange to discard the result. */
3904 o
->out
= tcg_temp_new_i64();
3912 /* MASK is the set of bits to be operated on from R2.
3913 Take care for I3/I4 wraparound. */
3916 mask
^= ~0ull >> i4
>> 1;
3918 mask
|= ~(~0ull >> i4
>> 1);
3921 /* Rotate the input as necessary. */
3922 tcg_gen_rotli_i64(o
->in2
, o
->in2
, i5
);
3925 switch (s
->fields
.op2
) {
3926 case 0x54: /* AND */
3927 tcg_gen_ori_i64(o
->in2
, o
->in2
, ~mask
);
3928 tcg_gen_and_i64(o
->out
, o
->out
, o
->in2
);
3931 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3932 tcg_gen_or_i64(o
->out
, o
->out
, o
->in2
);
3934 case 0x57: /* XOR */
3935 tcg_gen_andi_i64(o
->in2
, o
->in2
, mask
);
3936 tcg_gen_xor_i64(o
->out
, o
->out
, o
->in2
);
3943 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
3944 set_cc_nz_u64(s
, cc_dst
);
3948 static DisasJumpType
op_rev16(DisasContext
*s
, DisasOps
*o
)
3950 tcg_gen_bswap16_i64(o
->out
, o
->in2
, TCG_BSWAP_IZ
| TCG_BSWAP_OZ
);
3954 static DisasJumpType
op_rev32(DisasContext
*s
, DisasOps
*o
)
3956 tcg_gen_bswap32_i64(o
->out
, o
->in2
, TCG_BSWAP_IZ
| TCG_BSWAP_OZ
);
3960 static DisasJumpType
op_rev64(DisasContext
*s
, DisasOps
*o
)
3962 tcg_gen_bswap64_i64(o
->out
, o
->in2
);
3966 static DisasJumpType
op_rll32(DisasContext
*s
, DisasOps
*o
)
3968 TCGv_i32 t1
= tcg_temp_new_i32();
3969 TCGv_i32 t2
= tcg_temp_new_i32();
3970 TCGv_i32 to
= tcg_temp_new_i32();
3971 tcg_gen_extrl_i64_i32(t1
, o
->in1
);
3972 tcg_gen_extrl_i64_i32(t2
, o
->in2
);
3973 tcg_gen_rotl_i32(to
, t1
, t2
);
3974 tcg_gen_extu_i32_i64(o
->out
, to
);
3975 tcg_temp_free_i32(t1
);
3976 tcg_temp_free_i32(t2
);
3977 tcg_temp_free_i32(to
);
3981 static DisasJumpType
op_rll64(DisasContext
*s
, DisasOps
*o
)
3983 tcg_gen_rotl_i64(o
->out
, o
->in1
, o
->in2
);
3987 #ifndef CONFIG_USER_ONLY
3988 static DisasJumpType
op_rrbe(DisasContext
*s
, DisasOps
*o
)
3990 gen_helper_rrbe(cc_op
, cpu_env
, o
->in2
);
3995 static DisasJumpType
op_sacf(DisasContext
*s
, DisasOps
*o
)
3997 gen_helper_sacf(cpu_env
, o
->in2
);
3998 /* Addressing mode has changed, so end the block. */
3999 return DISAS_PC_STALE
;
4003 static DisasJumpType
op_sam(DisasContext
*s
, DisasOps
*o
)
4005 int sam
= s
->insn
->data
;
4021 /* Bizarre but true, we check the address of the current insn for the
4022 specification exception, not the next to be executed. Thus the PoO
4023 documents that Bad Things Happen two bytes before the end. */
4024 if (s
->base
.pc_next
& ~mask
) {
4025 gen_program_exception(s
, PGM_SPECIFICATION
);
4026 return DISAS_NORETURN
;
4030 tsam
= tcg_const_i64(sam
);
4031 tcg_gen_deposit_i64(psw_mask
, psw_mask
, tsam
, 31, 2);
4032 tcg_temp_free_i64(tsam
);
4034 /* Always exit the TB, since we (may have) changed execution mode. */
4035 return DISAS_PC_STALE
;
4038 static DisasJumpType
op_sar(DisasContext
*s
, DisasOps
*o
)
4040 int r1
= get_field(s
, r1
);
4041 tcg_gen_st32_i64(o
->in2
, cpu_env
, offsetof(CPUS390XState
, aregs
[r1
]));
4045 static DisasJumpType
op_seb(DisasContext
*s
, DisasOps
*o
)
4047 gen_helper_seb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
4051 static DisasJumpType
op_sdb(DisasContext
*s
, DisasOps
*o
)
4053 gen_helper_sdb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
4057 static DisasJumpType
op_sxb(DisasContext
*s
, DisasOps
*o
)
4059 gen_helper_sxb(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in1
, o
->in2
);
4060 return_low128(o
->out2
);
4064 static DisasJumpType
op_sqeb(DisasContext
*s
, DisasOps
*o
)
4066 gen_helper_sqeb(o
->out
, cpu_env
, o
->in2
);
4070 static DisasJumpType
op_sqdb(DisasContext
*s
, DisasOps
*o
)
4072 gen_helper_sqdb(o
->out
, cpu_env
, o
->in2
);
4076 static DisasJumpType
op_sqxb(DisasContext
*s
, DisasOps
*o
)
4078 gen_helper_sqxb(o
->out
, cpu_env
, o
->in1
, o
->in2
);
4079 return_low128(o
->out2
);
4083 #ifndef CONFIG_USER_ONLY
4084 static DisasJumpType
op_servc(DisasContext
*s
, DisasOps
*o
)
4086 gen_helper_servc(cc_op
, cpu_env
, o
->in2
, o
->in1
);
4091 static DisasJumpType
op_sigp(DisasContext
*s
, DisasOps
*o
)
4093 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4094 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
4095 gen_helper_sigp(cc_op
, cpu_env
, o
->in2
, r1
, r3
);
4097 tcg_temp_free_i32(r1
);
4098 tcg_temp_free_i32(r3
);
4103 static DisasJumpType
op_soc(DisasContext
*s
, DisasOps
*o
)
4110 disas_jcc(s
, &c
, get_field(s
, m3
));
4112 /* We want to store when the condition is fulfilled, so branch
4113 out when it's not */
4114 c
.cond
= tcg_invert_cond(c
.cond
);
4116 lab
= gen_new_label();
4118 tcg_gen_brcond_i64(c
.cond
, c
.u
.s64
.a
, c
.u
.s64
.b
, lab
);
4120 tcg_gen_brcond_i32(c
.cond
, c
.u
.s32
.a
, c
.u
.s32
.b
, lab
);
4124 r1
= get_field(s
, r1
);
4125 a
= get_address(s
, 0, get_field(s
, b2
), get_field(s
, d2
));
4126 switch (s
->insn
->data
) {
4128 tcg_gen_qemu_st64(regs
[r1
], a
, get_mem_index(s
));
4131 tcg_gen_qemu_st32(regs
[r1
], a
, get_mem_index(s
));
4133 case 2: /* STOCFH */
4134 h
= tcg_temp_new_i64();
4135 tcg_gen_shri_i64(h
, regs
[r1
], 32);
4136 tcg_gen_qemu_st32(h
, a
, get_mem_index(s
));
4137 tcg_temp_free_i64(h
);
4140 g_assert_not_reached();
4142 tcg_temp_free_i64(a
);
4148 static DisasJumpType
op_sla(DisasContext
*s
, DisasOps
*o
)
4151 uint64_t sign
= 1ull << s
->insn
->data
;
4152 if (s
->insn
->data
== 31) {
4153 t
= tcg_temp_new_i64();
4154 tcg_gen_shli_i64(t
, o
->in1
, 32);
4158 gen_op_update2_cc_i64(s
, CC_OP_SLA
, t
, o
->in2
);
4159 if (s
->insn
->data
== 31) {
4160 tcg_temp_free_i64(t
);
4162 tcg_gen_shl_i64(o
->out
, o
->in1
, o
->in2
);
4163 /* The arithmetic left shift is curious in that it does not affect
4164 the sign bit. Copy that over from the source unchanged. */
4165 tcg_gen_andi_i64(o
->out
, o
->out
, ~sign
);
4166 tcg_gen_andi_i64(o
->in1
, o
->in1
, sign
);
4167 tcg_gen_or_i64(o
->out
, o
->out
, o
->in1
);
4171 static DisasJumpType
op_sll(DisasContext
*s
, DisasOps
*o
)
4173 tcg_gen_shl_i64(o
->out
, o
->in1
, o
->in2
);
4177 static DisasJumpType
op_sra(DisasContext
*s
, DisasOps
*o
)
4179 tcg_gen_sar_i64(o
->out
, o
->in1
, o
->in2
);
4183 static DisasJumpType
op_srl(DisasContext
*s
, DisasOps
*o
)
4185 tcg_gen_shr_i64(o
->out
, o
->in1
, o
->in2
);
4189 static DisasJumpType
op_sfpc(DisasContext
*s
, DisasOps
*o
)
4191 gen_helper_sfpc(cpu_env
, o
->in2
);
4195 static DisasJumpType
op_sfas(DisasContext
*s
, DisasOps
*o
)
4197 gen_helper_sfas(cpu_env
, o
->in2
);
4201 static DisasJumpType
op_srnm(DisasContext
*s
, DisasOps
*o
)
4203 /* Bits other than 62 and 63 are ignored. Bit 29 is set to zero. */
4204 tcg_gen_andi_i64(o
->addr1
, o
->addr1
, 0x3ull
);
4205 gen_helper_srnm(cpu_env
, o
->addr1
);
4209 static DisasJumpType
op_srnmb(DisasContext
*s
, DisasOps
*o
)
4211 /* Bits 0-55 are are ignored. */
4212 tcg_gen_andi_i64(o
->addr1
, o
->addr1
, 0xffull
);
4213 gen_helper_srnm(cpu_env
, o
->addr1
);
4217 static DisasJumpType
op_srnmt(DisasContext
*s
, DisasOps
*o
)
4219 TCGv_i64 tmp
= tcg_temp_new_i64();
4221 /* Bits other than 61-63 are ignored. */
4222 tcg_gen_andi_i64(o
->addr1
, o
->addr1
, 0x7ull
);
4224 /* No need to call a helper, we don't implement dfp */
4225 tcg_gen_ld32u_i64(tmp
, cpu_env
, offsetof(CPUS390XState
, fpc
));
4226 tcg_gen_deposit_i64(tmp
, tmp
, o
->addr1
, 4, 3);
4227 tcg_gen_st32_i64(tmp
, cpu_env
, offsetof(CPUS390XState
, fpc
));
4229 tcg_temp_free_i64(tmp
);
4233 static DisasJumpType
op_spm(DisasContext
*s
, DisasOps
*o
)
4235 tcg_gen_extrl_i64_i32(cc_op
, o
->in1
);
4236 tcg_gen_extract_i32(cc_op
, cc_op
, 28, 2);
4239 tcg_gen_shri_i64(o
->in1
, o
->in1
, 24);
4240 tcg_gen_deposit_i64(psw_mask
, psw_mask
, o
->in1
, PSW_SHIFT_MASK_PM
, 4);
4244 static DisasJumpType
op_ectg(DisasContext
*s
, DisasOps
*o
)
4246 int b1
= get_field(s
, b1
);
4247 int d1
= get_field(s
, d1
);
4248 int b2
= get_field(s
, b2
);
4249 int d2
= get_field(s
, d2
);
4250 int r3
= get_field(s
, r3
);
4251 TCGv_i64 tmp
= tcg_temp_new_i64();
4253 /* fetch all operands first */
4254 o
->in1
= tcg_temp_new_i64();
4255 tcg_gen_addi_i64(o
->in1
, regs
[b1
], d1
);
4256 o
->in2
= tcg_temp_new_i64();
4257 tcg_gen_addi_i64(o
->in2
, regs
[b2
], d2
);
4258 o
->addr1
= tcg_temp_new_i64();
4259 gen_addi_and_wrap_i64(s
, o
->addr1
, regs
[r3
], 0);
4261 /* load the third operand into r3 before modifying anything */
4262 tcg_gen_qemu_ld64(regs
[r3
], o
->addr1
, get_mem_index(s
));
4264 /* subtract CPU timer from first operand and store in GR0 */
4265 gen_helper_stpt(tmp
, cpu_env
);
4266 tcg_gen_sub_i64(regs
[0], o
->in1
, tmp
);
4268 /* store second operand in GR1 */
4269 tcg_gen_mov_i64(regs
[1], o
->in2
);
4271 tcg_temp_free_i64(tmp
);
4275 #ifndef CONFIG_USER_ONLY
4276 static DisasJumpType
op_spka(DisasContext
*s
, DisasOps
*o
)
4278 tcg_gen_shri_i64(o
->in2
, o
->in2
, 4);
4279 tcg_gen_deposit_i64(psw_mask
, psw_mask
, o
->in2
, PSW_SHIFT_KEY
, 4);
4283 static DisasJumpType
op_sske(DisasContext
*s
, DisasOps
*o
)
4285 gen_helper_sske(cpu_env
, o
->in1
, o
->in2
);
4289 static DisasJumpType
op_ssm(DisasContext
*s
, DisasOps
*o
)
4291 tcg_gen_deposit_i64(psw_mask
, psw_mask
, o
->in2
, 56, 8);
4292 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
4293 return DISAS_PC_STALE_NOCHAIN
;
4296 static DisasJumpType
op_stap(DisasContext
*s
, DisasOps
*o
)
4298 tcg_gen_ld32u_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, core_id
));
4303 static DisasJumpType
op_stck(DisasContext
*s
, DisasOps
*o
)
4305 gen_helper_stck(o
->out
, cpu_env
);
4306 /* ??? We don't implement clock states. */
4307 gen_op_movi_cc(s
, 0);
4311 static DisasJumpType
op_stcke(DisasContext
*s
, DisasOps
*o
)
4313 TCGv_i64 c1
= tcg_temp_new_i64();
4314 TCGv_i64 c2
= tcg_temp_new_i64();
4315 TCGv_i64 todpr
= tcg_temp_new_i64();
4316 gen_helper_stck(c1
, cpu_env
);
4317 /* 16 bit value store in an uint32_t (only valid bits set) */
4318 tcg_gen_ld32u_i64(todpr
, cpu_env
, offsetof(CPUS390XState
, todpr
));
4319 /* Shift the 64-bit value into its place as a zero-extended
4320 104-bit value. Note that "bit positions 64-103 are always
4321 non-zero so that they compare differently to STCK"; we set
4322 the least significant bit to 1. */
4323 tcg_gen_shli_i64(c2
, c1
, 56);
4324 tcg_gen_shri_i64(c1
, c1
, 8);
4325 tcg_gen_ori_i64(c2
, c2
, 0x10000);
4326 tcg_gen_or_i64(c2
, c2
, todpr
);
4327 tcg_gen_qemu_st64(c1
, o
->in2
, get_mem_index(s
));
4328 tcg_gen_addi_i64(o
->in2
, o
->in2
, 8);
4329 tcg_gen_qemu_st64(c2
, o
->in2
, get_mem_index(s
));
4330 tcg_temp_free_i64(c1
);
4331 tcg_temp_free_i64(c2
);
4332 tcg_temp_free_i64(todpr
);
4333 /* ??? We don't implement clock states. */
4334 gen_op_movi_cc(s
, 0);
4338 #ifndef CONFIG_USER_ONLY
4339 static DisasJumpType
op_sck(DisasContext
*s
, DisasOps
*o
)
4341 gen_helper_sck(cc_op
, cpu_env
, o
->in2
);
4346 static DisasJumpType
op_sckc(DisasContext
*s
, DisasOps
*o
)
4348 gen_helper_sckc(cpu_env
, o
->in2
);
4352 static DisasJumpType
op_sckpf(DisasContext
*s
, DisasOps
*o
)
4354 gen_helper_sckpf(cpu_env
, regs
[0]);
4358 static DisasJumpType
op_stckc(DisasContext
*s
, DisasOps
*o
)
4360 gen_helper_stckc(o
->out
, cpu_env
);
4364 static DisasJumpType
op_stctg(DisasContext
*s
, DisasOps
*o
)
4366 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4367 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
4368 gen_helper_stctg(cpu_env
, r1
, o
->in2
, r3
);
4369 tcg_temp_free_i32(r1
);
4370 tcg_temp_free_i32(r3
);
4374 static DisasJumpType
op_stctl(DisasContext
*s
, DisasOps
*o
)
4376 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4377 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
4378 gen_helper_stctl(cpu_env
, r1
, o
->in2
, r3
);
4379 tcg_temp_free_i32(r1
);
4380 tcg_temp_free_i32(r3
);
4384 static DisasJumpType
op_stidp(DisasContext
*s
, DisasOps
*o
)
4386 tcg_gen_ld_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, cpuid
));
4390 static DisasJumpType
op_spt(DisasContext
*s
, DisasOps
*o
)
4392 gen_helper_spt(cpu_env
, o
->in2
);
4396 static DisasJumpType
op_stfl(DisasContext
*s
, DisasOps
*o
)
4398 gen_helper_stfl(cpu_env
);
4402 static DisasJumpType
op_stpt(DisasContext
*s
, DisasOps
*o
)
4404 gen_helper_stpt(o
->out
, cpu_env
);
4408 static DisasJumpType
op_stsi(DisasContext
*s
, DisasOps
*o
)
4410 gen_helper_stsi(cc_op
, cpu_env
, o
->in2
, regs
[0], regs
[1]);
4415 static DisasJumpType
op_spx(DisasContext
*s
, DisasOps
*o
)
4417 gen_helper_spx(cpu_env
, o
->in2
);
4421 static DisasJumpType
op_xsch(DisasContext
*s
, DisasOps
*o
)
4423 gen_helper_xsch(cpu_env
, regs
[1]);
4428 static DisasJumpType
op_csch(DisasContext
*s
, DisasOps
*o
)
4430 gen_helper_csch(cpu_env
, regs
[1]);
4435 static DisasJumpType
op_hsch(DisasContext
*s
, DisasOps
*o
)
4437 gen_helper_hsch(cpu_env
, regs
[1]);
4442 static DisasJumpType
op_msch(DisasContext
*s
, DisasOps
*o
)
4444 gen_helper_msch(cpu_env
, regs
[1], o
->in2
);
4449 static DisasJumpType
op_rchp(DisasContext
*s
, DisasOps
*o
)
4451 gen_helper_rchp(cpu_env
, regs
[1]);
4456 static DisasJumpType
op_rsch(DisasContext
*s
, DisasOps
*o
)
4458 gen_helper_rsch(cpu_env
, regs
[1]);
4463 static DisasJumpType
op_sal(DisasContext
*s
, DisasOps
*o
)
4465 gen_helper_sal(cpu_env
, regs
[1]);
4469 static DisasJumpType
op_schm(DisasContext
*s
, DisasOps
*o
)
4471 gen_helper_schm(cpu_env
, regs
[1], regs
[2], o
->in2
);
4475 static DisasJumpType
op_siga(DisasContext
*s
, DisasOps
*o
)
4477 /* From KVM code: Not provided, set CC = 3 for subchannel not operational */
4478 gen_op_movi_cc(s
, 3);
4482 static DisasJumpType
op_stcps(DisasContext
*s
, DisasOps
*o
)
4484 /* The instruction is suppressed if not provided. */
4488 static DisasJumpType
op_ssch(DisasContext
*s
, DisasOps
*o
)
4490 gen_helper_ssch(cpu_env
, regs
[1], o
->in2
);
4495 static DisasJumpType
op_stsch(DisasContext
*s
, DisasOps
*o
)
4497 gen_helper_stsch(cpu_env
, regs
[1], o
->in2
);
4502 static DisasJumpType
op_stcrw(DisasContext
*s
, DisasOps
*o
)
4504 gen_helper_stcrw(cpu_env
, o
->in2
);
4509 static DisasJumpType
op_tpi(DisasContext
*s
, DisasOps
*o
)
4511 gen_helper_tpi(cc_op
, cpu_env
, o
->addr1
);
4516 static DisasJumpType
op_tsch(DisasContext
*s
, DisasOps
*o
)
4518 gen_helper_tsch(cpu_env
, regs
[1], o
->in2
);
4523 static DisasJumpType
op_chsc(DisasContext
*s
, DisasOps
*o
)
4525 gen_helper_chsc(cpu_env
, o
->in2
);
4530 static DisasJumpType
op_stpx(DisasContext
*s
, DisasOps
*o
)
4532 tcg_gen_ld_i64(o
->out
, cpu_env
, offsetof(CPUS390XState
, psa
));
4533 tcg_gen_andi_i64(o
->out
, o
->out
, 0x7fffe000);
4537 static DisasJumpType
op_stnosm(DisasContext
*s
, DisasOps
*o
)
4539 uint64_t i2
= get_field(s
, i2
);
4542 /* It is important to do what the instruction name says: STORE THEN.
4543 If we let the output hook perform the store then if we fault and
4544 restart, we'll have the wrong SYSTEM MASK in place. */
4545 t
= tcg_temp_new_i64();
4546 tcg_gen_shri_i64(t
, psw_mask
, 56);
4547 tcg_gen_qemu_st8(t
, o
->addr1
, get_mem_index(s
));
4548 tcg_temp_free_i64(t
);
4550 if (s
->fields
.op
== 0xac) {
4551 tcg_gen_andi_i64(psw_mask
, psw_mask
,
4552 (i2
<< 56) | 0x00ffffffffffffffull
);
4554 tcg_gen_ori_i64(psw_mask
, psw_mask
, i2
<< 56);
4557 /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
4558 return DISAS_PC_STALE_NOCHAIN
;
4561 static DisasJumpType
op_stura(DisasContext
*s
, DisasOps
*o
)
4563 tcg_gen_qemu_st_tl(o
->in1
, o
->in2
, MMU_REAL_IDX
, s
->insn
->data
);
4565 if (s
->base
.tb
->flags
& FLAG_MASK_PER
) {
4567 gen_helper_per_store_real(cpu_env
);
4573 static DisasJumpType
op_stfle(DisasContext
*s
, DisasOps
*o
)
4575 gen_helper_stfle(cc_op
, cpu_env
, o
->in2
);
4580 static DisasJumpType
op_st8(DisasContext
*s
, DisasOps
*o
)
4582 tcg_gen_qemu_st8(o
->in1
, o
->in2
, get_mem_index(s
));
4586 static DisasJumpType
op_st16(DisasContext
*s
, DisasOps
*o
)
4588 tcg_gen_qemu_st16(o
->in1
, o
->in2
, get_mem_index(s
));
4592 static DisasJumpType
op_st32(DisasContext
*s
, DisasOps
*o
)
4594 tcg_gen_qemu_st32(o
->in1
, o
->in2
, get_mem_index(s
));
4598 static DisasJumpType
op_st64(DisasContext
*s
, DisasOps
*o
)
4600 tcg_gen_qemu_st64(o
->in1
, o
->in2
, get_mem_index(s
));
4604 static DisasJumpType
op_stam(DisasContext
*s
, DisasOps
*o
)
4606 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4607 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
4608 gen_helper_stam(cpu_env
, r1
, o
->in2
, r3
);
4609 tcg_temp_free_i32(r1
);
4610 tcg_temp_free_i32(r3
);
4614 static DisasJumpType
op_stcm(DisasContext
*s
, DisasOps
*o
)
4616 int m3
= get_field(s
, m3
);
4617 int pos
, base
= s
->insn
->data
;
4618 TCGv_i64 tmp
= tcg_temp_new_i64();
4620 pos
= base
+ ctz32(m3
) * 8;
4623 /* Effectively a 32-bit store. */
4624 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
4625 tcg_gen_qemu_st32(tmp
, o
->in2
, get_mem_index(s
));
4631 /* Effectively a 16-bit store. */
4632 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
4633 tcg_gen_qemu_st16(tmp
, o
->in2
, get_mem_index(s
));
4640 /* Effectively an 8-bit store. */
4641 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
4642 tcg_gen_qemu_st8(tmp
, o
->in2
, get_mem_index(s
));
4646 /* This is going to be a sequence of shifts and stores. */
4647 pos
= base
+ 32 - 8;
4650 tcg_gen_shri_i64(tmp
, o
->in1
, pos
);
4651 tcg_gen_qemu_st8(tmp
, o
->in2
, get_mem_index(s
));
4652 tcg_gen_addi_i64(o
->in2
, o
->in2
, 1);
4654 m3
= (m3
<< 1) & 0xf;
4659 tcg_temp_free_i64(tmp
);
4663 static DisasJumpType
op_stm(DisasContext
*s
, DisasOps
*o
)
4665 int r1
= get_field(s
, r1
);
4666 int r3
= get_field(s
, r3
);
4667 int size
= s
->insn
->data
;
4668 TCGv_i64 tsize
= tcg_const_i64(size
);
4672 tcg_gen_qemu_st64(regs
[r1
], o
->in2
, get_mem_index(s
));
4674 tcg_gen_qemu_st32(regs
[r1
], o
->in2
, get_mem_index(s
));
4679 tcg_gen_add_i64(o
->in2
, o
->in2
, tsize
);
4683 tcg_temp_free_i64(tsize
);
4687 static DisasJumpType
op_stmh(DisasContext
*s
, DisasOps
*o
)
4689 int r1
= get_field(s
, r1
);
4690 int r3
= get_field(s
, r3
);
4691 TCGv_i64 t
= tcg_temp_new_i64();
4692 TCGv_i64 t4
= tcg_const_i64(4);
4693 TCGv_i64 t32
= tcg_const_i64(32);
4696 tcg_gen_shl_i64(t
, regs
[r1
], t32
);
4697 tcg_gen_qemu_st32(t
, o
->in2
, get_mem_index(s
));
4701 tcg_gen_add_i64(o
->in2
, o
->in2
, t4
);
4705 tcg_temp_free_i64(t
);
4706 tcg_temp_free_i64(t4
);
4707 tcg_temp_free_i64(t32
);
4711 static DisasJumpType
op_stpq(DisasContext
*s
, DisasOps
*o
)
4713 if (!(tb_cflags(s
->base
.tb
) & CF_PARALLEL
)) {
4714 gen_helper_stpq(cpu_env
, o
->in2
, o
->out2
, o
->out
);
4715 } else if (HAVE_ATOMIC128
) {
4716 gen_helper_stpq_parallel(cpu_env
, o
->in2
, o
->out2
, o
->out
);
4718 gen_helper_exit_atomic(cpu_env
);
4719 return DISAS_NORETURN
;
4724 static DisasJumpType
op_srst(DisasContext
*s
, DisasOps
*o
)
4726 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4727 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
4729 gen_helper_srst(cpu_env
, r1
, r2
);
4731 tcg_temp_free_i32(r1
);
4732 tcg_temp_free_i32(r2
);
4737 static DisasJumpType
op_srstu(DisasContext
*s
, DisasOps
*o
)
4739 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4740 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
4742 gen_helper_srstu(cpu_env
, r1
, r2
);
4744 tcg_temp_free_i32(r1
);
4745 tcg_temp_free_i32(r2
);
4750 static DisasJumpType
op_sub(DisasContext
*s
, DisasOps
*o
)
4752 tcg_gen_sub_i64(o
->out
, o
->in1
, o
->in2
);
4756 static DisasJumpType
op_subu64(DisasContext
*s
, DisasOps
*o
)
4758 tcg_gen_movi_i64(cc_src
, 0);
4759 tcg_gen_sub2_i64(o
->out
, cc_src
, o
->in1
, cc_src
, o
->in2
, cc_src
);
4763 /* Compute borrow (0, -1) into cc_src. */
4764 static void compute_borrow(DisasContext
*s
)
4768 /* The borrow value is already in cc_src (0,-1). */
4774 /* The carry flag is the msb of CC; compute into cc_src. */
4775 tcg_gen_extu_i32_i64(cc_src
, cc_op
);
4776 tcg_gen_shri_i64(cc_src
, cc_src
, 1);
4779 /* Convert carry (1,0) to borrow (0,-1). */
4780 tcg_gen_subi_i64(cc_src
, cc_src
, 1);
4785 static DisasJumpType
op_subb32(DisasContext
*s
, DisasOps
*o
)
4789 /* Borrow is {0, -1}, so add to subtract. */
4790 tcg_gen_add_i64(o
->out
, o
->in1
, cc_src
);
4791 tcg_gen_sub_i64(o
->out
, o
->out
, o
->in2
);
4795 static DisasJumpType
op_subb64(DisasContext
*s
, DisasOps
*o
)
4800 * Borrow is {0, -1}, so add to subtract; replicate the
4801 * borrow input to produce 128-bit -1 for the addition.
4803 TCGv_i64 zero
= tcg_const_i64(0);
4804 tcg_gen_add2_i64(o
->out
, cc_src
, o
->in1
, zero
, cc_src
, cc_src
);
4805 tcg_gen_sub2_i64(o
->out
, cc_src
, o
->out
, cc_src
, o
->in2
, zero
);
4806 tcg_temp_free_i64(zero
);
4811 static DisasJumpType
op_svc(DisasContext
*s
, DisasOps
*o
)
4818 t
= tcg_const_i32(get_field(s
, i1
) & 0xff);
4819 tcg_gen_st_i32(t
, cpu_env
, offsetof(CPUS390XState
, int_svc_code
));
4820 tcg_temp_free_i32(t
);
4822 t
= tcg_const_i32(s
->ilen
);
4823 tcg_gen_st_i32(t
, cpu_env
, offsetof(CPUS390XState
, int_svc_ilen
));
4824 tcg_temp_free_i32(t
);
4826 gen_exception(EXCP_SVC
);
4827 return DISAS_NORETURN
;
4830 static DisasJumpType
op_tam(DisasContext
*s
, DisasOps
*o
)
4834 cc
|= (s
->base
.tb
->flags
& FLAG_MASK_64
) ? 2 : 0;
4835 cc
|= (s
->base
.tb
->flags
& FLAG_MASK_32
) ? 1 : 0;
4836 gen_op_movi_cc(s
, cc
);
4840 static DisasJumpType
op_tceb(DisasContext
*s
, DisasOps
*o
)
4842 gen_helper_tceb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
4847 static DisasJumpType
op_tcdb(DisasContext
*s
, DisasOps
*o
)
4849 gen_helper_tcdb(cc_op
, cpu_env
, o
->in1
, o
->in2
);
4854 static DisasJumpType
op_tcxb(DisasContext
*s
, DisasOps
*o
)
4856 gen_helper_tcxb(cc_op
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
4861 #ifndef CONFIG_USER_ONLY
4863 static DisasJumpType
op_testblock(DisasContext
*s
, DisasOps
*o
)
4865 gen_helper_testblock(cc_op
, cpu_env
, o
->in2
);
4870 static DisasJumpType
op_tprot(DisasContext
*s
, DisasOps
*o
)
4872 gen_helper_tprot(cc_op
, cpu_env
, o
->addr1
, o
->in2
);
4879 static DisasJumpType
op_tp(DisasContext
*s
, DisasOps
*o
)
4881 TCGv_i32 l1
= tcg_const_i32(get_field(s
, l1
) + 1);
4882 gen_helper_tp(cc_op
, cpu_env
, o
->addr1
, l1
);
4883 tcg_temp_free_i32(l1
);
4888 static DisasJumpType
op_tr(DisasContext
*s
, DisasOps
*o
)
4890 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
4891 gen_helper_tr(cpu_env
, l
, o
->addr1
, o
->in2
);
4892 tcg_temp_free_i32(l
);
4897 static DisasJumpType
op_tre(DisasContext
*s
, DisasOps
*o
)
4899 gen_helper_tre(o
->out
, cpu_env
, o
->out
, o
->out2
, o
->in2
);
4900 return_low128(o
->out2
);
4905 static DisasJumpType
op_trt(DisasContext
*s
, DisasOps
*o
)
4907 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
4908 gen_helper_trt(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
4909 tcg_temp_free_i32(l
);
4914 static DisasJumpType
op_trtr(DisasContext
*s
, DisasOps
*o
)
4916 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
4917 gen_helper_trtr(cc_op
, cpu_env
, l
, o
->addr1
, o
->in2
);
4918 tcg_temp_free_i32(l
);
4923 static DisasJumpType
op_trXX(DisasContext
*s
, DisasOps
*o
)
4925 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
4926 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
4927 TCGv_i32 sizes
= tcg_const_i32(s
->insn
->opc
& 3);
4928 TCGv_i32 tst
= tcg_temp_new_i32();
4929 int m3
= get_field(s
, m3
);
4931 if (!s390_has_feat(S390_FEAT_ETF2_ENH
)) {
4935 tcg_gen_movi_i32(tst
, -1);
4937 tcg_gen_extrl_i64_i32(tst
, regs
[0]);
4938 if (s
->insn
->opc
& 3) {
4939 tcg_gen_ext8u_i32(tst
, tst
);
4941 tcg_gen_ext16u_i32(tst
, tst
);
4944 gen_helper_trXX(cc_op
, cpu_env
, r1
, r2
, tst
, sizes
);
4946 tcg_temp_free_i32(r1
);
4947 tcg_temp_free_i32(r2
);
4948 tcg_temp_free_i32(sizes
);
4949 tcg_temp_free_i32(tst
);
4954 static DisasJumpType
op_ts(DisasContext
*s
, DisasOps
*o
)
4956 TCGv_i32 t1
= tcg_const_i32(0xff);
4957 tcg_gen_atomic_xchg_i32(t1
, o
->in2
, t1
, get_mem_index(s
), MO_UB
);
4958 tcg_gen_extract_i32(cc_op
, t1
, 7, 1);
4959 tcg_temp_free_i32(t1
);
4964 static DisasJumpType
op_unpk(DisasContext
*s
, DisasOps
*o
)
4966 TCGv_i32 l
= tcg_const_i32(get_field(s
, l1
));
4967 gen_helper_unpk(cpu_env
, l
, o
->addr1
, o
->in2
);
4968 tcg_temp_free_i32(l
);
4972 static DisasJumpType
op_unpka(DisasContext
*s
, DisasOps
*o
)
4974 int l1
= get_field(s
, l1
) + 1;
4977 /* The length must not exceed 32 bytes. */
4979 gen_program_exception(s
, PGM_SPECIFICATION
);
4980 return DISAS_NORETURN
;
4982 l
= tcg_const_i32(l1
);
4983 gen_helper_unpka(cc_op
, cpu_env
, o
->addr1
, l
, o
->in2
);
4984 tcg_temp_free_i32(l
);
4989 static DisasJumpType
op_unpku(DisasContext
*s
, DisasOps
*o
)
4991 int l1
= get_field(s
, l1
) + 1;
4994 /* The length must be even and should not exceed 64 bytes. */
4995 if ((l1
& 1) || (l1
> 64)) {
4996 gen_program_exception(s
, PGM_SPECIFICATION
);
4997 return DISAS_NORETURN
;
4999 l
= tcg_const_i32(l1
);
5000 gen_helper_unpku(cc_op
, cpu_env
, o
->addr1
, l
, o
->in2
);
5001 tcg_temp_free_i32(l
);
5007 static DisasJumpType
op_xc(DisasContext
*s
, DisasOps
*o
)
5009 int d1
= get_field(s
, d1
);
5010 int d2
= get_field(s
, d2
);
5011 int b1
= get_field(s
, b1
);
5012 int b2
= get_field(s
, b2
);
5013 int l
= get_field(s
, l1
);
5016 o
->addr1
= get_address(s
, 0, b1
, d1
);
5018 /* If the addresses are identical, this is a store/memset of zero. */
5019 if (b1
== b2
&& d1
== d2
&& (l
+ 1) <= 32) {
5020 o
->in2
= tcg_const_i64(0);
5024 tcg_gen_qemu_st64(o
->in2
, o
->addr1
, get_mem_index(s
));
5027 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 8);
5031 tcg_gen_qemu_st32(o
->in2
, o
->addr1
, get_mem_index(s
));
5034 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 4);
5038 tcg_gen_qemu_st16(o
->in2
, o
->addr1
, get_mem_index(s
));
5041 tcg_gen_addi_i64(o
->addr1
, o
->addr1
, 2);
5045 tcg_gen_qemu_st8(o
->in2
, o
->addr1
, get_mem_index(s
));
5047 gen_op_movi_cc(s
, 0);
5051 /* But in general we'll defer to a helper. */
5052 o
->in2
= get_address(s
, 0, b2
, d2
);
5053 t32
= tcg_const_i32(l
);
5054 gen_helper_xc(cc_op
, cpu_env
, t32
, o
->addr1
, o
->in2
);
5055 tcg_temp_free_i32(t32
);
5060 static DisasJumpType
op_xor(DisasContext
*s
, DisasOps
*o
)
5062 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
5066 static DisasJumpType
op_xori(DisasContext
*s
, DisasOps
*o
)
5068 int shift
= s
->insn
->data
& 0xff;
5069 int size
= s
->insn
->data
>> 8;
5070 uint64_t mask
= ((1ull << size
) - 1) << shift
;
5073 tcg_gen_shli_i64(o
->in2
, o
->in2
, shift
);
5074 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
5076 /* Produce the CC from only the bits manipulated. */
5077 tcg_gen_andi_i64(cc_dst
, o
->out
, mask
);
5078 set_cc_nz_u64(s
, cc_dst
);
5082 static DisasJumpType
op_xi(DisasContext
*s
, DisasOps
*o
)
5084 o
->in1
= tcg_temp_new_i64();
5086 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
5087 tcg_gen_qemu_ld_tl(o
->in1
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
5089 /* Perform the atomic operation in memory. */
5090 tcg_gen_atomic_fetch_xor_i64(o
->in1
, o
->addr1
, o
->in2
, get_mem_index(s
),
5094 /* Recompute also for atomic case: needed for setting CC. */
5095 tcg_gen_xor_i64(o
->out
, o
->in1
, o
->in2
);
5097 if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2
)) {
5098 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), s
->insn
->data
);
5103 static DisasJumpType
op_zero(DisasContext
*s
, DisasOps
*o
)
5105 o
->out
= tcg_const_i64(0);
5109 static DisasJumpType
op_zero2(DisasContext
*s
, DisasOps
*o
)
5111 o
->out
= tcg_const_i64(0);
5117 #ifndef CONFIG_USER_ONLY
5118 static DisasJumpType
op_clp(DisasContext
*s
, DisasOps
*o
)
5120 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
5122 gen_helper_clp(cpu_env
, r2
);
5123 tcg_temp_free_i32(r2
);
5128 static DisasJumpType
op_pcilg(DisasContext
*s
, DisasOps
*o
)
5130 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5131 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
5133 gen_helper_pcilg(cpu_env
, r1
, r2
);
5134 tcg_temp_free_i32(r1
);
5135 tcg_temp_free_i32(r2
);
5140 static DisasJumpType
op_pcistg(DisasContext
*s
, DisasOps
*o
)
5142 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5143 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
5145 gen_helper_pcistg(cpu_env
, r1
, r2
);
5146 tcg_temp_free_i32(r1
);
5147 tcg_temp_free_i32(r2
);
5152 static DisasJumpType
op_stpcifc(DisasContext
*s
, DisasOps
*o
)
5154 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5155 TCGv_i32 ar
= tcg_const_i32(get_field(s
, b2
));
5157 gen_helper_stpcifc(cpu_env
, r1
, o
->addr1
, ar
);
5158 tcg_temp_free_i32(ar
);
5159 tcg_temp_free_i32(r1
);
5164 static DisasJumpType
op_sic(DisasContext
*s
, DisasOps
*o
)
5166 gen_helper_sic(cpu_env
, o
->in1
, o
->in2
);
5170 static DisasJumpType
op_rpcit(DisasContext
*s
, DisasOps
*o
)
5172 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5173 TCGv_i32 r2
= tcg_const_i32(get_field(s
, r2
));
5175 gen_helper_rpcit(cpu_env
, r1
, r2
);
5176 tcg_temp_free_i32(r1
);
5177 tcg_temp_free_i32(r2
);
5182 static DisasJumpType
op_pcistb(DisasContext
*s
, DisasOps
*o
)
5184 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5185 TCGv_i32 r3
= tcg_const_i32(get_field(s
, r3
));
5186 TCGv_i32 ar
= tcg_const_i32(get_field(s
, b2
));
5188 gen_helper_pcistb(cpu_env
, r1
, r3
, o
->addr1
, ar
);
5189 tcg_temp_free_i32(ar
);
5190 tcg_temp_free_i32(r1
);
5191 tcg_temp_free_i32(r3
);
5196 static DisasJumpType
op_mpcifc(DisasContext
*s
, DisasOps
*o
)
5198 TCGv_i32 r1
= tcg_const_i32(get_field(s
, r1
));
5199 TCGv_i32 ar
= tcg_const_i32(get_field(s
, b2
));
5201 gen_helper_mpcifc(cpu_env
, r1
, o
->addr1
, ar
);
5202 tcg_temp_free_i32(ar
);
5203 tcg_temp_free_i32(r1
);
5209 #include "translate_vx.c.inc"
5211 /* ====================================================================== */
5212 /* The "Cc OUTput" generators. Given the generated output (and in some cases
5213 the original inputs), update the various cc data structures in order to
5214 be able to compute the new condition code. */
5216 static void cout_abs32(DisasContext
*s
, DisasOps
*o
)
5218 gen_op_update1_cc_i64(s
, CC_OP_ABS_32
, o
->out
);
5221 static void cout_abs64(DisasContext
*s
, DisasOps
*o
)
5223 gen_op_update1_cc_i64(s
, CC_OP_ABS_64
, o
->out
);
5226 static void cout_adds32(DisasContext
*s
, DisasOps
*o
)
5228 gen_op_update3_cc_i64(s
, CC_OP_ADD_32
, o
->in1
, o
->in2
, o
->out
);
5231 static void cout_adds64(DisasContext
*s
, DisasOps
*o
)
5233 gen_op_update3_cc_i64(s
, CC_OP_ADD_64
, o
->in1
, o
->in2
, o
->out
);
5236 static void cout_addu32(DisasContext
*s
, DisasOps
*o
)
5238 tcg_gen_shri_i64(cc_src
, o
->out
, 32);
5239 tcg_gen_ext32u_i64(cc_dst
, o
->out
);
5240 gen_op_update2_cc_i64(s
, CC_OP_ADDU
, cc_src
, cc_dst
);
5243 static void cout_addu64(DisasContext
*s
, DisasOps
*o
)
5245 gen_op_update2_cc_i64(s
, CC_OP_ADDU
, cc_src
, o
->out
);
5248 static void cout_cmps32(DisasContext
*s
, DisasOps
*o
)
5250 gen_op_update2_cc_i64(s
, CC_OP_LTGT_32
, o
->in1
, o
->in2
);
5253 static void cout_cmps64(DisasContext
*s
, DisasOps
*o
)
5255 gen_op_update2_cc_i64(s
, CC_OP_LTGT_64
, o
->in1
, o
->in2
);
5258 static void cout_cmpu32(DisasContext
*s
, DisasOps
*o
)
5260 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_32
, o
->in1
, o
->in2
);
5263 static void cout_cmpu64(DisasContext
*s
, DisasOps
*o
)
5265 gen_op_update2_cc_i64(s
, CC_OP_LTUGTU_64
, o
->in1
, o
->in2
);
5268 static void cout_f32(DisasContext
*s
, DisasOps
*o
)
5270 gen_op_update1_cc_i64(s
, CC_OP_NZ_F32
, o
->out
);
5273 static void cout_f64(DisasContext
*s
, DisasOps
*o
)
5275 gen_op_update1_cc_i64(s
, CC_OP_NZ_F64
, o
->out
);
5278 static void cout_f128(DisasContext
*s
, DisasOps
*o
)
5280 gen_op_update2_cc_i64(s
, CC_OP_NZ_F128
, o
->out
, o
->out2
);
5283 static void cout_nabs32(DisasContext
*s
, DisasOps
*o
)
5285 gen_op_update1_cc_i64(s
, CC_OP_NABS_32
, o
->out
);
5288 static void cout_nabs64(DisasContext
*s
, DisasOps
*o
)
5290 gen_op_update1_cc_i64(s
, CC_OP_NABS_64
, o
->out
);
5293 static void cout_neg32(DisasContext
*s
, DisasOps
*o
)
5295 gen_op_update1_cc_i64(s
, CC_OP_COMP_32
, o
->out
);
5298 static void cout_neg64(DisasContext
*s
, DisasOps
*o
)
5300 gen_op_update1_cc_i64(s
, CC_OP_COMP_64
, o
->out
);
5303 static void cout_nz32(DisasContext
*s
, DisasOps
*o
)
5305 tcg_gen_ext32u_i64(cc_dst
, o
->out
);
5306 gen_op_update1_cc_i64(s
, CC_OP_NZ
, cc_dst
);
5309 static void cout_nz64(DisasContext
*s
, DisasOps
*o
)
5311 gen_op_update1_cc_i64(s
, CC_OP_NZ
, o
->out
);
5314 static void cout_s32(DisasContext
*s
, DisasOps
*o
)
5316 gen_op_update1_cc_i64(s
, CC_OP_LTGT0_32
, o
->out
);
5319 static void cout_s64(DisasContext
*s
, DisasOps
*o
)
5321 gen_op_update1_cc_i64(s
, CC_OP_LTGT0_64
, o
->out
);
5324 static void cout_subs32(DisasContext
*s
, DisasOps
*o
)
5326 gen_op_update3_cc_i64(s
, CC_OP_SUB_32
, o
->in1
, o
->in2
, o
->out
);
5329 static void cout_subs64(DisasContext
*s
, DisasOps
*o
)
5331 gen_op_update3_cc_i64(s
, CC_OP_SUB_64
, o
->in1
, o
->in2
, o
->out
);
5334 static void cout_subu32(DisasContext
*s
, DisasOps
*o
)
5336 tcg_gen_sari_i64(cc_src
, o
->out
, 32);
5337 tcg_gen_ext32u_i64(cc_dst
, o
->out
);
5338 gen_op_update2_cc_i64(s
, CC_OP_SUBU
, cc_src
, cc_dst
);
5341 static void cout_subu64(DisasContext
*s
, DisasOps
*o
)
5343 gen_op_update2_cc_i64(s
, CC_OP_SUBU
, cc_src
, o
->out
);
5346 static void cout_tm32(DisasContext
*s
, DisasOps
*o
)
5348 gen_op_update2_cc_i64(s
, CC_OP_TM_32
, o
->in1
, o
->in2
);
5351 static void cout_tm64(DisasContext
*s
, DisasOps
*o
)
5353 gen_op_update2_cc_i64(s
, CC_OP_TM_64
, o
->in1
, o
->in2
);
5356 static void cout_muls32(DisasContext
*s
, DisasOps
*o
)
5358 gen_op_update1_cc_i64(s
, CC_OP_MULS_32
, o
->out
);
5361 static void cout_muls64(DisasContext
*s
, DisasOps
*o
)
5363 /* out contains "high" part, out2 contains "low" part of 128 bit result */
5364 gen_op_update2_cc_i64(s
, CC_OP_MULS_64
, o
->out
, o
->out2
);
5367 /* ====================================================================== */
5368 /* The "PREParation" generators. These initialize the DisasOps.OUT fields
5369 with the TCG register to which we will write. Used in combination with
5370 the "wout" generators, in some cases we need a new temporary, and in
5371 some cases we can write to a TCG global. */
5373 static void prep_new(DisasContext
*s
, DisasOps
*o
)
5375 o
->out
= tcg_temp_new_i64();
5377 #define SPEC_prep_new 0
5379 static void prep_new_P(DisasContext
*s
, DisasOps
*o
)
5381 o
->out
= tcg_temp_new_i64();
5382 o
->out2
= tcg_temp_new_i64();
5384 #define SPEC_prep_new_P 0
5386 static void prep_r1(DisasContext
*s
, DisasOps
*o
)
5388 o
->out
= regs
[get_field(s
, r1
)];
5391 #define SPEC_prep_r1 0
5393 static void prep_r1_P(DisasContext
*s
, DisasOps
*o
)
5395 int r1
= get_field(s
, r1
);
5397 o
->out2
= regs
[r1
+ 1];
5398 o
->g_out
= o
->g_out2
= true;
5400 #define SPEC_prep_r1_P SPEC_r1_even
5402 /* Whenever we need x1 in addition to other inputs, we'll load it to out/out2 */
5403 static void prep_x1(DisasContext
*s
, DisasOps
*o
)
5405 o
->out
= load_freg(get_field(s
, r1
));
5406 o
->out2
= load_freg(get_field(s
, r1
) + 2);
5408 #define SPEC_prep_x1 SPEC_r1_f128
5410 /* ====================================================================== */
5411 /* The "Write OUTput" generators. These generally perform some non-trivial
5412 copy of data to TCG globals, or to main memory. The trivial cases are
5413 generally handled by having a "prep" generator install the TCG global
5414 as the destination of the operation. */
5416 static void wout_r1(DisasContext
*s
, DisasOps
*o
)
5418 store_reg(get_field(s
, r1
), o
->out
);
5420 #define SPEC_wout_r1 0
5422 static void wout_out2_r1(DisasContext
*s
, DisasOps
*o
)
5424 store_reg(get_field(s
, r1
), o
->out2
);
5426 #define SPEC_wout_out2_r1 0
5428 static void wout_r1_8(DisasContext
*s
, DisasOps
*o
)
5430 int r1
= get_field(s
, r1
);
5431 tcg_gen_deposit_i64(regs
[r1
], regs
[r1
], o
->out
, 0, 8);
5433 #define SPEC_wout_r1_8 0
5435 static void wout_r1_16(DisasContext
*s
, DisasOps
*o
)
5437 int r1
= get_field(s
, r1
);
5438 tcg_gen_deposit_i64(regs
[r1
], regs
[r1
], o
->out
, 0, 16);
5440 #define SPEC_wout_r1_16 0
5442 static void wout_r1_32(DisasContext
*s
, DisasOps
*o
)
5444 store_reg32_i64(get_field(s
, r1
), o
->out
);
5446 #define SPEC_wout_r1_32 0
5448 static void wout_r1_32h(DisasContext
*s
, DisasOps
*o
)
5450 store_reg32h_i64(get_field(s
, r1
), o
->out
);
5452 #define SPEC_wout_r1_32h 0
5454 static void wout_r1_P32(DisasContext
*s
, DisasOps
*o
)
5456 int r1
= get_field(s
, r1
);
5457 store_reg32_i64(r1
, o
->out
);
5458 store_reg32_i64(r1
+ 1, o
->out2
);
5460 #define SPEC_wout_r1_P32 SPEC_r1_even
5462 static void wout_r1_D32(DisasContext
*s
, DisasOps
*o
)
5464 int r1
= get_field(s
, r1
);
5465 TCGv_i64 t
= tcg_temp_new_i64();
5466 store_reg32_i64(r1
+ 1, o
->out
);
5467 tcg_gen_shri_i64(t
, o
->out
, 32);
5468 store_reg32_i64(r1
, t
);
5469 tcg_temp_free_i64(t
);
5471 #define SPEC_wout_r1_D32 SPEC_r1_even
5473 static void wout_r3_P32(DisasContext
*s
, DisasOps
*o
)
5475 int r3
= get_field(s
, r3
);
5476 store_reg32_i64(r3
, o
->out
);
5477 store_reg32_i64(r3
+ 1, o
->out2
);
5479 #define SPEC_wout_r3_P32 SPEC_r3_even
5481 static void wout_r3_P64(DisasContext
*s
, DisasOps
*o
)
5483 int r3
= get_field(s
, r3
);
5484 store_reg(r3
, o
->out
);
5485 store_reg(r3
+ 1, o
->out2
);
5487 #define SPEC_wout_r3_P64 SPEC_r3_even
5489 static void wout_e1(DisasContext
*s
, DisasOps
*o
)
5491 store_freg32_i64(get_field(s
, r1
), o
->out
);
5493 #define SPEC_wout_e1 0
5495 static void wout_f1(DisasContext
*s
, DisasOps
*o
)
5497 store_freg(get_field(s
, r1
), o
->out
);
5499 #define SPEC_wout_f1 0
5501 static void wout_x1(DisasContext
*s
, DisasOps
*o
)
5503 int f1
= get_field(s
, r1
);
5504 store_freg(f1
, o
->out
);
5505 store_freg(f1
+ 2, o
->out2
);
5507 #define SPEC_wout_x1 SPEC_r1_f128
5509 static void wout_cond_r1r2_32(DisasContext
*s
, DisasOps
*o
)
5511 if (get_field(s
, r1
) != get_field(s
, r2
)) {
5512 store_reg32_i64(get_field(s
, r1
), o
->out
);
5515 #define SPEC_wout_cond_r1r2_32 0
5517 static void wout_cond_e1e2(DisasContext
*s
, DisasOps
*o
)
5519 if (get_field(s
, r1
) != get_field(s
, r2
)) {
5520 store_freg32_i64(get_field(s
, r1
), o
->out
);
5523 #define SPEC_wout_cond_e1e2 0
5525 static void wout_m1_8(DisasContext
*s
, DisasOps
*o
)
5527 tcg_gen_qemu_st8(o
->out
, o
->addr1
, get_mem_index(s
));
5529 #define SPEC_wout_m1_8 0
5531 static void wout_m1_16(DisasContext
*s
, DisasOps
*o
)
5533 tcg_gen_qemu_st16(o
->out
, o
->addr1
, get_mem_index(s
));
5535 #define SPEC_wout_m1_16 0
5537 #ifndef CONFIG_USER_ONLY
5538 static void wout_m1_16a(DisasContext
*s
, DisasOps
*o
)
5540 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), MO_TEUW
| MO_ALIGN
);
5542 #define SPEC_wout_m1_16a 0
5545 static void wout_m1_32(DisasContext
*s
, DisasOps
*o
)
5547 tcg_gen_qemu_st32(o
->out
, o
->addr1
, get_mem_index(s
));
5549 #define SPEC_wout_m1_32 0
5551 #ifndef CONFIG_USER_ONLY
5552 static void wout_m1_32a(DisasContext
*s
, DisasOps
*o
)
5554 tcg_gen_qemu_st_tl(o
->out
, o
->addr1
, get_mem_index(s
), MO_TEUL
| MO_ALIGN
);
5556 #define SPEC_wout_m1_32a 0
5559 static void wout_m1_64(DisasContext
*s
, DisasOps
*o
)
5561 tcg_gen_qemu_st64(o
->out
, o
->addr1
, get_mem_index(s
));
5563 #define SPEC_wout_m1_64 0
5565 #ifndef CONFIG_USER_ONLY
5566 static void wout_m1_64a(DisasContext
*s
, DisasOps
*o
)
5568 tcg_gen_qemu_st_i64(o
->out
, o
->addr1
, get_mem_index(s
), MO_TEUQ
| MO_ALIGN
);
5570 #define SPEC_wout_m1_64a 0
5573 static void wout_m2_32(DisasContext
*s
, DisasOps
*o
)
5575 tcg_gen_qemu_st32(o
->out
, o
->in2
, get_mem_index(s
));
5577 #define SPEC_wout_m2_32 0
5579 static void wout_in2_r1(DisasContext
*s
, DisasOps
*o
)
5581 store_reg(get_field(s
, r1
), o
->in2
);
5583 #define SPEC_wout_in2_r1 0
5585 static void wout_in2_r1_32(DisasContext
*s
, DisasOps
*o
)
5587 store_reg32_i64(get_field(s
, r1
), o
->in2
);
5589 #define SPEC_wout_in2_r1_32 0
5591 /* ====================================================================== */
5592 /* The "INput 1" generators. These load the first operand to an insn. */
5594 static void in1_r1(DisasContext
*s
, DisasOps
*o
)
5596 o
->in1
= load_reg(get_field(s
, r1
));
5598 #define SPEC_in1_r1 0
5600 static void in1_r1_o(DisasContext
*s
, DisasOps
*o
)
5602 o
->in1
= regs
[get_field(s
, r1
)];
5605 #define SPEC_in1_r1_o 0
5607 static void in1_r1_32s(DisasContext
*s
, DisasOps
*o
)
5609 o
->in1
= tcg_temp_new_i64();
5610 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(s
, r1
)]);
5612 #define SPEC_in1_r1_32s 0
5614 static void in1_r1_32u(DisasContext
*s
, DisasOps
*o
)
5616 o
->in1
= tcg_temp_new_i64();
5617 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(s
, r1
)]);
5619 #define SPEC_in1_r1_32u 0
5621 static void in1_r1_sr32(DisasContext
*s
, DisasOps
*o
)
5623 o
->in1
= tcg_temp_new_i64();
5624 tcg_gen_shri_i64(o
->in1
, regs
[get_field(s
, r1
)], 32);
5626 #define SPEC_in1_r1_sr32 0
5628 static void in1_r1p1(DisasContext
*s
, DisasOps
*o
)
5630 o
->in1
= load_reg(get_field(s
, r1
) + 1);
5632 #define SPEC_in1_r1p1 SPEC_r1_even
5634 static void in1_r1p1_o(DisasContext
*s
, DisasOps
*o
)
5636 o
->in1
= regs
[get_field(s
, r1
) + 1];
5639 #define SPEC_in1_r1p1_o SPEC_r1_even
5641 static void in1_r1p1_32s(DisasContext
*s
, DisasOps
*o
)
5643 o
->in1
= tcg_temp_new_i64();
5644 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(s
, r1
) + 1]);
5646 #define SPEC_in1_r1p1_32s SPEC_r1_even
5648 static void in1_r1p1_32u(DisasContext
*s
, DisasOps
*o
)
5650 o
->in1
= tcg_temp_new_i64();
5651 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(s
, r1
) + 1]);
5653 #define SPEC_in1_r1p1_32u SPEC_r1_even
5655 static void in1_r1_D32(DisasContext
*s
, DisasOps
*o
)
5657 int r1
= get_field(s
, r1
);
5658 o
->in1
= tcg_temp_new_i64();
5659 tcg_gen_concat32_i64(o
->in1
, regs
[r1
+ 1], regs
[r1
]);
5661 #define SPEC_in1_r1_D32 SPEC_r1_even
5663 static void in1_r2(DisasContext
*s
, DisasOps
*o
)
5665 o
->in1
= load_reg(get_field(s
, r2
));
5667 #define SPEC_in1_r2 0
5669 static void in1_r2_sr32(DisasContext
*s
, DisasOps
*o
)
5671 o
->in1
= tcg_temp_new_i64();
5672 tcg_gen_shri_i64(o
->in1
, regs
[get_field(s
, r2
)], 32);
5674 #define SPEC_in1_r2_sr32 0
5676 static void in1_r2_32u(DisasContext
*s
, DisasOps
*o
)
5678 o
->in1
= tcg_temp_new_i64();
5679 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(s
, r2
)]);
5681 #define SPEC_in1_r2_32u 0
5683 static void in1_r3(DisasContext
*s
, DisasOps
*o
)
5685 o
->in1
= load_reg(get_field(s
, r3
));
5687 #define SPEC_in1_r3 0
5689 static void in1_r3_o(DisasContext
*s
, DisasOps
*o
)
5691 o
->in1
= regs
[get_field(s
, r3
)];
5694 #define SPEC_in1_r3_o 0
5696 static void in1_r3_32s(DisasContext
*s
, DisasOps
*o
)
5698 o
->in1
= tcg_temp_new_i64();
5699 tcg_gen_ext32s_i64(o
->in1
, regs
[get_field(s
, r3
)]);
5701 #define SPEC_in1_r3_32s 0
5703 static void in1_r3_32u(DisasContext
*s
, DisasOps
*o
)
5705 o
->in1
= tcg_temp_new_i64();
5706 tcg_gen_ext32u_i64(o
->in1
, regs
[get_field(s
, r3
)]);
5708 #define SPEC_in1_r3_32u 0
5710 static void in1_r3_D32(DisasContext
*s
, DisasOps
*o
)
5712 int r3
= get_field(s
, r3
);
5713 o
->in1
= tcg_temp_new_i64();
5714 tcg_gen_concat32_i64(o
->in1
, regs
[r3
+ 1], regs
[r3
]);
5716 #define SPEC_in1_r3_D32 SPEC_r3_even
5718 static void in1_r3_sr32(DisasContext
*s
, DisasOps
*o
)
5720 o
->in1
= tcg_temp_new_i64();
5721 tcg_gen_shri_i64(o
->in1
, regs
[get_field(s
, r3
)], 32);
5723 #define SPEC_in1_r3_sr32 0
5725 static void in1_e1(DisasContext
*s
, DisasOps
*o
)
5727 o
->in1
= load_freg32_i64(get_field(s
, r1
));
5729 #define SPEC_in1_e1 0
5731 static void in1_f1(DisasContext
*s
, DisasOps
*o
)
5733 o
->in1
= load_freg(get_field(s
, r1
));
5735 #define SPEC_in1_f1 0
5737 /* Load the high double word of an extended (128-bit) format FP number */
5738 static void in1_x2h(DisasContext
*s
, DisasOps
*o
)
5740 o
->in1
= load_freg(get_field(s
, r2
));
5742 #define SPEC_in1_x2h SPEC_r2_f128
5744 static void in1_f3(DisasContext
*s
, DisasOps
*o
)
5746 o
->in1
= load_freg(get_field(s
, r3
));
5748 #define SPEC_in1_f3 0
5750 static void in1_la1(DisasContext
*s
, DisasOps
*o
)
5752 o
->addr1
= get_address(s
, 0, get_field(s
, b1
), get_field(s
, d1
));
5754 #define SPEC_in1_la1 0
5756 static void in1_la2(DisasContext
*s
, DisasOps
*o
)
5758 int x2
= have_field(s
, x2
) ? get_field(s
, x2
) : 0;
5759 o
->addr1
= get_address(s
, x2
, get_field(s
, b2
), get_field(s
, d2
));
5761 #define SPEC_in1_la2 0
5763 static void in1_m1_8u(DisasContext
*s
, DisasOps
*o
)
5766 o
->in1
= tcg_temp_new_i64();
5767 tcg_gen_qemu_ld8u(o
->in1
, o
->addr1
, get_mem_index(s
));
5769 #define SPEC_in1_m1_8u 0
5771 static void in1_m1_16s(DisasContext
*s
, DisasOps
*o
)
5774 o
->in1
= tcg_temp_new_i64();
5775 tcg_gen_qemu_ld16s(o
->in1
, o
->addr1
, get_mem_index(s
));
5777 #define SPEC_in1_m1_16s 0
5779 static void in1_m1_16u(DisasContext
*s
, DisasOps
*o
)
5782 o
->in1
= tcg_temp_new_i64();
5783 tcg_gen_qemu_ld16u(o
->in1
, o
->addr1
, get_mem_index(s
));
5785 #define SPEC_in1_m1_16u 0
5787 static void in1_m1_32s(DisasContext
*s
, DisasOps
*o
)
5790 o
->in1
= tcg_temp_new_i64();
5791 tcg_gen_qemu_ld32s(o
->in1
, o
->addr1
, get_mem_index(s
));
5793 #define SPEC_in1_m1_32s 0
5795 static void in1_m1_32u(DisasContext
*s
, DisasOps
*o
)
5798 o
->in1
= tcg_temp_new_i64();
5799 tcg_gen_qemu_ld32u(o
->in1
, o
->addr1
, get_mem_index(s
));
5801 #define SPEC_in1_m1_32u 0
5803 static void in1_m1_64(DisasContext
*s
, DisasOps
*o
)
5806 o
->in1
= tcg_temp_new_i64();
5807 tcg_gen_qemu_ld64(o
->in1
, o
->addr1
, get_mem_index(s
));
5809 #define SPEC_in1_m1_64 0
5811 /* ====================================================================== */
5812 /* The "INput 2" generators. These load the second operand to an insn. */
5814 static void in2_r1_o(DisasContext
*s
, DisasOps
*o
)
5816 o
->in2
= regs
[get_field(s
, r1
)];
5819 #define SPEC_in2_r1_o 0
5821 static void in2_r1_16u(DisasContext
*s
, DisasOps
*o
)
5823 o
->in2
= tcg_temp_new_i64();
5824 tcg_gen_ext16u_i64(o
->in2
, regs
[get_field(s
, r1
)]);
5826 #define SPEC_in2_r1_16u 0
5828 static void in2_r1_32u(DisasContext
*s
, DisasOps
*o
)
5830 o
->in2
= tcg_temp_new_i64();
5831 tcg_gen_ext32u_i64(o
->in2
, regs
[get_field(s
, r1
)]);
5833 #define SPEC_in2_r1_32u 0
5835 static void in2_r1_D32(DisasContext
*s
, DisasOps
*o
)
5837 int r1
= get_field(s
, r1
);
5838 o
->in2
= tcg_temp_new_i64();
5839 tcg_gen_concat32_i64(o
->in2
, regs
[r1
+ 1], regs
[r1
]);
5841 #define SPEC_in2_r1_D32 SPEC_r1_even
5843 static void in2_r2(DisasContext
*s
, DisasOps
*o
)
5845 o
->in2
= load_reg(get_field(s
, r2
));
5847 #define SPEC_in2_r2 0
5849 static void in2_r2_o(DisasContext
*s
, DisasOps
*o
)
5851 o
->in2
= regs
[get_field(s
, r2
)];
5854 #define SPEC_in2_r2_o 0
5856 static void in2_r2_nz(DisasContext
*s
, DisasOps
*o
)
5858 int r2
= get_field(s
, r2
);
5860 o
->in2
= load_reg(r2
);
5863 #define SPEC_in2_r2_nz 0
5865 static void in2_r2_8s(DisasContext
*s
, DisasOps
*o
)
5867 o
->in2
= tcg_temp_new_i64();
5868 tcg_gen_ext8s_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5870 #define SPEC_in2_r2_8s 0
5872 static void in2_r2_8u(DisasContext
*s
, DisasOps
*o
)
5874 o
->in2
= tcg_temp_new_i64();
5875 tcg_gen_ext8u_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5877 #define SPEC_in2_r2_8u 0
5879 static void in2_r2_16s(DisasContext
*s
, DisasOps
*o
)
5881 o
->in2
= tcg_temp_new_i64();
5882 tcg_gen_ext16s_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5884 #define SPEC_in2_r2_16s 0
5886 static void in2_r2_16u(DisasContext
*s
, DisasOps
*o
)
5888 o
->in2
= tcg_temp_new_i64();
5889 tcg_gen_ext16u_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5891 #define SPEC_in2_r2_16u 0
5893 static void in2_r3(DisasContext
*s
, DisasOps
*o
)
5895 o
->in2
= load_reg(get_field(s
, r3
));
5897 #define SPEC_in2_r3 0
5899 static void in2_r3_sr32(DisasContext
*s
, DisasOps
*o
)
5901 o
->in2
= tcg_temp_new_i64();
5902 tcg_gen_shri_i64(o
->in2
, regs
[get_field(s
, r3
)], 32);
5904 #define SPEC_in2_r3_sr32 0
5906 static void in2_r3_32u(DisasContext
*s
, DisasOps
*o
)
5908 o
->in2
= tcg_temp_new_i64();
5909 tcg_gen_ext32u_i64(o
->in2
, regs
[get_field(s
, r3
)]);
5911 #define SPEC_in2_r3_32u 0
5913 static void in2_r2_32s(DisasContext
*s
, DisasOps
*o
)
5915 o
->in2
= tcg_temp_new_i64();
5916 tcg_gen_ext32s_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5918 #define SPEC_in2_r2_32s 0
5920 static void in2_r2_32u(DisasContext
*s
, DisasOps
*o
)
5922 o
->in2
= tcg_temp_new_i64();
5923 tcg_gen_ext32u_i64(o
->in2
, regs
[get_field(s
, r2
)]);
5925 #define SPEC_in2_r2_32u 0
5927 static void in2_r2_sr32(DisasContext
*s
, DisasOps
*o
)
5929 o
->in2
= tcg_temp_new_i64();
5930 tcg_gen_shri_i64(o
->in2
, regs
[get_field(s
, r2
)], 32);
5932 #define SPEC_in2_r2_sr32 0
5934 static void in2_e2(DisasContext
*s
, DisasOps
*o
)
5936 o
->in2
= load_freg32_i64(get_field(s
, r2
));
5938 #define SPEC_in2_e2 0
5940 static void in2_f2(DisasContext
*s
, DisasOps
*o
)
5942 o
->in2
= load_freg(get_field(s
, r2
));
5944 #define SPEC_in2_f2 0
5946 /* Load the low double word of an extended (128-bit) format FP number */
5947 static void in2_x2l(DisasContext
*s
, DisasOps
*o
)
5949 o
->in2
= load_freg(get_field(s
, r2
) + 2);
5951 #define SPEC_in2_x2l SPEC_r2_f128
5953 static void in2_ra2(DisasContext
*s
, DisasOps
*o
)
5955 int r2
= get_field(s
, r2
);
5957 /* Note: *don't* treat !r2 as 0, use the reg value. */
5958 o
->in2
= tcg_temp_new_i64();
5959 gen_addi_and_wrap_i64(s
, o
->in2
, regs
[r2
], 0);
5961 #define SPEC_in2_ra2 0
5963 static void in2_a2(DisasContext
*s
, DisasOps
*o
)
5965 int x2
= have_field(s
, x2
) ? get_field(s
, x2
) : 0;
5966 o
->in2
= get_address(s
, x2
, get_field(s
, b2
), get_field(s
, d2
));
5968 #define SPEC_in2_a2 0
5970 static void in2_ri2(DisasContext
*s
, DisasOps
*o
)
5972 o
->in2
= tcg_const_i64(s
->base
.pc_next
+ (int64_t)get_field(s
, i2
) * 2);
5974 #define SPEC_in2_ri2 0
5976 static void in2_sh(DisasContext
*s
, DisasOps
*o
)
5978 int b2
= get_field(s
, b2
);
5979 int d2
= get_field(s
, d2
);
5982 o
->in2
= tcg_const_i64(d2
& 0x3f);
5984 o
->in2
= get_address(s
, 0, b2
, d2
);
5985 tcg_gen_andi_i64(o
->in2
, o
->in2
, 0x3f);
5988 #define SPEC_in2_sh 0
5990 static void in2_m2_8u(DisasContext
*s
, DisasOps
*o
)
5993 tcg_gen_qemu_ld8u(o
->in2
, o
->in2
, get_mem_index(s
));
5995 #define SPEC_in2_m2_8u 0
5997 static void in2_m2_16s(DisasContext
*s
, DisasOps
*o
)
6000 tcg_gen_qemu_ld16s(o
->in2
, o
->in2
, get_mem_index(s
));
6002 #define SPEC_in2_m2_16s 0
6004 static void in2_m2_16u(DisasContext
*s
, DisasOps
*o
)
6007 tcg_gen_qemu_ld16u(o
->in2
, o
->in2
, get_mem_index(s
));
6009 #define SPEC_in2_m2_16u 0
6011 static void in2_m2_32s(DisasContext
*s
, DisasOps
*o
)
6014 tcg_gen_qemu_ld32s(o
->in2
, o
->in2
, get_mem_index(s
));
6016 #define SPEC_in2_m2_32s 0
6018 static void in2_m2_32u(DisasContext
*s
, DisasOps
*o
)
6021 tcg_gen_qemu_ld32u(o
->in2
, o
->in2
, get_mem_index(s
));
6023 #define SPEC_in2_m2_32u 0
6025 #ifndef CONFIG_USER_ONLY
6026 static void in2_m2_32ua(DisasContext
*s
, DisasOps
*o
)
6029 tcg_gen_qemu_ld_tl(o
->in2
, o
->in2
, get_mem_index(s
), MO_TEUL
| MO_ALIGN
);
6031 #define SPEC_in2_m2_32ua 0
6034 static void in2_m2_64(DisasContext
*s
, DisasOps
*o
)
6037 tcg_gen_qemu_ld64(o
->in2
, o
->in2
, get_mem_index(s
));
6039 #define SPEC_in2_m2_64 0
6041 static void in2_m2_64w(DisasContext
*s
, DisasOps
*o
)
6044 tcg_gen_qemu_ld64(o
->in2
, o
->in2
, get_mem_index(s
));
6045 gen_addi_and_wrap_i64(s
, o
->in2
, o
->in2
, 0);
6047 #define SPEC_in2_m2_64w 0
6049 #ifndef CONFIG_USER_ONLY
6050 static void in2_m2_64a(DisasContext
*s
, DisasOps
*o
)
6053 tcg_gen_qemu_ld_i64(o
->in2
, o
->in2
, get_mem_index(s
), MO_TEUQ
| MO_ALIGN
);
6055 #define SPEC_in2_m2_64a 0
6058 static void in2_mri2_16u(DisasContext
*s
, DisasOps
*o
)
6061 tcg_gen_qemu_ld16u(o
->in2
, o
->in2
, get_mem_index(s
));
6063 #define SPEC_in2_mri2_16u 0
6065 static void in2_mri2_32s(DisasContext
*s
, DisasOps
*o
)
6068 tcg_gen_qemu_ld32s(o
->in2
, o
->in2
, get_mem_index(s
));
6070 #define SPEC_in2_mri2_32s 0
6072 static void in2_mri2_32u(DisasContext
*s
, DisasOps
*o
)
6075 tcg_gen_qemu_ld32u(o
->in2
, o
->in2
, get_mem_index(s
));
6077 #define SPEC_in2_mri2_32u 0
6079 static void in2_mri2_64(DisasContext
*s
, DisasOps
*o
)
6082 tcg_gen_qemu_ld64(o
->in2
, o
->in2
, get_mem_index(s
));
6084 #define SPEC_in2_mri2_64 0
6086 static void in2_i2(DisasContext
*s
, DisasOps
*o
)
6088 o
->in2
= tcg_const_i64(get_field(s
, i2
));
6090 #define SPEC_in2_i2 0
6092 static void in2_i2_8u(DisasContext
*s
, DisasOps
*o
)
6094 o
->in2
= tcg_const_i64((uint8_t)get_field(s
, i2
));
6096 #define SPEC_in2_i2_8u 0
6098 static void in2_i2_16u(DisasContext
*s
, DisasOps
*o
)
6100 o
->in2
= tcg_const_i64((uint16_t)get_field(s
, i2
));
6102 #define SPEC_in2_i2_16u 0
6104 static void in2_i2_32u(DisasContext
*s
, DisasOps
*o
)
6106 o
->in2
= tcg_const_i64((uint32_t)get_field(s
, i2
));
6108 #define SPEC_in2_i2_32u 0
6110 static void in2_i2_16u_shl(DisasContext
*s
, DisasOps
*o
)
6112 uint64_t i2
= (uint16_t)get_field(s
, i2
);
6113 o
->in2
= tcg_const_i64(i2
<< s
->insn
->data
);
6115 #define SPEC_in2_i2_16u_shl 0
6117 static void in2_i2_32u_shl(DisasContext
*s
, DisasOps
*o
)
6119 uint64_t i2
= (uint32_t)get_field(s
, i2
);
6120 o
->in2
= tcg_const_i64(i2
<< s
->insn
->data
);
6122 #define SPEC_in2_i2_32u_shl 0
6124 #ifndef CONFIG_USER_ONLY
6125 static void in2_insn(DisasContext
*s
, DisasOps
*o
)
6127 o
->in2
= tcg_const_i64(s
->fields
.raw_insn
);
6129 #define SPEC_in2_insn 0
6132 /* ====================================================================== */
6134 /* Find opc within the table of insns. This is formulated as a switch
6135 statement so that (1) we get compile-time notice of cut-paste errors
6136 for duplicated opcodes, and (2) the compiler generates the binary
6137 search tree, rather than us having to post-process the table. */
6139 #define C(OPC, NM, FT, FC, I1, I2, P, W, OP, CC) \
6140 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, 0)
6142 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) \
6143 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, 0)
6145 #define F(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, FL) \
6146 E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, 0, FL)
6148 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) insn_ ## NM,
6150 enum DisasInsnEnum
{
6151 #include "insn-data.def"
6155 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) { \
6160 .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W, \
6162 .help_in1 = in1_##I1, \
6163 .help_in2 = in2_##I2, \
6164 .help_prep = prep_##P, \
6165 .help_wout = wout_##W, \
6166 .help_cout = cout_##CC, \
6167 .help_op = op_##OP, \
6171 /* Allow 0 to be used for NULL in the table below. */
6179 #define SPEC_in1_0 0
6180 #define SPEC_in2_0 0
6181 #define SPEC_prep_0 0
6182 #define SPEC_wout_0 0
6184 /* Give smaller names to the various facilities. */
6185 #define FAC_Z S390_FEAT_ZARCH
6186 #define FAC_CASS S390_FEAT_COMPARE_AND_SWAP_AND_STORE
6187 #define FAC_DFP S390_FEAT_DFP
6188 #define FAC_DFPR S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* DFP-rounding */
6189 #define FAC_DO S390_FEAT_STFLE_45 /* distinct-operands */
6190 #define FAC_EE S390_FEAT_EXECUTE_EXT
6191 #define FAC_EI S390_FEAT_EXTENDED_IMMEDIATE
6192 #define FAC_FPE S390_FEAT_FLOATING_POINT_EXT
6193 #define FAC_FPSSH S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* FPS-sign-handling */
6194 #define FAC_FPRGR S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* FPR-GR-transfer */
6195 #define FAC_GIE S390_FEAT_GENERAL_INSTRUCTIONS_EXT
6196 #define FAC_HFP_MA S390_FEAT_HFP_MADDSUB
6197 #define FAC_HW S390_FEAT_STFLE_45 /* high-word */
6198 #define FAC_IEEEE_SIM S390_FEAT_FLOATING_POINT_SUPPPORT_ENH /* IEEE-exception-simulation */
6199 #define FAC_MIE S390_FEAT_STFLE_49 /* misc-instruction-extensions */
6200 #define FAC_LAT S390_FEAT_STFLE_49 /* load-and-trap */
6201 #define FAC_LOC S390_FEAT_STFLE_45 /* load/store on condition 1 */
6202 #define FAC_LOC2 S390_FEAT_STFLE_53 /* load/store on condition 2 */
6203 #define FAC_LD S390_FEAT_LONG_DISPLACEMENT
6204 #define FAC_PC S390_FEAT_STFLE_45 /* population count */
6205 #define FAC_SCF S390_FEAT_STORE_CLOCK_FAST
6206 #define FAC_SFLE S390_FEAT_STFLE
6207 #define FAC_ILA S390_FEAT_STFLE_45 /* interlocked-access-facility 1 */
6208 #define FAC_MVCOS S390_FEAT_MOVE_WITH_OPTIONAL_SPEC
6209 #define FAC_LPP S390_FEAT_SET_PROGRAM_PARAMETERS /* load-program-parameter */
6210 #define FAC_DAT_ENH S390_FEAT_DAT_ENH
6211 #define FAC_E2 S390_FEAT_EXTENDED_TRANSLATION_2
6212 #define FAC_EH S390_FEAT_STFLE_49 /* execution-hint */
6213 #define FAC_PPA S390_FEAT_STFLE_49 /* processor-assist */
6214 #define FAC_LZRB S390_FEAT_STFLE_53 /* load-and-zero-rightmost-byte */
6215 #define FAC_ETF3 S390_FEAT_EXTENDED_TRANSLATION_3
6216 #define FAC_MSA S390_FEAT_MSA /* message-security-assist facility */
6217 #define FAC_MSA3 S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */
6218 #define FAC_MSA4 S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */
6219 #define FAC_MSA5 S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */
6220 #define FAC_MSA8 S390_FEAT_MSA_EXT_8 /* msa-extension-8 facility */
6221 #define FAC_ECT S390_FEAT_EXTRACT_CPU_TIME
6222 #define FAC_PCI S390_FEAT_ZPCI /* z/PCI facility */
6223 #define FAC_AIS S390_FEAT_ADAPTER_INT_SUPPRESSION
6224 #define FAC_V S390_FEAT_VECTOR /* vector facility */
6225 #define FAC_VE S390_FEAT_VECTOR_ENH /* vector enhancements facility 1 */
6226 #define FAC_MIE2 S390_FEAT_MISC_INSTRUCTION_EXT2 /* miscellaneous-instruction-extensions facility 2 */
6227 #define FAC_MIE3 S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */
6229 static const DisasInsn insn_info
[] = {
6230 #include "insn-data.def"
6234 #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) \
6235 case OPC: return &insn_info[insn_ ## NM];
6237 static const DisasInsn
*lookup_opc(uint16_t opc
)
6240 #include "insn-data.def"
6251 /* Extract a field from the insn. The INSN should be left-aligned in
6252 the uint64_t so that we can more easily utilize the big-bit-endian
6253 definitions we extract from the Principals of Operation. */
6255 static void extract_field(DisasFields
*o
, const DisasField
*f
, uint64_t insn
)
6263 /* Zero extract the field from the insn. */
6264 r
= (insn
<< f
->beg
) >> (64 - f
->size
);
6266 /* Sign-extend, or un-swap the field as necessary. */
6268 case 0: /* unsigned */
6270 case 1: /* signed */
6271 assert(f
->size
<= 32);
6272 m
= 1u << (f
->size
- 1);
6275 case 2: /* dl+dh split, signed 20 bit. */
6276 r
= ((int8_t)r
<< 12) | (r
>> 8);
6278 case 3: /* MSB stored in RXB */
6279 g_assert(f
->size
== 4);
6282 r
|= extract64(insn
, 63 - 36, 1) << 4;
6285 r
|= extract64(insn
, 63 - 37, 1) << 4;
6288 r
|= extract64(insn
, 63 - 38, 1) << 4;
6291 r
|= extract64(insn
, 63 - 39, 1) << 4;
6294 g_assert_not_reached();
6302 * Validate that the "compressed" encoding we selected above is valid.
6303 * I.e. we haven't made two different original fields overlap.
6305 assert(((o
->presentC
>> f
->indexC
) & 1) == 0);
6306 o
->presentC
|= 1 << f
->indexC
;
6307 o
->presentO
|= 1 << f
->indexO
;
6309 o
->c
[f
->indexC
] = r
;
6312 /* Lookup the insn at the current PC, extracting the operands into O and
6313 returning the info struct for the insn. Returns NULL for invalid insn. */
6315 static const DisasInsn
*extract_insn(CPUS390XState
*env
, DisasContext
*s
)
6317 uint64_t insn
, pc
= s
->base
.pc_next
;
6319 const DisasInsn
*info
;
6321 if (unlikely(s
->ex_value
)) {
6322 /* Drop the EX data now, so that it's clear on exception paths. */
6323 TCGv_i64 zero
= tcg_const_i64(0);
6324 tcg_gen_st_i64(zero
, cpu_env
, offsetof(CPUS390XState
, ex_value
));
6325 tcg_temp_free_i64(zero
);
6327 /* Extract the values saved by EXECUTE. */
6328 insn
= s
->ex_value
& 0xffffffffffff0000ull
;
6329 ilen
= s
->ex_value
& 0xf;
6332 insn
= ld_code2(env
, s
, pc
);
6333 op
= (insn
>> 8) & 0xff;
6334 ilen
= get_ilen(op
);
6340 insn
= ld_code4(env
, s
, pc
) << 32;
6343 insn
= (insn
<< 48) | (ld_code4(env
, s
, pc
+ 2) << 16);
6346 g_assert_not_reached();
6349 s
->pc_tmp
= s
->base
.pc_next
+ ilen
;
6352 /* We can't actually determine the insn format until we've looked up
6353 the full insn opcode. Which we can't do without locating the
6354 secondary opcode. Assume by default that OP2 is at bit 40; for
6355 those smaller insns that don't actually have a secondary opcode
6356 this will correctly result in OP2 = 0. */
6362 case 0xb2: /* S, RRF, RRE, IE */
6363 case 0xb3: /* RRE, RRD, RRF */
6364 case 0xb9: /* RRE, RRF */
6365 case 0xe5: /* SSE, SIL */
6366 op2
= (insn
<< 8) >> 56;
6370 case 0xc0: /* RIL */
6371 case 0xc2: /* RIL */
6372 case 0xc4: /* RIL */
6373 case 0xc6: /* RIL */
6374 case 0xc8: /* SSF */
6375 case 0xcc: /* RIL */
6376 op2
= (insn
<< 12) >> 60;
6378 case 0xc5: /* MII */
6379 case 0xc7: /* SMI */
6380 case 0xd0 ... 0xdf: /* SS */
6386 case 0xee ... 0xf3: /* SS */
6387 case 0xf8 ... 0xfd: /* SS */
6391 op2
= (insn
<< 40) >> 56;
6395 memset(&s
->fields
, 0, sizeof(s
->fields
));
6396 s
->fields
.raw_insn
= insn
;
6398 s
->fields
.op2
= op2
;
6400 /* Lookup the instruction. */
6401 info
= lookup_opc(op
<< 8 | op2
);
6404 /* If we found it, extract the operands. */
6406 DisasFormat fmt
= info
->fmt
;
6409 for (i
= 0; i
< NUM_C_FIELD
; ++i
) {
6410 extract_field(&s
->fields
, &format_info
[fmt
].op
[i
], insn
);
6416 static bool is_afp_reg(int reg
)
6418 return reg
% 2 || reg
> 6;
6421 static bool is_fp_pair(int reg
)
6423 /* 0,1,4,5,8,9,12,13: to exclude the others, check for single bit */
6424 return !(reg
& 0x2);
6427 static DisasJumpType
translate_one(CPUS390XState
*env
, DisasContext
*s
)
6429 const DisasInsn
*insn
;
6430 DisasJumpType ret
= DISAS_NEXT
;
6432 bool icount
= false;
6434 /* Search for the insn in the table. */
6435 insn
= extract_insn(env
, s
);
6437 /* Update insn_start now that we know the ILEN. */
6438 tcg_set_insn_start_param(s
->insn_start
, 2, s
->ilen
);
6440 /* Not found means unimplemented/illegal opcode. */
6442 qemu_log_mask(LOG_UNIMP
, "unimplemented opcode 0x%02x%02x\n",
6443 s
->fields
.op
, s
->fields
.op2
);
6444 gen_illegal_opcode(s
);
6445 ret
= DISAS_NORETURN
;
6449 #ifndef CONFIG_USER_ONLY
6450 if (s
->base
.tb
->flags
& FLAG_MASK_PER
) {
6451 TCGv_i64 addr
= tcg_const_i64(s
->base
.pc_next
);
6452 gen_helper_per_ifetch(cpu_env
, addr
);
6453 tcg_temp_free_i64(addr
);
6459 /* privileged instruction */
6460 if ((s
->base
.tb
->flags
& FLAG_MASK_PSTATE
) && (insn
->flags
& IF_PRIV
)) {
6461 gen_program_exception(s
, PGM_PRIVILEGED
);
6462 ret
= DISAS_NORETURN
;
6466 /* if AFP is not enabled, instructions and registers are forbidden */
6467 if (!(s
->base
.tb
->flags
& FLAG_MASK_AFP
)) {
6470 if ((insn
->flags
& IF_AFP1
) && is_afp_reg(get_field(s
, r1
))) {
6473 if ((insn
->flags
& IF_AFP2
) && is_afp_reg(get_field(s
, r2
))) {
6476 if ((insn
->flags
& IF_AFP3
) && is_afp_reg(get_field(s
, r3
))) {
6479 if (insn
->flags
& IF_BFP
) {
6482 if (insn
->flags
& IF_DFP
) {
6485 if (insn
->flags
& IF_VEC
) {
6489 gen_data_exception(dxc
);
6490 ret
= DISAS_NORETURN
;
6495 /* if vector instructions not enabled, executing them is forbidden */
6496 if (insn
->flags
& IF_VEC
) {
6497 if (!((s
->base
.tb
->flags
& FLAG_MASK_VECTOR
))) {
6498 gen_data_exception(0xfe);
6499 ret
= DISAS_NORETURN
;
6504 /* input/output is the special case for icount mode */
6505 if (unlikely(insn
->flags
& IF_IO
)) {
6506 icount
= tb_cflags(s
->base
.tb
) & CF_USE_ICOUNT
;
6513 /* Check for insn specification exceptions. */
6515 if ((insn
->spec
& SPEC_r1_even
&& get_field(s
, r1
) & 1) ||
6516 (insn
->spec
& SPEC_r2_even
&& get_field(s
, r2
) & 1) ||
6517 (insn
->spec
& SPEC_r3_even
&& get_field(s
, r3
) & 1) ||
6518 (insn
->spec
& SPEC_r1_f128
&& !is_fp_pair(get_field(s
, r1
))) ||
6519 (insn
->spec
& SPEC_r2_f128
&& !is_fp_pair(get_field(s
, r2
)))) {
6520 gen_program_exception(s
, PGM_SPECIFICATION
);
6521 ret
= DISAS_NORETURN
;
6526 /* Implement the instruction. */
6527 if (insn
->help_in1
) {
6528 insn
->help_in1(s
, &o
);
6530 if (insn
->help_in2
) {
6531 insn
->help_in2(s
, &o
);
6533 if (insn
->help_prep
) {
6534 insn
->help_prep(s
, &o
);
6536 if (insn
->help_op
) {
6537 ret
= insn
->help_op(s
, &o
);
6539 if (ret
!= DISAS_NORETURN
) {
6540 if (insn
->help_wout
) {
6541 insn
->help_wout(s
, &o
);
6543 if (insn
->help_cout
) {
6544 insn
->help_cout(s
, &o
);
6548 /* Free any temporaries created by the helpers. */
6549 if (o
.out
&& !o
.g_out
) {
6550 tcg_temp_free_i64(o
.out
);
6552 if (o
.out2
&& !o
.g_out2
) {
6553 tcg_temp_free_i64(o
.out2
);
6555 if (o
.in1
&& !o
.g_in1
) {
6556 tcg_temp_free_i64(o
.in1
);
6558 if (o
.in2
&& !o
.g_in2
) {
6559 tcg_temp_free_i64(o
.in2
);
6562 tcg_temp_free_i64(o
.addr1
);
6565 /* io should be the last instruction in tb when icount is enabled */
6566 if (unlikely(icount
&& ret
== DISAS_NEXT
)) {
6567 ret
= DISAS_PC_STALE
;
6570 #ifndef CONFIG_USER_ONLY
6571 if (s
->base
.tb
->flags
& FLAG_MASK_PER
) {
6572 /* An exception might be triggered, save PSW if not already done. */
6573 if (ret
== DISAS_NEXT
|| ret
== DISAS_PC_STALE
) {
6574 tcg_gen_movi_i64(psw_addr
, s
->pc_tmp
);
6577 /* Call the helper to check for a possible PER exception. */
6578 gen_helper_per_check_exception(cpu_env
);
6583 /* Advance to the next instruction. */
6584 s
->base
.pc_next
= s
->pc_tmp
;
6588 static void s390x_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
6590 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
6593 if (!(dc
->base
.tb
->flags
& FLAG_MASK_64
)) {
6594 dc
->base
.pc_first
&= 0x7fffffff;
6595 dc
->base
.pc_next
= dc
->base
.pc_first
;
6598 dc
->cc_op
= CC_OP_DYNAMIC
;
6599 dc
->ex_value
= dc
->base
.tb
->cs_base
;
6602 static void s390x_tr_tb_start(DisasContextBase
*db
, CPUState
*cs
)
6606 static void s390x_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cs
)
6608 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
6610 /* Delay the set of ilen until we've read the insn. */
6611 tcg_gen_insn_start(dc
->base
.pc_next
, dc
->cc_op
, 0);
6612 dc
->insn_start
= tcg_last_op();
6615 static void s390x_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cs
)
6617 CPUS390XState
*env
= cs
->env_ptr
;
6618 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
6620 dc
->base
.is_jmp
= translate_one(env
, dc
);
6621 if (dc
->base
.is_jmp
== DISAS_NEXT
) {
6622 uint64_t page_start
;
6624 page_start
= dc
->base
.pc_first
& TARGET_PAGE_MASK
;
6625 if (dc
->base
.pc_next
- page_start
>= TARGET_PAGE_SIZE
|| dc
->ex_value
) {
6626 dc
->base
.is_jmp
= DISAS_TOO_MANY
;
6631 static void s390x_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cs
)
6633 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
6635 switch (dc
->base
.is_jmp
) {
6637 case DISAS_NORETURN
:
6639 case DISAS_TOO_MANY
:
6640 case DISAS_PC_STALE
:
6641 case DISAS_PC_STALE_NOCHAIN
:
6642 update_psw_addr(dc
);
6644 case DISAS_PC_UPDATED
:
6645 /* Next TB starts off with CC_OP_DYNAMIC, so make sure the
6646 cc op type is in env */
6649 case DISAS_PC_CC_UPDATED
:
6650 /* Exit the TB, either by raising a debug exception or by return. */
6651 if ((dc
->base
.tb
->flags
& FLAG_MASK_PER
) ||
6652 dc
->base
.is_jmp
== DISAS_PC_STALE_NOCHAIN
) {
6653 tcg_gen_exit_tb(NULL
, 0);
6655 tcg_gen_lookup_and_goto_ptr();
6659 g_assert_not_reached();
6663 static void s390x_tr_disas_log(const DisasContextBase
*dcbase
, CPUState
*cs
)
6665 DisasContext
*dc
= container_of(dcbase
, DisasContext
, base
);
6667 if (unlikely(dc
->ex_value
)) {
6668 /* ??? Unfortunately log_target_disas can't use host memory. */
6669 qemu_log("IN: EXECUTE %016" PRIx64
, dc
->ex_value
);
6671 qemu_log("IN: %s\n", lookup_symbol(dc
->base
.pc_first
));
6672 log_target_disas(cs
, dc
->base
.pc_first
, dc
->base
.tb
->size
);
6676 static const TranslatorOps s390x_tr_ops
= {
6677 .init_disas_context
= s390x_tr_init_disas_context
,
6678 .tb_start
= s390x_tr_tb_start
,
6679 .insn_start
= s390x_tr_insn_start
,
6680 .translate_insn
= s390x_tr_translate_insn
,
6681 .tb_stop
= s390x_tr_tb_stop
,
6682 .disas_log
= s390x_tr_disas_log
,
6685 void gen_intermediate_code(CPUState
*cs
, TranslationBlock
*tb
, int max_insns
)
6689 translator_loop(&s390x_tr_ops
, &dc
.base
, cs
, tb
, max_insns
);
6692 void restore_state_to_opc(CPUS390XState
*env
, TranslationBlock
*tb
,
6695 int cc_op
= data
[1];
6697 env
->psw
.addr
= data
[0];
6699 /* Update the CC opcode if it is not already up-to-date. */
6700 if ((cc_op
!= CC_OP_DYNAMIC
) && (cc_op
!= CC_OP_STATIC
)) {
6705 env
->int_pgm_ilen
= data
[2];