xref: /openbmc/qemu/target/hppa/translate.c (revision 3d68ee7bbe34278d5792f5341ba0246069c6191c)
161766fe9SRichard Henderson /*
261766fe9SRichard Henderson  * HPPA emulation cpu translation for qemu.
361766fe9SRichard Henderson  *
461766fe9SRichard Henderson  * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
561766fe9SRichard Henderson  *
661766fe9SRichard Henderson  * This library is free software; you can redistribute it and/or
761766fe9SRichard Henderson  * modify it under the terms of the GNU Lesser General Public
861766fe9SRichard Henderson  * License as published by the Free Software Foundation; either
961766fe9SRichard Henderson  * version 2 of the License, or (at your option) any later version.
1061766fe9SRichard Henderson  *
1161766fe9SRichard Henderson  * This library is distributed in the hope that it will be useful,
1261766fe9SRichard Henderson  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1361766fe9SRichard Henderson  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1461766fe9SRichard Henderson  * Lesser General Public License for more details.
1561766fe9SRichard Henderson  *
1661766fe9SRichard Henderson  * You should have received a copy of the GNU Lesser General Public
1761766fe9SRichard Henderson  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1861766fe9SRichard Henderson  */
1961766fe9SRichard Henderson 
2061766fe9SRichard Henderson #include "qemu/osdep.h"
2161766fe9SRichard Henderson #include "cpu.h"
2261766fe9SRichard Henderson #include "disas/disas.h"
2361766fe9SRichard Henderson #include "qemu/host-utils.h"
2461766fe9SRichard Henderson #include "exec/exec-all.h"
2561766fe9SRichard Henderson #include "tcg-op.h"
2661766fe9SRichard Henderson #include "exec/cpu_ldst.h"
2761766fe9SRichard Henderson #include "exec/helper-proto.h"
2861766fe9SRichard Henderson #include "exec/helper-gen.h"
29869051eaSRichard Henderson #include "exec/translator.h"
3061766fe9SRichard Henderson #include "trace-tcg.h"
3161766fe9SRichard Henderson #include "exec/log.h"
3261766fe9SRichard Henderson 
33eaa3783bSRichard Henderson /* Since we have a distinction between register size and address size,
34eaa3783bSRichard Henderson    we need to redefine all of these.  */
35eaa3783bSRichard Henderson 
36eaa3783bSRichard Henderson #undef TCGv
37eaa3783bSRichard Henderson #undef tcg_temp_new
38eaa3783bSRichard Henderson #undef tcg_global_reg_new
39eaa3783bSRichard Henderson #undef tcg_global_mem_new
40eaa3783bSRichard Henderson #undef tcg_temp_local_new
41eaa3783bSRichard Henderson #undef tcg_temp_free
42eaa3783bSRichard Henderson 
43eaa3783bSRichard Henderson #if TARGET_LONG_BITS == 64
44eaa3783bSRichard Henderson #define TCGv_tl              TCGv_i64
45eaa3783bSRichard Henderson #define tcg_temp_new_tl      tcg_temp_new_i64
46eaa3783bSRichard Henderson #define tcg_temp_free_tl     tcg_temp_free_i64
47eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64
48eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl  tcg_gen_mov_i64
49eaa3783bSRichard Henderson #else
50eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl  tcg_gen_extu_i32_i64
51eaa3783bSRichard Henderson #endif
52eaa3783bSRichard Henderson #else
53eaa3783bSRichard Henderson #define TCGv_tl              TCGv_i32
54eaa3783bSRichard Henderson #define tcg_temp_new_tl      tcg_temp_new_i32
55eaa3783bSRichard Henderson #define tcg_temp_free_tl     tcg_temp_free_i32
56eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl  tcg_gen_mov_i32
57eaa3783bSRichard Henderson #endif
58eaa3783bSRichard Henderson 
59eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64
60eaa3783bSRichard Henderson #define TCGv_reg             TCGv_i64
61eaa3783bSRichard Henderson 
62eaa3783bSRichard Henderson #define tcg_temp_new         tcg_temp_new_i64
63eaa3783bSRichard Henderson #define tcg_global_reg_new   tcg_global_reg_new_i64
64eaa3783bSRichard Henderson #define tcg_global_mem_new   tcg_global_mem_new_i64
65eaa3783bSRichard Henderson #define tcg_temp_local_new   tcg_temp_local_new_i64
66eaa3783bSRichard Henderson #define tcg_temp_free        tcg_temp_free_i64
67eaa3783bSRichard Henderson 
68eaa3783bSRichard Henderson #define tcg_gen_movi_reg     tcg_gen_movi_i64
69eaa3783bSRichard Henderson #define tcg_gen_mov_reg      tcg_gen_mov_i64
70eaa3783bSRichard Henderson #define tcg_gen_ld8u_reg     tcg_gen_ld8u_i64
71eaa3783bSRichard Henderson #define tcg_gen_ld8s_reg     tcg_gen_ld8s_i64
72eaa3783bSRichard Henderson #define tcg_gen_ld16u_reg    tcg_gen_ld16u_i64
73eaa3783bSRichard Henderson #define tcg_gen_ld16s_reg    tcg_gen_ld16s_i64
74eaa3783bSRichard Henderson #define tcg_gen_ld32u_reg    tcg_gen_ld32u_i64
75eaa3783bSRichard Henderson #define tcg_gen_ld32s_reg    tcg_gen_ld32s_i64
76eaa3783bSRichard Henderson #define tcg_gen_ld_reg       tcg_gen_ld_i64
77eaa3783bSRichard Henderson #define tcg_gen_st8_reg      tcg_gen_st8_i64
78eaa3783bSRichard Henderson #define tcg_gen_st16_reg     tcg_gen_st16_i64
79eaa3783bSRichard Henderson #define tcg_gen_st32_reg     tcg_gen_st32_i64
80eaa3783bSRichard Henderson #define tcg_gen_st_reg       tcg_gen_st_i64
81eaa3783bSRichard Henderson #define tcg_gen_add_reg      tcg_gen_add_i64
82eaa3783bSRichard Henderson #define tcg_gen_addi_reg     tcg_gen_addi_i64
83eaa3783bSRichard Henderson #define tcg_gen_sub_reg      tcg_gen_sub_i64
84eaa3783bSRichard Henderson #define tcg_gen_neg_reg      tcg_gen_neg_i64
85eaa3783bSRichard Henderson #define tcg_gen_subfi_reg    tcg_gen_subfi_i64
86eaa3783bSRichard Henderson #define tcg_gen_subi_reg     tcg_gen_subi_i64
87eaa3783bSRichard Henderson #define tcg_gen_and_reg      tcg_gen_and_i64
88eaa3783bSRichard Henderson #define tcg_gen_andi_reg     tcg_gen_andi_i64
89eaa3783bSRichard Henderson #define tcg_gen_or_reg       tcg_gen_or_i64
90eaa3783bSRichard Henderson #define tcg_gen_ori_reg      tcg_gen_ori_i64
91eaa3783bSRichard Henderson #define tcg_gen_xor_reg      tcg_gen_xor_i64
92eaa3783bSRichard Henderson #define tcg_gen_xori_reg     tcg_gen_xori_i64
93eaa3783bSRichard Henderson #define tcg_gen_not_reg      tcg_gen_not_i64
94eaa3783bSRichard Henderson #define tcg_gen_shl_reg      tcg_gen_shl_i64
95eaa3783bSRichard Henderson #define tcg_gen_shli_reg     tcg_gen_shli_i64
96eaa3783bSRichard Henderson #define tcg_gen_shr_reg      tcg_gen_shr_i64
97eaa3783bSRichard Henderson #define tcg_gen_shri_reg     tcg_gen_shri_i64
98eaa3783bSRichard Henderson #define tcg_gen_sar_reg      tcg_gen_sar_i64
99eaa3783bSRichard Henderson #define tcg_gen_sari_reg     tcg_gen_sari_i64
100eaa3783bSRichard Henderson #define tcg_gen_brcond_reg   tcg_gen_brcond_i64
101eaa3783bSRichard Henderson #define tcg_gen_brcondi_reg  tcg_gen_brcondi_i64
102eaa3783bSRichard Henderson #define tcg_gen_setcond_reg  tcg_gen_setcond_i64
103eaa3783bSRichard Henderson #define tcg_gen_setcondi_reg tcg_gen_setcondi_i64
104eaa3783bSRichard Henderson #define tcg_gen_mul_reg      tcg_gen_mul_i64
105eaa3783bSRichard Henderson #define tcg_gen_muli_reg     tcg_gen_muli_i64
106eaa3783bSRichard Henderson #define tcg_gen_div_reg      tcg_gen_div_i64
107eaa3783bSRichard Henderson #define tcg_gen_rem_reg      tcg_gen_rem_i64
108eaa3783bSRichard Henderson #define tcg_gen_divu_reg     tcg_gen_divu_i64
109eaa3783bSRichard Henderson #define tcg_gen_remu_reg     tcg_gen_remu_i64
110eaa3783bSRichard Henderson #define tcg_gen_discard_reg  tcg_gen_discard_i64
111eaa3783bSRichard Henderson #define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32
112eaa3783bSRichard Henderson #define tcg_gen_trunc_i64_reg tcg_gen_mov_i64
113eaa3783bSRichard Henderson #define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64
114eaa3783bSRichard Henderson #define tcg_gen_ext_i32_reg  tcg_gen_ext_i32_i64
115eaa3783bSRichard Henderson #define tcg_gen_extu_reg_i64 tcg_gen_mov_i64
116eaa3783bSRichard Henderson #define tcg_gen_ext_reg_i64  tcg_gen_mov_i64
117eaa3783bSRichard Henderson #define tcg_gen_ext8u_reg    tcg_gen_ext8u_i64
118eaa3783bSRichard Henderson #define tcg_gen_ext8s_reg    tcg_gen_ext8s_i64
119eaa3783bSRichard Henderson #define tcg_gen_ext16u_reg   tcg_gen_ext16u_i64
120eaa3783bSRichard Henderson #define tcg_gen_ext16s_reg   tcg_gen_ext16s_i64
121eaa3783bSRichard Henderson #define tcg_gen_ext32u_reg   tcg_gen_ext32u_i64
122eaa3783bSRichard Henderson #define tcg_gen_ext32s_reg   tcg_gen_ext32s_i64
123eaa3783bSRichard Henderson #define tcg_gen_bswap16_reg  tcg_gen_bswap16_i64
124eaa3783bSRichard Henderson #define tcg_gen_bswap32_reg  tcg_gen_bswap32_i64
125eaa3783bSRichard Henderson #define tcg_gen_bswap64_reg  tcg_gen_bswap64_i64
126eaa3783bSRichard Henderson #define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64
127eaa3783bSRichard Henderson #define tcg_gen_andc_reg     tcg_gen_andc_i64
128eaa3783bSRichard Henderson #define tcg_gen_eqv_reg      tcg_gen_eqv_i64
129eaa3783bSRichard Henderson #define tcg_gen_nand_reg     tcg_gen_nand_i64
130eaa3783bSRichard Henderson #define tcg_gen_nor_reg      tcg_gen_nor_i64
131eaa3783bSRichard Henderson #define tcg_gen_orc_reg      tcg_gen_orc_i64
132eaa3783bSRichard Henderson #define tcg_gen_clz_reg      tcg_gen_clz_i64
133eaa3783bSRichard Henderson #define tcg_gen_ctz_reg      tcg_gen_ctz_i64
134eaa3783bSRichard Henderson #define tcg_gen_clzi_reg     tcg_gen_clzi_i64
135eaa3783bSRichard Henderson #define tcg_gen_ctzi_reg     tcg_gen_ctzi_i64
136eaa3783bSRichard Henderson #define tcg_gen_clrsb_reg    tcg_gen_clrsb_i64
137eaa3783bSRichard Henderson #define tcg_gen_ctpop_reg    tcg_gen_ctpop_i64
138eaa3783bSRichard Henderson #define tcg_gen_rotl_reg     tcg_gen_rotl_i64
139eaa3783bSRichard Henderson #define tcg_gen_rotli_reg    tcg_gen_rotli_i64
140eaa3783bSRichard Henderson #define tcg_gen_rotr_reg     tcg_gen_rotr_i64
141eaa3783bSRichard Henderson #define tcg_gen_rotri_reg    tcg_gen_rotri_i64
142eaa3783bSRichard Henderson #define tcg_gen_deposit_reg  tcg_gen_deposit_i64
143eaa3783bSRichard Henderson #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64
144eaa3783bSRichard Henderson #define tcg_gen_extract_reg  tcg_gen_extract_i64
145eaa3783bSRichard Henderson #define tcg_gen_sextract_reg tcg_gen_sextract_i64
146eaa3783bSRichard Henderson #define tcg_const_reg        tcg_const_i64
147eaa3783bSRichard Henderson #define tcg_const_local_reg  tcg_const_local_i64
148eaa3783bSRichard Henderson #define tcg_gen_movcond_reg  tcg_gen_movcond_i64
149eaa3783bSRichard Henderson #define tcg_gen_add2_reg     tcg_gen_add2_i64
150eaa3783bSRichard Henderson #define tcg_gen_sub2_reg     tcg_gen_sub2_i64
151eaa3783bSRichard Henderson #define tcg_gen_qemu_ld_reg  tcg_gen_qemu_ld_i64
152eaa3783bSRichard Henderson #define tcg_gen_qemu_st_reg  tcg_gen_qemu_st_i64
153eaa3783bSRichard Henderson #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64
154eaa3783bSRichard Henderson #if UINTPTR_MAX == UINT32_MAX
155eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \
156eaa3783bSRichard Henderson     tcg_gen_trunc_i64_i32(TCGV_PTR_TO_NAT(p), r)
157eaa3783bSRichard Henderson #else
158eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \
159eaa3783bSRichard Henderson     tcg_gen_mov_i64(TCGV_PTR_TO_NAT(p), r)
160eaa3783bSRichard Henderson #endif
161eaa3783bSRichard Henderson #else
162eaa3783bSRichard Henderson #define TCGv_reg             TCGv_i32
163eaa3783bSRichard Henderson #define tcg_temp_new         tcg_temp_new_i32
164eaa3783bSRichard Henderson #define tcg_global_reg_new   tcg_global_reg_new_i32
165eaa3783bSRichard Henderson #define tcg_global_mem_new   tcg_global_mem_new_i32
166eaa3783bSRichard Henderson #define tcg_temp_local_new   tcg_temp_local_new_i32
167eaa3783bSRichard Henderson #define tcg_temp_free        tcg_temp_free_i32
168eaa3783bSRichard Henderson 
169eaa3783bSRichard Henderson #define tcg_gen_movi_reg     tcg_gen_movi_i32
170eaa3783bSRichard Henderson #define tcg_gen_mov_reg      tcg_gen_mov_i32
171eaa3783bSRichard Henderson #define tcg_gen_ld8u_reg     tcg_gen_ld8u_i32
172eaa3783bSRichard Henderson #define tcg_gen_ld8s_reg     tcg_gen_ld8s_i32
173eaa3783bSRichard Henderson #define tcg_gen_ld16u_reg    tcg_gen_ld16u_i32
174eaa3783bSRichard Henderson #define tcg_gen_ld16s_reg    tcg_gen_ld16s_i32
175eaa3783bSRichard Henderson #define tcg_gen_ld32u_reg    tcg_gen_ld_i32
176eaa3783bSRichard Henderson #define tcg_gen_ld32s_reg    tcg_gen_ld_i32
177eaa3783bSRichard Henderson #define tcg_gen_ld_reg       tcg_gen_ld_i32
178eaa3783bSRichard Henderson #define tcg_gen_st8_reg      tcg_gen_st8_i32
179eaa3783bSRichard Henderson #define tcg_gen_st16_reg     tcg_gen_st16_i32
180eaa3783bSRichard Henderson #define tcg_gen_st32_reg     tcg_gen_st32_i32
181eaa3783bSRichard Henderson #define tcg_gen_st_reg       tcg_gen_st_i32
182eaa3783bSRichard Henderson #define tcg_gen_add_reg      tcg_gen_add_i32
183eaa3783bSRichard Henderson #define tcg_gen_addi_reg     tcg_gen_addi_i32
184eaa3783bSRichard Henderson #define tcg_gen_sub_reg      tcg_gen_sub_i32
185eaa3783bSRichard Henderson #define tcg_gen_neg_reg      tcg_gen_neg_i32
186eaa3783bSRichard Henderson #define tcg_gen_subfi_reg    tcg_gen_subfi_i32
187eaa3783bSRichard Henderson #define tcg_gen_subi_reg     tcg_gen_subi_i32
188eaa3783bSRichard Henderson #define tcg_gen_and_reg      tcg_gen_and_i32
189eaa3783bSRichard Henderson #define tcg_gen_andi_reg     tcg_gen_andi_i32
190eaa3783bSRichard Henderson #define tcg_gen_or_reg       tcg_gen_or_i32
191eaa3783bSRichard Henderson #define tcg_gen_ori_reg      tcg_gen_ori_i32
192eaa3783bSRichard Henderson #define tcg_gen_xor_reg      tcg_gen_xor_i32
193eaa3783bSRichard Henderson #define tcg_gen_xori_reg     tcg_gen_xori_i32
194eaa3783bSRichard Henderson #define tcg_gen_not_reg      tcg_gen_not_i32
195eaa3783bSRichard Henderson #define tcg_gen_shl_reg      tcg_gen_shl_i32
196eaa3783bSRichard Henderson #define tcg_gen_shli_reg     tcg_gen_shli_i32
197eaa3783bSRichard Henderson #define tcg_gen_shr_reg      tcg_gen_shr_i32
198eaa3783bSRichard Henderson #define tcg_gen_shri_reg     tcg_gen_shri_i32
199eaa3783bSRichard Henderson #define tcg_gen_sar_reg      tcg_gen_sar_i32
200eaa3783bSRichard Henderson #define tcg_gen_sari_reg     tcg_gen_sari_i32
201eaa3783bSRichard Henderson #define tcg_gen_brcond_reg   tcg_gen_brcond_i32
202eaa3783bSRichard Henderson #define tcg_gen_brcondi_reg  tcg_gen_brcondi_i32
203eaa3783bSRichard Henderson #define tcg_gen_setcond_reg  tcg_gen_setcond_i32
204eaa3783bSRichard Henderson #define tcg_gen_setcondi_reg tcg_gen_setcondi_i32
205eaa3783bSRichard Henderson #define tcg_gen_mul_reg      tcg_gen_mul_i32
206eaa3783bSRichard Henderson #define tcg_gen_muli_reg     tcg_gen_muli_i32
207eaa3783bSRichard Henderson #define tcg_gen_div_reg      tcg_gen_div_i32
208eaa3783bSRichard Henderson #define tcg_gen_rem_reg      tcg_gen_rem_i32
209eaa3783bSRichard Henderson #define tcg_gen_divu_reg     tcg_gen_divu_i32
210eaa3783bSRichard Henderson #define tcg_gen_remu_reg     tcg_gen_remu_i32
211eaa3783bSRichard Henderson #define tcg_gen_discard_reg  tcg_gen_discard_i32
212eaa3783bSRichard Henderson #define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32
213eaa3783bSRichard Henderson #define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32
214eaa3783bSRichard Henderson #define tcg_gen_extu_i32_reg tcg_gen_mov_i32
215eaa3783bSRichard Henderson #define tcg_gen_ext_i32_reg  tcg_gen_mov_i32
216eaa3783bSRichard Henderson #define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64
217eaa3783bSRichard Henderson #define tcg_gen_ext_reg_i64  tcg_gen_ext_i32_i64
218eaa3783bSRichard Henderson #define tcg_gen_ext8u_reg    tcg_gen_ext8u_i32
219eaa3783bSRichard Henderson #define tcg_gen_ext8s_reg    tcg_gen_ext8s_i32
220eaa3783bSRichard Henderson #define tcg_gen_ext16u_reg   tcg_gen_ext16u_i32
221eaa3783bSRichard Henderson #define tcg_gen_ext16s_reg   tcg_gen_ext16s_i32
222eaa3783bSRichard Henderson #define tcg_gen_ext32u_reg   tcg_gen_mov_i32
223eaa3783bSRichard Henderson #define tcg_gen_ext32s_reg   tcg_gen_mov_i32
224eaa3783bSRichard Henderson #define tcg_gen_bswap16_reg  tcg_gen_bswap16_i32
225eaa3783bSRichard Henderson #define tcg_gen_bswap32_reg  tcg_gen_bswap32_i32
226eaa3783bSRichard Henderson #define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64
227eaa3783bSRichard Henderson #define tcg_gen_andc_reg     tcg_gen_andc_i32
228eaa3783bSRichard Henderson #define tcg_gen_eqv_reg      tcg_gen_eqv_i32
229eaa3783bSRichard Henderson #define tcg_gen_nand_reg     tcg_gen_nand_i32
230eaa3783bSRichard Henderson #define tcg_gen_nor_reg      tcg_gen_nor_i32
231eaa3783bSRichard Henderson #define tcg_gen_orc_reg      tcg_gen_orc_i32
232eaa3783bSRichard Henderson #define tcg_gen_clz_reg      tcg_gen_clz_i32
233eaa3783bSRichard Henderson #define tcg_gen_ctz_reg      tcg_gen_ctz_i32
234eaa3783bSRichard Henderson #define tcg_gen_clzi_reg     tcg_gen_clzi_i32
235eaa3783bSRichard Henderson #define tcg_gen_ctzi_reg     tcg_gen_ctzi_i32
236eaa3783bSRichard Henderson #define tcg_gen_clrsb_reg    tcg_gen_clrsb_i32
237eaa3783bSRichard Henderson #define tcg_gen_ctpop_reg    tcg_gen_ctpop_i32
238eaa3783bSRichard Henderson #define tcg_gen_rotl_reg     tcg_gen_rotl_i32
239eaa3783bSRichard Henderson #define tcg_gen_rotli_reg    tcg_gen_rotli_i32
240eaa3783bSRichard Henderson #define tcg_gen_rotr_reg     tcg_gen_rotr_i32
241eaa3783bSRichard Henderson #define tcg_gen_rotri_reg    tcg_gen_rotri_i32
242eaa3783bSRichard Henderson #define tcg_gen_deposit_reg  tcg_gen_deposit_i32
243eaa3783bSRichard Henderson #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32
244eaa3783bSRichard Henderson #define tcg_gen_extract_reg  tcg_gen_extract_i32
245eaa3783bSRichard Henderson #define tcg_gen_sextract_reg tcg_gen_sextract_i32
246eaa3783bSRichard Henderson #define tcg_const_reg        tcg_const_i32
247eaa3783bSRichard Henderson #define tcg_const_local_reg  tcg_const_local_i32
248eaa3783bSRichard Henderson #define tcg_gen_movcond_reg  tcg_gen_movcond_i32
249eaa3783bSRichard Henderson #define tcg_gen_add2_reg     tcg_gen_add2_i32
250eaa3783bSRichard Henderson #define tcg_gen_sub2_reg     tcg_gen_sub2_i32
251eaa3783bSRichard Henderson #define tcg_gen_qemu_ld_reg  tcg_gen_qemu_ld_i32
252eaa3783bSRichard Henderson #define tcg_gen_qemu_st_reg  tcg_gen_qemu_st_i32
253eaa3783bSRichard Henderson #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
254eaa3783bSRichard Henderson #if UINTPTR_MAX == UINT32_MAX
255eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \
256eaa3783bSRichard Henderson     tcg_gen_mov_i32(TCGV_PTR_TO_NAT(p), r)
257eaa3783bSRichard Henderson #else
258eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \
259eaa3783bSRichard Henderson     tcg_gen_extu_i32_i64(TCGV_PTR_TO_NAT(p), r)
260eaa3783bSRichard Henderson #endif
261eaa3783bSRichard Henderson #endif /* TARGET_REGISTER_BITS */
262eaa3783bSRichard Henderson 
26361766fe9SRichard Henderson typedef struct DisasCond {
26461766fe9SRichard Henderson     TCGCond c;
265eaa3783bSRichard Henderson     TCGv_reg a0, a1;
26661766fe9SRichard Henderson     bool a0_is_n;
26761766fe9SRichard Henderson     bool a1_is_0;
26861766fe9SRichard Henderson } DisasCond;
26961766fe9SRichard Henderson 
27061766fe9SRichard Henderson typedef struct DisasContext {
271d01a3625SRichard Henderson     DisasContextBase base;
27261766fe9SRichard Henderson     CPUState *cs;
27361766fe9SRichard Henderson 
274eaa3783bSRichard Henderson     target_ureg iaoq_f;
275eaa3783bSRichard Henderson     target_ureg iaoq_b;
276eaa3783bSRichard Henderson     target_ureg iaoq_n;
277eaa3783bSRichard Henderson     TCGv_reg iaoq_n_var;
27861766fe9SRichard Henderson 
27961766fe9SRichard Henderson     int ntemps;
280eaa3783bSRichard Henderson     TCGv_reg temps[8];
28161766fe9SRichard Henderson 
28261766fe9SRichard Henderson     DisasCond null_cond;
28361766fe9SRichard Henderson     TCGLabel *null_lab;
28461766fe9SRichard Henderson 
285*3d68ee7bSRichard Henderson     int mmu_idx;
286*3d68ee7bSRichard Henderson     int privilege;
28761766fe9SRichard Henderson     bool psw_n_nonzero;
28861766fe9SRichard Henderson } DisasContext;
28961766fe9SRichard Henderson 
290869051eaSRichard Henderson /* Target-specific return values from translate_one, indicating the
291869051eaSRichard Henderson    state of the TB.  Note that DISAS_NEXT indicates that we are not
292869051eaSRichard Henderson    exiting the TB.  */
29361766fe9SRichard Henderson 
29461766fe9SRichard Henderson /* We are not using a goto_tb (for whatever reason), but have updated
29561766fe9SRichard Henderson    the iaq (for whatever reason), so don't do it again on exit.  */
296869051eaSRichard Henderson #define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
29761766fe9SRichard Henderson 
29861766fe9SRichard Henderson /* We are exiting the TB, but have neither emitted a goto_tb, nor
29961766fe9SRichard Henderson    updated the iaq for the next instruction to be executed.  */
300869051eaSRichard Henderson #define DISAS_IAQ_N_STALE    DISAS_TARGET_1
30161766fe9SRichard Henderson 
30261766fe9SRichard Henderson typedef struct DisasInsn {
30361766fe9SRichard Henderson     uint32_t insn, mask;
304869051eaSRichard Henderson     DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
30561766fe9SRichard Henderson                            const struct DisasInsn *f);
306b2167459SRichard Henderson     union {
307eaa3783bSRichard Henderson         void (*ttt)(TCGv_reg, TCGv_reg, TCGv_reg);
308eff235ebSPaolo Bonzini         void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32);
309eff235ebSPaolo Bonzini         void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64);
310eff235ebSPaolo Bonzini         void (*wew)(TCGv_i32, TCGv_env, TCGv_i32);
311eff235ebSPaolo Bonzini         void (*ded)(TCGv_i64, TCGv_env, TCGv_i64);
312eff235ebSPaolo Bonzini         void (*wed)(TCGv_i32, TCGv_env, TCGv_i64);
313eff235ebSPaolo Bonzini         void (*dew)(TCGv_i64, TCGv_env, TCGv_i32);
314eff235ebSPaolo Bonzini     } f;
31561766fe9SRichard Henderson } DisasInsn;
31661766fe9SRichard Henderson 
31761766fe9SRichard Henderson /* global register indexes */
318eaa3783bSRichard Henderson static TCGv_reg cpu_gr[32];
319eaa3783bSRichard Henderson static TCGv_reg cpu_iaoq_f;
320eaa3783bSRichard Henderson static TCGv_reg cpu_iaoq_b;
321eaa3783bSRichard Henderson static TCGv_reg cpu_sar;
322eaa3783bSRichard Henderson static TCGv_reg cpu_psw_n;
323eaa3783bSRichard Henderson static TCGv_reg cpu_psw_v;
324eaa3783bSRichard Henderson static TCGv_reg cpu_psw_cb;
325eaa3783bSRichard Henderson static TCGv_reg cpu_psw_cb_msb;
326eaa3783bSRichard Henderson static TCGv_reg cpu_cr26;
327eaa3783bSRichard Henderson static TCGv_reg cpu_cr27;
32861766fe9SRichard Henderson 
32961766fe9SRichard Henderson #include "exec/gen-icount.h"
33061766fe9SRichard Henderson 
33161766fe9SRichard Henderson void hppa_translate_init(void)
33261766fe9SRichard Henderson {
33361766fe9SRichard Henderson #define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
33461766fe9SRichard Henderson 
335eaa3783bSRichard Henderson     typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar;
33661766fe9SRichard Henderson     static const GlobalVar vars[] = {
33761766fe9SRichard Henderson         DEF_VAR(sar),
33861766fe9SRichard Henderson         DEF_VAR(cr26),
33961766fe9SRichard Henderson         DEF_VAR(cr27),
34061766fe9SRichard Henderson         DEF_VAR(psw_n),
34161766fe9SRichard Henderson         DEF_VAR(psw_v),
34261766fe9SRichard Henderson         DEF_VAR(psw_cb),
34361766fe9SRichard Henderson         DEF_VAR(psw_cb_msb),
34461766fe9SRichard Henderson         DEF_VAR(iaoq_f),
34561766fe9SRichard Henderson         DEF_VAR(iaoq_b),
34661766fe9SRichard Henderson     };
34761766fe9SRichard Henderson 
34861766fe9SRichard Henderson #undef DEF_VAR
34961766fe9SRichard Henderson 
35061766fe9SRichard Henderson     /* Use the symbolic register names that match the disassembler.  */
35161766fe9SRichard Henderson     static const char gr_names[32][4] = {
35261766fe9SRichard Henderson         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
35361766fe9SRichard Henderson         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
35461766fe9SRichard Henderson         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
35561766fe9SRichard Henderson         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
35661766fe9SRichard Henderson     };
35761766fe9SRichard Henderson 
35861766fe9SRichard Henderson     int i;
35961766fe9SRichard Henderson 
360f764718dSRichard Henderson     cpu_gr[0] = NULL;
36161766fe9SRichard Henderson     for (i = 1; i < 32; i++) {
36261766fe9SRichard Henderson         cpu_gr[i] = tcg_global_mem_new(cpu_env,
36361766fe9SRichard Henderson                                        offsetof(CPUHPPAState, gr[i]),
36461766fe9SRichard Henderson                                        gr_names[i]);
36561766fe9SRichard Henderson     }
36661766fe9SRichard Henderson 
36761766fe9SRichard Henderson     for (i = 0; i < ARRAY_SIZE(vars); ++i) {
36861766fe9SRichard Henderson         const GlobalVar *v = &vars[i];
36961766fe9SRichard Henderson         *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name);
37061766fe9SRichard Henderson     }
37161766fe9SRichard Henderson }
37261766fe9SRichard Henderson 
373129e9cc3SRichard Henderson static DisasCond cond_make_f(void)
374129e9cc3SRichard Henderson {
375f764718dSRichard Henderson     return (DisasCond){
376f764718dSRichard Henderson         .c = TCG_COND_NEVER,
377f764718dSRichard Henderson         .a0 = NULL,
378f764718dSRichard Henderson         .a1 = NULL,
379f764718dSRichard Henderson     };
380129e9cc3SRichard Henderson }
381129e9cc3SRichard Henderson 
382129e9cc3SRichard Henderson static DisasCond cond_make_n(void)
383129e9cc3SRichard Henderson {
384f764718dSRichard Henderson     return (DisasCond){
385f764718dSRichard Henderson         .c = TCG_COND_NE,
386f764718dSRichard Henderson         .a0 = cpu_psw_n,
387f764718dSRichard Henderson         .a0_is_n = true,
388f764718dSRichard Henderson         .a1 = NULL,
389f764718dSRichard Henderson         .a1_is_0 = true
390f764718dSRichard Henderson     };
391129e9cc3SRichard Henderson }
392129e9cc3SRichard Henderson 
393eaa3783bSRichard Henderson static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
394129e9cc3SRichard Henderson {
395f764718dSRichard Henderson     DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true };
396129e9cc3SRichard Henderson 
397129e9cc3SRichard Henderson     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
398129e9cc3SRichard Henderson     r.a0 = tcg_temp_new();
399eaa3783bSRichard Henderson     tcg_gen_mov_reg(r.a0, a0);
400129e9cc3SRichard Henderson 
401129e9cc3SRichard Henderson     return r;
402129e9cc3SRichard Henderson }
403129e9cc3SRichard Henderson 
404eaa3783bSRichard Henderson static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
405129e9cc3SRichard Henderson {
406129e9cc3SRichard Henderson     DisasCond r = { .c = c };
407129e9cc3SRichard Henderson 
408129e9cc3SRichard Henderson     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
409129e9cc3SRichard Henderson     r.a0 = tcg_temp_new();
410eaa3783bSRichard Henderson     tcg_gen_mov_reg(r.a0, a0);
411129e9cc3SRichard Henderson     r.a1 = tcg_temp_new();
412eaa3783bSRichard Henderson     tcg_gen_mov_reg(r.a1, a1);
413129e9cc3SRichard Henderson 
414129e9cc3SRichard Henderson     return r;
415129e9cc3SRichard Henderson }
416129e9cc3SRichard Henderson 
417129e9cc3SRichard Henderson static void cond_prep(DisasCond *cond)
418129e9cc3SRichard Henderson {
419129e9cc3SRichard Henderson     if (cond->a1_is_0) {
420129e9cc3SRichard Henderson         cond->a1_is_0 = false;
421eaa3783bSRichard Henderson         cond->a1 = tcg_const_reg(0);
422129e9cc3SRichard Henderson     }
423129e9cc3SRichard Henderson }
424129e9cc3SRichard Henderson 
425129e9cc3SRichard Henderson static void cond_free(DisasCond *cond)
426129e9cc3SRichard Henderson {
427129e9cc3SRichard Henderson     switch (cond->c) {
428129e9cc3SRichard Henderson     default:
429129e9cc3SRichard Henderson         if (!cond->a0_is_n) {
430129e9cc3SRichard Henderson             tcg_temp_free(cond->a0);
431129e9cc3SRichard Henderson         }
432129e9cc3SRichard Henderson         if (!cond->a1_is_0) {
433129e9cc3SRichard Henderson             tcg_temp_free(cond->a1);
434129e9cc3SRichard Henderson         }
435129e9cc3SRichard Henderson         cond->a0_is_n = false;
436129e9cc3SRichard Henderson         cond->a1_is_0 = false;
437f764718dSRichard Henderson         cond->a0 = NULL;
438f764718dSRichard Henderson         cond->a1 = NULL;
439129e9cc3SRichard Henderson         /* fallthru */
440129e9cc3SRichard Henderson     case TCG_COND_ALWAYS:
441129e9cc3SRichard Henderson         cond->c = TCG_COND_NEVER;
442129e9cc3SRichard Henderson         break;
443129e9cc3SRichard Henderson     case TCG_COND_NEVER:
444129e9cc3SRichard Henderson         break;
445129e9cc3SRichard Henderson     }
446129e9cc3SRichard Henderson }
447129e9cc3SRichard Henderson 
448eaa3783bSRichard Henderson static TCGv_reg get_temp(DisasContext *ctx)
44961766fe9SRichard Henderson {
45061766fe9SRichard Henderson     unsigned i = ctx->ntemps++;
45161766fe9SRichard Henderson     g_assert(i < ARRAY_SIZE(ctx->temps));
45261766fe9SRichard Henderson     return ctx->temps[i] = tcg_temp_new();
45361766fe9SRichard Henderson }
45461766fe9SRichard Henderson 
455eaa3783bSRichard Henderson static TCGv_reg load_const(DisasContext *ctx, target_sreg v)
45661766fe9SRichard Henderson {
457eaa3783bSRichard Henderson     TCGv_reg t = get_temp(ctx);
458eaa3783bSRichard Henderson     tcg_gen_movi_reg(t, v);
45961766fe9SRichard Henderson     return t;
46061766fe9SRichard Henderson }
46161766fe9SRichard Henderson 
462eaa3783bSRichard Henderson static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg)
46361766fe9SRichard Henderson {
46461766fe9SRichard Henderson     if (reg == 0) {
465eaa3783bSRichard Henderson         TCGv_reg t = get_temp(ctx);
466eaa3783bSRichard Henderson         tcg_gen_movi_reg(t, 0);
46761766fe9SRichard Henderson         return t;
46861766fe9SRichard Henderson     } else {
46961766fe9SRichard Henderson         return cpu_gr[reg];
47061766fe9SRichard Henderson     }
47161766fe9SRichard Henderson }
47261766fe9SRichard Henderson 
473eaa3783bSRichard Henderson static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg)
47461766fe9SRichard Henderson {
475129e9cc3SRichard Henderson     if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
47661766fe9SRichard Henderson         return get_temp(ctx);
47761766fe9SRichard Henderson     } else {
47861766fe9SRichard Henderson         return cpu_gr[reg];
47961766fe9SRichard Henderson     }
48061766fe9SRichard Henderson }
48161766fe9SRichard Henderson 
482eaa3783bSRichard Henderson static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
483129e9cc3SRichard Henderson {
484129e9cc3SRichard Henderson     if (ctx->null_cond.c != TCG_COND_NEVER) {
485129e9cc3SRichard Henderson         cond_prep(&ctx->null_cond);
486eaa3783bSRichard Henderson         tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0,
487129e9cc3SRichard Henderson                            ctx->null_cond.a1, dest, t);
488129e9cc3SRichard Henderson     } else {
489eaa3783bSRichard Henderson         tcg_gen_mov_reg(dest, t);
490129e9cc3SRichard Henderson     }
491129e9cc3SRichard Henderson }
492129e9cc3SRichard Henderson 
493eaa3783bSRichard Henderson static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t)
494129e9cc3SRichard Henderson {
495129e9cc3SRichard Henderson     if (reg != 0) {
496129e9cc3SRichard Henderson         save_or_nullify(ctx, cpu_gr[reg], t);
497129e9cc3SRichard Henderson     }
498129e9cc3SRichard Henderson }
499129e9cc3SRichard Henderson 
50096d6407fSRichard Henderson #ifdef HOST_WORDS_BIGENDIAN
50196d6407fSRichard Henderson # define HI_OFS  0
50296d6407fSRichard Henderson # define LO_OFS  4
50396d6407fSRichard Henderson #else
50496d6407fSRichard Henderson # define HI_OFS  4
50596d6407fSRichard Henderson # define LO_OFS  0
50696d6407fSRichard Henderson #endif
50796d6407fSRichard Henderson 
50896d6407fSRichard Henderson static TCGv_i32 load_frw_i32(unsigned rt)
50996d6407fSRichard Henderson {
51096d6407fSRichard Henderson     TCGv_i32 ret = tcg_temp_new_i32();
51196d6407fSRichard Henderson     tcg_gen_ld_i32(ret, cpu_env,
51296d6407fSRichard Henderson                    offsetof(CPUHPPAState, fr[rt & 31])
51396d6407fSRichard Henderson                    + (rt & 32 ? LO_OFS : HI_OFS));
51496d6407fSRichard Henderson     return ret;
51596d6407fSRichard Henderson }
51696d6407fSRichard Henderson 
517ebe9383cSRichard Henderson static TCGv_i32 load_frw0_i32(unsigned rt)
518ebe9383cSRichard Henderson {
519ebe9383cSRichard Henderson     if (rt == 0) {
520ebe9383cSRichard Henderson         return tcg_const_i32(0);
521ebe9383cSRichard Henderson     } else {
522ebe9383cSRichard Henderson         return load_frw_i32(rt);
523ebe9383cSRichard Henderson     }
524ebe9383cSRichard Henderson }
525ebe9383cSRichard Henderson 
526ebe9383cSRichard Henderson static TCGv_i64 load_frw0_i64(unsigned rt)
527ebe9383cSRichard Henderson {
528ebe9383cSRichard Henderson     if (rt == 0) {
529ebe9383cSRichard Henderson         return tcg_const_i64(0);
530ebe9383cSRichard Henderson     } else {
531ebe9383cSRichard Henderson         TCGv_i64 ret = tcg_temp_new_i64();
532ebe9383cSRichard Henderson         tcg_gen_ld32u_i64(ret, cpu_env,
533ebe9383cSRichard Henderson                           offsetof(CPUHPPAState, fr[rt & 31])
534ebe9383cSRichard Henderson                           + (rt & 32 ? LO_OFS : HI_OFS));
535ebe9383cSRichard Henderson         return ret;
536ebe9383cSRichard Henderson     }
537ebe9383cSRichard Henderson }
538ebe9383cSRichard Henderson 
53996d6407fSRichard Henderson static void save_frw_i32(unsigned rt, TCGv_i32 val)
54096d6407fSRichard Henderson {
54196d6407fSRichard Henderson     tcg_gen_st_i32(val, cpu_env,
54296d6407fSRichard Henderson                    offsetof(CPUHPPAState, fr[rt & 31])
54396d6407fSRichard Henderson                    + (rt & 32 ? LO_OFS : HI_OFS));
54496d6407fSRichard Henderson }
54596d6407fSRichard Henderson 
54696d6407fSRichard Henderson #undef HI_OFS
54796d6407fSRichard Henderson #undef LO_OFS
54896d6407fSRichard Henderson 
54996d6407fSRichard Henderson static TCGv_i64 load_frd(unsigned rt)
55096d6407fSRichard Henderson {
55196d6407fSRichard Henderson     TCGv_i64 ret = tcg_temp_new_i64();
55296d6407fSRichard Henderson     tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt]));
55396d6407fSRichard Henderson     return ret;
55496d6407fSRichard Henderson }
55596d6407fSRichard Henderson 
556ebe9383cSRichard Henderson static TCGv_i64 load_frd0(unsigned rt)
557ebe9383cSRichard Henderson {
558ebe9383cSRichard Henderson     if (rt == 0) {
559ebe9383cSRichard Henderson         return tcg_const_i64(0);
560ebe9383cSRichard Henderson     } else {
561ebe9383cSRichard Henderson         return load_frd(rt);
562ebe9383cSRichard Henderson     }
563ebe9383cSRichard Henderson }
564ebe9383cSRichard Henderson 
56596d6407fSRichard Henderson static void save_frd(unsigned rt, TCGv_i64 val)
56696d6407fSRichard Henderson {
56796d6407fSRichard Henderson     tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
56896d6407fSRichard Henderson }
56996d6407fSRichard Henderson 
570129e9cc3SRichard Henderson /* Skip over the implementation of an insn that has been nullified.
571129e9cc3SRichard Henderson    Use this when the insn is too complex for a conditional move.  */
572129e9cc3SRichard Henderson static void nullify_over(DisasContext *ctx)
573129e9cc3SRichard Henderson {
574129e9cc3SRichard Henderson     if (ctx->null_cond.c != TCG_COND_NEVER) {
575129e9cc3SRichard Henderson         /* The always condition should have been handled in the main loop.  */
576129e9cc3SRichard Henderson         assert(ctx->null_cond.c != TCG_COND_ALWAYS);
577129e9cc3SRichard Henderson 
578129e9cc3SRichard Henderson         ctx->null_lab = gen_new_label();
579129e9cc3SRichard Henderson         cond_prep(&ctx->null_cond);
580129e9cc3SRichard Henderson 
581129e9cc3SRichard Henderson         /* If we're using PSW[N], copy it to a temp because... */
582129e9cc3SRichard Henderson         if (ctx->null_cond.a0_is_n) {
583129e9cc3SRichard Henderson             ctx->null_cond.a0_is_n = false;
584129e9cc3SRichard Henderson             ctx->null_cond.a0 = tcg_temp_new();
585eaa3783bSRichard Henderson             tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
586129e9cc3SRichard Henderson         }
587129e9cc3SRichard Henderson         /* ... we clear it before branching over the implementation,
588129e9cc3SRichard Henderson            so that (1) it's clear after nullifying this insn and
589129e9cc3SRichard Henderson            (2) if this insn nullifies the next, PSW[N] is valid.  */
590129e9cc3SRichard Henderson         if (ctx->psw_n_nonzero) {
591129e9cc3SRichard Henderson             ctx->psw_n_nonzero = false;
592eaa3783bSRichard Henderson             tcg_gen_movi_reg(cpu_psw_n, 0);
593129e9cc3SRichard Henderson         }
594129e9cc3SRichard Henderson 
595eaa3783bSRichard Henderson         tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0,
596129e9cc3SRichard Henderson                           ctx->null_cond.a1, ctx->null_lab);
597129e9cc3SRichard Henderson         cond_free(&ctx->null_cond);
598129e9cc3SRichard Henderson     }
599129e9cc3SRichard Henderson }
600129e9cc3SRichard Henderson 
601129e9cc3SRichard Henderson /* Save the current nullification state to PSW[N].  */
602129e9cc3SRichard Henderson static void nullify_save(DisasContext *ctx)
603129e9cc3SRichard Henderson {
604129e9cc3SRichard Henderson     if (ctx->null_cond.c == TCG_COND_NEVER) {
605129e9cc3SRichard Henderson         if (ctx->psw_n_nonzero) {
606eaa3783bSRichard Henderson             tcg_gen_movi_reg(cpu_psw_n, 0);
607129e9cc3SRichard Henderson         }
608129e9cc3SRichard Henderson         return;
609129e9cc3SRichard Henderson     }
610129e9cc3SRichard Henderson     if (!ctx->null_cond.a0_is_n) {
611129e9cc3SRichard Henderson         cond_prep(&ctx->null_cond);
612eaa3783bSRichard Henderson         tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n,
613129e9cc3SRichard Henderson                            ctx->null_cond.a0, ctx->null_cond.a1);
614129e9cc3SRichard Henderson         ctx->psw_n_nonzero = true;
615129e9cc3SRichard Henderson     }
616129e9cc3SRichard Henderson     cond_free(&ctx->null_cond);
617129e9cc3SRichard Henderson }
618129e9cc3SRichard Henderson 
619129e9cc3SRichard Henderson /* Set a PSW[N] to X.  The intention is that this is used immediately
620129e9cc3SRichard Henderson    before a goto_tb/exit_tb, so that there is no fallthru path to other
621129e9cc3SRichard Henderson    code within the TB.  Therefore we do not update psw_n_nonzero.  */
622129e9cc3SRichard Henderson static void nullify_set(DisasContext *ctx, bool x)
623129e9cc3SRichard Henderson {
624129e9cc3SRichard Henderson     if (ctx->psw_n_nonzero || x) {
625eaa3783bSRichard Henderson         tcg_gen_movi_reg(cpu_psw_n, x);
626129e9cc3SRichard Henderson     }
627129e9cc3SRichard Henderson }
628129e9cc3SRichard Henderson 
629129e9cc3SRichard Henderson /* Mark the end of an instruction that may have been nullified.
630129e9cc3SRichard Henderson    This is the pair to nullify_over.  */
631869051eaSRichard Henderson static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
632129e9cc3SRichard Henderson {
633129e9cc3SRichard Henderson     TCGLabel *null_lab = ctx->null_lab;
634129e9cc3SRichard Henderson 
635129e9cc3SRichard Henderson     if (likely(null_lab == NULL)) {
636129e9cc3SRichard Henderson         /* The current insn wasn't conditional or handled the condition
637129e9cc3SRichard Henderson            applied to it without a branch, so the (new) setting of
638129e9cc3SRichard Henderson            NULL_COND can be applied directly to the next insn.  */
639129e9cc3SRichard Henderson         return status;
640129e9cc3SRichard Henderson     }
641129e9cc3SRichard Henderson     ctx->null_lab = NULL;
642129e9cc3SRichard Henderson 
643129e9cc3SRichard Henderson     if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
644129e9cc3SRichard Henderson         /* The next instruction will be unconditional,
645129e9cc3SRichard Henderson            and NULL_COND already reflects that.  */
646129e9cc3SRichard Henderson         gen_set_label(null_lab);
647129e9cc3SRichard Henderson     } else {
648129e9cc3SRichard Henderson         /* The insn that we just executed is itself nullifying the next
649129e9cc3SRichard Henderson            instruction.  Store the condition in the PSW[N] global.
650129e9cc3SRichard Henderson            We asserted PSW[N] = 0 in nullify_over, so that after the
651129e9cc3SRichard Henderson            label we have the proper value in place.  */
652129e9cc3SRichard Henderson         nullify_save(ctx);
653129e9cc3SRichard Henderson         gen_set_label(null_lab);
654129e9cc3SRichard Henderson         ctx->null_cond = cond_make_n();
655129e9cc3SRichard Henderson     }
656129e9cc3SRichard Henderson 
657869051eaSRichard Henderson     assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED);
658869051eaSRichard Henderson     if (status == DISAS_NORETURN) {
659869051eaSRichard Henderson         status = DISAS_NEXT;
660129e9cc3SRichard Henderson     }
661129e9cc3SRichard Henderson     return status;
662129e9cc3SRichard Henderson }
663129e9cc3SRichard Henderson 
664eaa3783bSRichard Henderson static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
66561766fe9SRichard Henderson {
66661766fe9SRichard Henderson     if (unlikely(ival == -1)) {
667eaa3783bSRichard Henderson         tcg_gen_mov_reg(dest, vval);
66861766fe9SRichard Henderson     } else {
669eaa3783bSRichard Henderson         tcg_gen_movi_reg(dest, ival);
67061766fe9SRichard Henderson     }
67161766fe9SRichard Henderson }
67261766fe9SRichard Henderson 
673eaa3783bSRichard Henderson static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp)
67461766fe9SRichard Henderson {
67561766fe9SRichard Henderson     return ctx->iaoq_f + disp + 8;
67661766fe9SRichard Henderson }
67761766fe9SRichard Henderson 
67861766fe9SRichard Henderson static void gen_excp_1(int exception)
67961766fe9SRichard Henderson {
68061766fe9SRichard Henderson     TCGv_i32 t = tcg_const_i32(exception);
68161766fe9SRichard Henderson     gen_helper_excp(cpu_env, t);
68261766fe9SRichard Henderson     tcg_temp_free_i32(t);
68361766fe9SRichard Henderson }
68461766fe9SRichard Henderson 
685869051eaSRichard Henderson static DisasJumpType gen_excp(DisasContext *ctx, int exception)
68661766fe9SRichard Henderson {
68761766fe9SRichard Henderson     copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
68861766fe9SRichard Henderson     copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
689129e9cc3SRichard Henderson     nullify_save(ctx);
69061766fe9SRichard Henderson     gen_excp_1(exception);
691869051eaSRichard Henderson     return DISAS_NORETURN;
69261766fe9SRichard Henderson }
69361766fe9SRichard Henderson 
694869051eaSRichard Henderson static DisasJumpType gen_illegal(DisasContext *ctx)
69561766fe9SRichard Henderson {
696129e9cc3SRichard Henderson     nullify_over(ctx);
6972986721dSRichard Henderson     return nullify_end(ctx, gen_excp(ctx, EXCP_ILL));
69861766fe9SRichard Henderson }
69961766fe9SRichard Henderson 
700eaa3783bSRichard Henderson static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
70161766fe9SRichard Henderson {
70261766fe9SRichard Henderson     /* Suppress goto_tb in the case of single-steping and IO.  */
703c5a49c63SEmilio G. Cota     if ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ctx->base.singlestep_enabled) {
70461766fe9SRichard Henderson         return false;
70561766fe9SRichard Henderson     }
70661766fe9SRichard Henderson     return true;
70761766fe9SRichard Henderson }
70861766fe9SRichard Henderson 
709129e9cc3SRichard Henderson /* If the next insn is to be nullified, and it's on the same page,
710129e9cc3SRichard Henderson    and we're not attempting to set a breakpoint on it, then we can
711129e9cc3SRichard Henderson    totally skip the nullified insn.  This avoids creating and
712129e9cc3SRichard Henderson    executing a TB that merely branches to the next TB.  */
713129e9cc3SRichard Henderson static bool use_nullify_skip(DisasContext *ctx)
714129e9cc3SRichard Henderson {
715129e9cc3SRichard Henderson     return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
716129e9cc3SRichard Henderson             && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
717129e9cc3SRichard Henderson }
718129e9cc3SRichard Henderson 
71961766fe9SRichard Henderson static void gen_goto_tb(DisasContext *ctx, int which,
720eaa3783bSRichard Henderson                         target_ureg f, target_ureg b)
72161766fe9SRichard Henderson {
72261766fe9SRichard Henderson     if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
72361766fe9SRichard Henderson         tcg_gen_goto_tb(which);
724eaa3783bSRichard Henderson         tcg_gen_movi_reg(cpu_iaoq_f, f);
725eaa3783bSRichard Henderson         tcg_gen_movi_reg(cpu_iaoq_b, b);
726d01a3625SRichard Henderson         tcg_gen_exit_tb((uintptr_t)ctx->base.tb + which);
72761766fe9SRichard Henderson     } else {
72861766fe9SRichard Henderson         copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
72961766fe9SRichard Henderson         copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
730d01a3625SRichard Henderson         if (ctx->base.singlestep_enabled) {
73161766fe9SRichard Henderson             gen_excp_1(EXCP_DEBUG);
73261766fe9SRichard Henderson         } else {
7337f11636dSEmilio G. Cota             tcg_gen_lookup_and_goto_ptr();
73461766fe9SRichard Henderson         }
73561766fe9SRichard Henderson     }
73661766fe9SRichard Henderson }
73761766fe9SRichard Henderson 
738b2167459SRichard Henderson /* PA has a habit of taking the LSB of a field and using that as the sign,
739b2167459SRichard Henderson    with the rest of the field becoming the least significant bits.  */
740eaa3783bSRichard Henderson static target_sreg low_sextract(uint32_t val, int pos, int len)
741b2167459SRichard Henderson {
742eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)extract32(val, pos, 1);
743b2167459SRichard Henderson     x = (x << (len - 1)) | extract32(val, pos + 1, len - 1);
744b2167459SRichard Henderson     return x;
745b2167459SRichard Henderson }
746b2167459SRichard Henderson 
747ebe9383cSRichard Henderson static unsigned assemble_rt64(uint32_t insn)
748ebe9383cSRichard Henderson {
749ebe9383cSRichard Henderson     unsigned r1 = extract32(insn, 6, 1);
750ebe9383cSRichard Henderson     unsigned r0 = extract32(insn, 0, 5);
751ebe9383cSRichard Henderson     return r1 * 32 + r0;
752ebe9383cSRichard Henderson }
753ebe9383cSRichard Henderson 
754ebe9383cSRichard Henderson static unsigned assemble_ra64(uint32_t insn)
755ebe9383cSRichard Henderson {
756ebe9383cSRichard Henderson     unsigned r1 = extract32(insn, 7, 1);
757ebe9383cSRichard Henderson     unsigned r0 = extract32(insn, 21, 5);
758ebe9383cSRichard Henderson     return r1 * 32 + r0;
759ebe9383cSRichard Henderson }
760ebe9383cSRichard Henderson 
761ebe9383cSRichard Henderson static unsigned assemble_rb64(uint32_t insn)
762ebe9383cSRichard Henderson {
763ebe9383cSRichard Henderson     unsigned r1 = extract32(insn, 12, 1);
764ebe9383cSRichard Henderson     unsigned r0 = extract32(insn, 16, 5);
765ebe9383cSRichard Henderson     return r1 * 32 + r0;
766ebe9383cSRichard Henderson }
767ebe9383cSRichard Henderson 
768ebe9383cSRichard Henderson static unsigned assemble_rc64(uint32_t insn)
769ebe9383cSRichard Henderson {
770ebe9383cSRichard Henderson     unsigned r2 = extract32(insn, 8, 1);
771ebe9383cSRichard Henderson     unsigned r1 = extract32(insn, 13, 3);
772ebe9383cSRichard Henderson     unsigned r0 = extract32(insn, 9, 2);
773ebe9383cSRichard Henderson     return r2 * 32 + r1 * 4 + r0;
774ebe9383cSRichard Henderson }
775ebe9383cSRichard Henderson 
776eaa3783bSRichard Henderson static target_sreg assemble_12(uint32_t insn)
77798cd9ca7SRichard Henderson {
778eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)(insn & 1);
77998cd9ca7SRichard Henderson     x = (x <<  1) | extract32(insn, 2, 1);
78098cd9ca7SRichard Henderson     x = (x << 10) | extract32(insn, 3, 10);
78198cd9ca7SRichard Henderson     return x;
78298cd9ca7SRichard Henderson }
78398cd9ca7SRichard Henderson 
784eaa3783bSRichard Henderson static target_sreg assemble_16(uint32_t insn)
785b2167459SRichard Henderson {
786b2167459SRichard Henderson     /* Take the name from PA2.0, which produces a 16-bit number
787b2167459SRichard Henderson        only with wide mode; otherwise a 14-bit number.  Since we don't
788b2167459SRichard Henderson        implement wide mode, this is always the 14-bit number.  */
789b2167459SRichard Henderson     return low_sextract(insn, 0, 14);
790b2167459SRichard Henderson }
791b2167459SRichard Henderson 
792eaa3783bSRichard Henderson static target_sreg assemble_16a(uint32_t insn)
79396d6407fSRichard Henderson {
79496d6407fSRichard Henderson     /* Take the name from PA2.0, which produces a 14-bit shifted number
79596d6407fSRichard Henderson        only with wide mode; otherwise a 12-bit shifted number.  Since we
79696d6407fSRichard Henderson        don't implement wide mode, this is always the 12-bit number.  */
797eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)(insn & 1);
79896d6407fSRichard Henderson     x = (x << 11) | extract32(insn, 2, 11);
79996d6407fSRichard Henderson     return x << 2;
80096d6407fSRichard Henderson }
80196d6407fSRichard Henderson 
802eaa3783bSRichard Henderson static target_sreg assemble_17(uint32_t insn)
80398cd9ca7SRichard Henderson {
804eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)(insn & 1);
80598cd9ca7SRichard Henderson     x = (x <<  5) | extract32(insn, 16, 5);
80698cd9ca7SRichard Henderson     x = (x <<  1) | extract32(insn, 2, 1);
80798cd9ca7SRichard Henderson     x = (x << 10) | extract32(insn, 3, 10);
80898cd9ca7SRichard Henderson     return x << 2;
80998cd9ca7SRichard Henderson }
81098cd9ca7SRichard Henderson 
811eaa3783bSRichard Henderson static target_sreg assemble_21(uint32_t insn)
812b2167459SRichard Henderson {
813eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)(insn & 1);
814b2167459SRichard Henderson     x = (x << 11) | extract32(insn, 1, 11);
815b2167459SRichard Henderson     x = (x <<  2) | extract32(insn, 14, 2);
816b2167459SRichard Henderson     x = (x <<  5) | extract32(insn, 16, 5);
817b2167459SRichard Henderson     x = (x <<  2) | extract32(insn, 12, 2);
818b2167459SRichard Henderson     return x << 11;
819b2167459SRichard Henderson }
820b2167459SRichard Henderson 
821eaa3783bSRichard Henderson static target_sreg assemble_22(uint32_t insn)
82298cd9ca7SRichard Henderson {
823eaa3783bSRichard Henderson     target_ureg x = -(target_ureg)(insn & 1);
82498cd9ca7SRichard Henderson     x = (x << 10) | extract32(insn, 16, 10);
82598cd9ca7SRichard Henderson     x = (x <<  1) | extract32(insn, 2, 1);
82698cd9ca7SRichard Henderson     x = (x << 10) | extract32(insn, 3, 10);
82798cd9ca7SRichard Henderson     return x << 2;
82898cd9ca7SRichard Henderson }
82998cd9ca7SRichard Henderson 
830b2167459SRichard Henderson /* The parisc documentation describes only the general interpretation of
831b2167459SRichard Henderson    the conditions, without describing their exact implementation.  The
832b2167459SRichard Henderson    interpretations do not stand up well when considering ADD,C and SUB,B.
833b2167459SRichard Henderson    However, considering the Addition, Subtraction and Logical conditions
834b2167459SRichard Henderson    as a whole it would appear that these relations are similar to what
835b2167459SRichard Henderson    a traditional NZCV set of flags would produce.  */
836b2167459SRichard Henderson 
837eaa3783bSRichard Henderson static DisasCond do_cond(unsigned cf, TCGv_reg res,
838eaa3783bSRichard Henderson                          TCGv_reg cb_msb, TCGv_reg sv)
839b2167459SRichard Henderson {
840b2167459SRichard Henderson     DisasCond cond;
841eaa3783bSRichard Henderson     TCGv_reg tmp;
842b2167459SRichard Henderson 
843b2167459SRichard Henderson     switch (cf >> 1) {
844b2167459SRichard Henderson     case 0: /* Never / TR */
845b2167459SRichard Henderson         cond = cond_make_f();
846b2167459SRichard Henderson         break;
847b2167459SRichard Henderson     case 1: /* = / <>        (Z / !Z) */
848b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_EQ, res);
849b2167459SRichard Henderson         break;
850b2167459SRichard Henderson     case 2: /* < / >=        (N / !N) */
851b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_LT, res);
852b2167459SRichard Henderson         break;
853b2167459SRichard Henderson     case 3: /* <= / >        (N | Z / !N & !Z) */
854b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_LE, res);
855b2167459SRichard Henderson         break;
856b2167459SRichard Henderson     case 4: /* NUV / UV      (!C / C) */
857b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_EQ, cb_msb);
858b2167459SRichard Henderson         break;
859b2167459SRichard Henderson     case 5: /* ZNV / VNZ     (!C | Z / C & !Z) */
860b2167459SRichard Henderson         tmp = tcg_temp_new();
861eaa3783bSRichard Henderson         tcg_gen_neg_reg(tmp, cb_msb);
862eaa3783bSRichard Henderson         tcg_gen_and_reg(tmp, tmp, res);
863b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_EQ, tmp);
864b2167459SRichard Henderson         tcg_temp_free(tmp);
865b2167459SRichard Henderson         break;
866b2167459SRichard Henderson     case 6: /* SV / NSV      (V / !V) */
867b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_LT, sv);
868b2167459SRichard Henderson         break;
869b2167459SRichard Henderson     case 7: /* OD / EV */
870b2167459SRichard Henderson         tmp = tcg_temp_new();
871eaa3783bSRichard Henderson         tcg_gen_andi_reg(tmp, res, 1);
872b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, tmp);
873b2167459SRichard Henderson         tcg_temp_free(tmp);
874b2167459SRichard Henderson         break;
875b2167459SRichard Henderson     default:
876b2167459SRichard Henderson         g_assert_not_reached();
877b2167459SRichard Henderson     }
878b2167459SRichard Henderson     if (cf & 1) {
879b2167459SRichard Henderson         cond.c = tcg_invert_cond(cond.c);
880b2167459SRichard Henderson     }
881b2167459SRichard Henderson 
882b2167459SRichard Henderson     return cond;
883b2167459SRichard Henderson }
884b2167459SRichard Henderson 
885b2167459SRichard Henderson /* Similar, but for the special case of subtraction without borrow, we
886b2167459SRichard Henderson    can use the inputs directly.  This can allow other computation to be
887b2167459SRichard Henderson    deleted as unused.  */
888b2167459SRichard Henderson 
889eaa3783bSRichard Henderson static DisasCond do_sub_cond(unsigned cf, TCGv_reg res,
890eaa3783bSRichard Henderson                              TCGv_reg in1, TCGv_reg in2, TCGv_reg sv)
891b2167459SRichard Henderson {
892b2167459SRichard Henderson     DisasCond cond;
893b2167459SRichard Henderson 
894b2167459SRichard Henderson     switch (cf >> 1) {
895b2167459SRichard Henderson     case 1: /* = / <> */
896b2167459SRichard Henderson         cond = cond_make(TCG_COND_EQ, in1, in2);
897b2167459SRichard Henderson         break;
898b2167459SRichard Henderson     case 2: /* < / >= */
899b2167459SRichard Henderson         cond = cond_make(TCG_COND_LT, in1, in2);
900b2167459SRichard Henderson         break;
901b2167459SRichard Henderson     case 3: /* <= / > */
902b2167459SRichard Henderson         cond = cond_make(TCG_COND_LE, in1, in2);
903b2167459SRichard Henderson         break;
904b2167459SRichard Henderson     case 4: /* << / >>= */
905b2167459SRichard Henderson         cond = cond_make(TCG_COND_LTU, in1, in2);
906b2167459SRichard Henderson         break;
907b2167459SRichard Henderson     case 5: /* <<= / >> */
908b2167459SRichard Henderson         cond = cond_make(TCG_COND_LEU, in1, in2);
909b2167459SRichard Henderson         break;
910b2167459SRichard Henderson     default:
911b2167459SRichard Henderson         return do_cond(cf, res, sv, sv);
912b2167459SRichard Henderson     }
913b2167459SRichard Henderson     if (cf & 1) {
914b2167459SRichard Henderson         cond.c = tcg_invert_cond(cond.c);
915b2167459SRichard Henderson     }
916b2167459SRichard Henderson 
917b2167459SRichard Henderson     return cond;
918b2167459SRichard Henderson }
919b2167459SRichard Henderson 
920b2167459SRichard Henderson /* Similar, but for logicals, where the carry and overflow bits are not
921b2167459SRichard Henderson    computed, and use of them is undefined.  */
922b2167459SRichard Henderson 
923eaa3783bSRichard Henderson static DisasCond do_log_cond(unsigned cf, TCGv_reg res)
924b2167459SRichard Henderson {
925b2167459SRichard Henderson     switch (cf >> 1) {
926b2167459SRichard Henderson     case 4: case 5: case 6:
927b2167459SRichard Henderson         cf &= 1;
928b2167459SRichard Henderson         break;
929b2167459SRichard Henderson     }
930b2167459SRichard Henderson     return do_cond(cf, res, res, res);
931b2167459SRichard Henderson }
932b2167459SRichard Henderson 
93398cd9ca7SRichard Henderson /* Similar, but for shift/extract/deposit conditions.  */
93498cd9ca7SRichard Henderson 
935eaa3783bSRichard Henderson static DisasCond do_sed_cond(unsigned orig, TCGv_reg res)
93698cd9ca7SRichard Henderson {
93798cd9ca7SRichard Henderson     unsigned c, f;
93898cd9ca7SRichard Henderson 
93998cd9ca7SRichard Henderson     /* Convert the compressed condition codes to standard.
94098cd9ca7SRichard Henderson        0-2 are the same as logicals (nv,<,<=), while 3 is OD.
94198cd9ca7SRichard Henderson        4-7 are the reverse of 0-3.  */
94298cd9ca7SRichard Henderson     c = orig & 3;
94398cd9ca7SRichard Henderson     if (c == 3) {
94498cd9ca7SRichard Henderson         c = 7;
94598cd9ca7SRichard Henderson     }
94698cd9ca7SRichard Henderson     f = (orig & 4) / 4;
94798cd9ca7SRichard Henderson 
94898cd9ca7SRichard Henderson     return do_log_cond(c * 2 + f, res);
94998cd9ca7SRichard Henderson }
95098cd9ca7SRichard Henderson 
951b2167459SRichard Henderson /* Similar, but for unit conditions.  */
952b2167459SRichard Henderson 
953eaa3783bSRichard Henderson static DisasCond do_unit_cond(unsigned cf, TCGv_reg res,
954eaa3783bSRichard Henderson                               TCGv_reg in1, TCGv_reg in2)
955b2167459SRichard Henderson {
956b2167459SRichard Henderson     DisasCond cond;
957eaa3783bSRichard Henderson     TCGv_reg tmp, cb = NULL;
958b2167459SRichard Henderson 
959b2167459SRichard Henderson     if (cf & 8) {
960b2167459SRichard Henderson         /* Since we want to test lots of carry-out bits all at once, do not
961b2167459SRichard Henderson          * do our normal thing and compute carry-in of bit B+1 since that
962b2167459SRichard Henderson          * leaves us with carry bits spread across two words.
963b2167459SRichard Henderson          */
964b2167459SRichard Henderson         cb = tcg_temp_new();
965b2167459SRichard Henderson         tmp = tcg_temp_new();
966eaa3783bSRichard Henderson         tcg_gen_or_reg(cb, in1, in2);
967eaa3783bSRichard Henderson         tcg_gen_and_reg(tmp, in1, in2);
968eaa3783bSRichard Henderson         tcg_gen_andc_reg(cb, cb, res);
969eaa3783bSRichard Henderson         tcg_gen_or_reg(cb, cb, tmp);
970b2167459SRichard Henderson         tcg_temp_free(tmp);
971b2167459SRichard Henderson     }
972b2167459SRichard Henderson 
973b2167459SRichard Henderson     switch (cf >> 1) {
974b2167459SRichard Henderson     case 0: /* never / TR */
975b2167459SRichard Henderson     case 1: /* undefined */
976b2167459SRichard Henderson     case 5: /* undefined */
977b2167459SRichard Henderson         cond = cond_make_f();
978b2167459SRichard Henderson         break;
979b2167459SRichard Henderson 
980b2167459SRichard Henderson     case 2: /* SBZ / NBZ */
981b2167459SRichard Henderson         /* See hasless(v,1) from
982b2167459SRichard Henderson          * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
983b2167459SRichard Henderson          */
984b2167459SRichard Henderson         tmp = tcg_temp_new();
985eaa3783bSRichard Henderson         tcg_gen_subi_reg(tmp, res, 0x01010101u);
986eaa3783bSRichard Henderson         tcg_gen_andc_reg(tmp, tmp, res);
987eaa3783bSRichard Henderson         tcg_gen_andi_reg(tmp, tmp, 0x80808080u);
988b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, tmp);
989b2167459SRichard Henderson         tcg_temp_free(tmp);
990b2167459SRichard Henderson         break;
991b2167459SRichard Henderson 
992b2167459SRichard Henderson     case 3: /* SHZ / NHZ */
993b2167459SRichard Henderson         tmp = tcg_temp_new();
994eaa3783bSRichard Henderson         tcg_gen_subi_reg(tmp, res, 0x00010001u);
995eaa3783bSRichard Henderson         tcg_gen_andc_reg(tmp, tmp, res);
996eaa3783bSRichard Henderson         tcg_gen_andi_reg(tmp, tmp, 0x80008000u);
997b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, tmp);
998b2167459SRichard Henderson         tcg_temp_free(tmp);
999b2167459SRichard Henderson         break;
1000b2167459SRichard Henderson 
1001b2167459SRichard Henderson     case 4: /* SDC / NDC */
1002eaa3783bSRichard Henderson         tcg_gen_andi_reg(cb, cb, 0x88888888u);
1003b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, cb);
1004b2167459SRichard Henderson         break;
1005b2167459SRichard Henderson 
1006b2167459SRichard Henderson     case 6: /* SBC / NBC */
1007eaa3783bSRichard Henderson         tcg_gen_andi_reg(cb, cb, 0x80808080u);
1008b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, cb);
1009b2167459SRichard Henderson         break;
1010b2167459SRichard Henderson 
1011b2167459SRichard Henderson     case 7: /* SHC / NHC */
1012eaa3783bSRichard Henderson         tcg_gen_andi_reg(cb, cb, 0x80008000u);
1013b2167459SRichard Henderson         cond = cond_make_0(TCG_COND_NE, cb);
1014b2167459SRichard Henderson         break;
1015b2167459SRichard Henderson 
1016b2167459SRichard Henderson     default:
1017b2167459SRichard Henderson         g_assert_not_reached();
1018b2167459SRichard Henderson     }
1019b2167459SRichard Henderson     if (cf & 8) {
1020b2167459SRichard Henderson         tcg_temp_free(cb);
1021b2167459SRichard Henderson     }
1022b2167459SRichard Henderson     if (cf & 1) {
1023b2167459SRichard Henderson         cond.c = tcg_invert_cond(cond.c);
1024b2167459SRichard Henderson     }
1025b2167459SRichard Henderson 
1026b2167459SRichard Henderson     return cond;
1027b2167459SRichard Henderson }
1028b2167459SRichard Henderson 
1029b2167459SRichard Henderson /* Compute signed overflow for addition.  */
1030eaa3783bSRichard Henderson static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res,
1031eaa3783bSRichard Henderson                           TCGv_reg in1, TCGv_reg in2)
1032b2167459SRichard Henderson {
1033eaa3783bSRichard Henderson     TCGv_reg sv = get_temp(ctx);
1034eaa3783bSRichard Henderson     TCGv_reg tmp = tcg_temp_new();
1035b2167459SRichard Henderson 
1036eaa3783bSRichard Henderson     tcg_gen_xor_reg(sv, res, in1);
1037eaa3783bSRichard Henderson     tcg_gen_xor_reg(tmp, in1, in2);
1038eaa3783bSRichard Henderson     tcg_gen_andc_reg(sv, sv, tmp);
1039b2167459SRichard Henderson     tcg_temp_free(tmp);
1040b2167459SRichard Henderson 
1041b2167459SRichard Henderson     return sv;
1042b2167459SRichard Henderson }
1043b2167459SRichard Henderson 
1044b2167459SRichard Henderson /* Compute signed overflow for subtraction.  */
1045eaa3783bSRichard Henderson static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res,
1046eaa3783bSRichard Henderson                           TCGv_reg in1, TCGv_reg in2)
1047b2167459SRichard Henderson {
1048eaa3783bSRichard Henderson     TCGv_reg sv = get_temp(ctx);
1049eaa3783bSRichard Henderson     TCGv_reg tmp = tcg_temp_new();
1050b2167459SRichard Henderson 
1051eaa3783bSRichard Henderson     tcg_gen_xor_reg(sv, res, in1);
1052eaa3783bSRichard Henderson     tcg_gen_xor_reg(tmp, in1, in2);
1053eaa3783bSRichard Henderson     tcg_gen_and_reg(sv, sv, tmp);
1054b2167459SRichard Henderson     tcg_temp_free(tmp);
1055b2167459SRichard Henderson 
1056b2167459SRichard Henderson     return sv;
1057b2167459SRichard Henderson }
1058b2167459SRichard Henderson 
1059eaa3783bSRichard Henderson static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1060eaa3783bSRichard Henderson                             TCGv_reg in2, unsigned shift, bool is_l,
1061eaa3783bSRichard Henderson                             bool is_tsv, bool is_tc, bool is_c, unsigned cf)
1062b2167459SRichard Henderson {
1063eaa3783bSRichard Henderson     TCGv_reg dest, cb, cb_msb, sv, tmp;
1064b2167459SRichard Henderson     unsigned c = cf >> 1;
1065b2167459SRichard Henderson     DisasCond cond;
1066b2167459SRichard Henderson 
1067b2167459SRichard Henderson     dest = tcg_temp_new();
1068f764718dSRichard Henderson     cb = NULL;
1069f764718dSRichard Henderson     cb_msb = NULL;
1070b2167459SRichard Henderson 
1071b2167459SRichard Henderson     if (shift) {
1072b2167459SRichard Henderson         tmp = get_temp(ctx);
1073eaa3783bSRichard Henderson         tcg_gen_shli_reg(tmp, in1, shift);
1074b2167459SRichard Henderson         in1 = tmp;
1075b2167459SRichard Henderson     }
1076b2167459SRichard Henderson 
1077b2167459SRichard Henderson     if (!is_l || c == 4 || c == 5) {
1078eaa3783bSRichard Henderson         TCGv_reg zero = tcg_const_reg(0);
1079b2167459SRichard Henderson         cb_msb = get_temp(ctx);
1080eaa3783bSRichard Henderson         tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
1081b2167459SRichard Henderson         if (is_c) {
1082eaa3783bSRichard Henderson             tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
1083b2167459SRichard Henderson         }
1084b2167459SRichard Henderson         tcg_temp_free(zero);
1085b2167459SRichard Henderson         if (!is_l) {
1086b2167459SRichard Henderson             cb = get_temp(ctx);
1087eaa3783bSRichard Henderson             tcg_gen_xor_reg(cb, in1, in2);
1088eaa3783bSRichard Henderson             tcg_gen_xor_reg(cb, cb, dest);
1089b2167459SRichard Henderson         }
1090b2167459SRichard Henderson     } else {
1091eaa3783bSRichard Henderson         tcg_gen_add_reg(dest, in1, in2);
1092b2167459SRichard Henderson         if (is_c) {
1093eaa3783bSRichard Henderson             tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
1094b2167459SRichard Henderson         }
1095b2167459SRichard Henderson     }
1096b2167459SRichard Henderson 
1097b2167459SRichard Henderson     /* Compute signed overflow if required.  */
1098f764718dSRichard Henderson     sv = NULL;
1099b2167459SRichard Henderson     if (is_tsv || c == 6) {
1100b2167459SRichard Henderson         sv = do_add_sv(ctx, dest, in1, in2);
1101b2167459SRichard Henderson         if (is_tsv) {
1102b2167459SRichard Henderson             /* ??? Need to include overflow from shift.  */
1103b2167459SRichard Henderson             gen_helper_tsv(cpu_env, sv);
1104b2167459SRichard Henderson         }
1105b2167459SRichard Henderson     }
1106b2167459SRichard Henderson 
1107b2167459SRichard Henderson     /* Emit any conditional trap before any writeback.  */
1108b2167459SRichard Henderson     cond = do_cond(cf, dest, cb_msb, sv);
1109b2167459SRichard Henderson     if (is_tc) {
1110b2167459SRichard Henderson         cond_prep(&cond);
1111b2167459SRichard Henderson         tmp = tcg_temp_new();
1112eaa3783bSRichard Henderson         tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1113b2167459SRichard Henderson         gen_helper_tcond(cpu_env, tmp);
1114b2167459SRichard Henderson         tcg_temp_free(tmp);
1115b2167459SRichard Henderson     }
1116b2167459SRichard Henderson 
1117b2167459SRichard Henderson     /* Write back the result.  */
1118b2167459SRichard Henderson     if (!is_l) {
1119b2167459SRichard Henderson         save_or_nullify(ctx, cpu_psw_cb, cb);
1120b2167459SRichard Henderson         save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1121b2167459SRichard Henderson     }
1122b2167459SRichard Henderson     save_gpr(ctx, rt, dest);
1123b2167459SRichard Henderson     tcg_temp_free(dest);
1124b2167459SRichard Henderson 
1125b2167459SRichard Henderson     /* Install the new nullification.  */
1126b2167459SRichard Henderson     cond_free(&ctx->null_cond);
1127b2167459SRichard Henderson     ctx->null_cond = cond;
1128869051eaSRichard Henderson     return DISAS_NEXT;
1129b2167459SRichard Henderson }
1130b2167459SRichard Henderson 
1131eaa3783bSRichard Henderson static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1132eaa3783bSRichard Henderson                             TCGv_reg in2, bool is_tsv, bool is_b,
1133eaa3783bSRichard Henderson                             bool is_tc, unsigned cf)
1134b2167459SRichard Henderson {
1135eaa3783bSRichard Henderson     TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
1136b2167459SRichard Henderson     unsigned c = cf >> 1;
1137b2167459SRichard Henderson     DisasCond cond;
1138b2167459SRichard Henderson 
1139b2167459SRichard Henderson     dest = tcg_temp_new();
1140b2167459SRichard Henderson     cb = tcg_temp_new();
1141b2167459SRichard Henderson     cb_msb = tcg_temp_new();
1142b2167459SRichard Henderson 
1143eaa3783bSRichard Henderson     zero = tcg_const_reg(0);
1144b2167459SRichard Henderson     if (is_b) {
1145b2167459SRichard Henderson         /* DEST,C = IN1 + ~IN2 + C.  */
1146eaa3783bSRichard Henderson         tcg_gen_not_reg(cb, in2);
1147eaa3783bSRichard Henderson         tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
1148eaa3783bSRichard Henderson         tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
1149eaa3783bSRichard Henderson         tcg_gen_xor_reg(cb, cb, in1);
1150eaa3783bSRichard Henderson         tcg_gen_xor_reg(cb, cb, dest);
1151b2167459SRichard Henderson     } else {
1152b2167459SRichard Henderson         /* DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
1153b2167459SRichard Henderson            operations by seeding the high word with 1 and subtracting.  */
1154eaa3783bSRichard Henderson         tcg_gen_movi_reg(cb_msb, 1);
1155eaa3783bSRichard Henderson         tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero);
1156eaa3783bSRichard Henderson         tcg_gen_eqv_reg(cb, in1, in2);
1157eaa3783bSRichard Henderson         tcg_gen_xor_reg(cb, cb, dest);
1158b2167459SRichard Henderson     }
1159b2167459SRichard Henderson     tcg_temp_free(zero);
1160b2167459SRichard Henderson 
1161b2167459SRichard Henderson     /* Compute signed overflow if required.  */
1162f764718dSRichard Henderson     sv = NULL;
1163b2167459SRichard Henderson     if (is_tsv || c == 6) {
1164b2167459SRichard Henderson         sv = do_sub_sv(ctx, dest, in1, in2);
1165b2167459SRichard Henderson         if (is_tsv) {
1166b2167459SRichard Henderson             gen_helper_tsv(cpu_env, sv);
1167b2167459SRichard Henderson         }
1168b2167459SRichard Henderson     }
1169b2167459SRichard Henderson 
1170b2167459SRichard Henderson     /* Compute the condition.  We cannot use the special case for borrow.  */
1171b2167459SRichard Henderson     if (!is_b) {
1172b2167459SRichard Henderson         cond = do_sub_cond(cf, dest, in1, in2, sv);
1173b2167459SRichard Henderson     } else {
1174b2167459SRichard Henderson         cond = do_cond(cf, dest, cb_msb, sv);
1175b2167459SRichard Henderson     }
1176b2167459SRichard Henderson 
1177b2167459SRichard Henderson     /* Emit any conditional trap before any writeback.  */
1178b2167459SRichard Henderson     if (is_tc) {
1179b2167459SRichard Henderson         cond_prep(&cond);
1180b2167459SRichard Henderson         tmp = tcg_temp_new();
1181eaa3783bSRichard Henderson         tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1182b2167459SRichard Henderson         gen_helper_tcond(cpu_env, tmp);
1183b2167459SRichard Henderson         tcg_temp_free(tmp);
1184b2167459SRichard Henderson     }
1185b2167459SRichard Henderson 
1186b2167459SRichard Henderson     /* Write back the result.  */
1187b2167459SRichard Henderson     save_or_nullify(ctx, cpu_psw_cb, cb);
1188b2167459SRichard Henderson     save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1189b2167459SRichard Henderson     save_gpr(ctx, rt, dest);
1190b2167459SRichard Henderson     tcg_temp_free(dest);
1191b2167459SRichard Henderson 
1192b2167459SRichard Henderson     /* Install the new nullification.  */
1193b2167459SRichard Henderson     cond_free(&ctx->null_cond);
1194b2167459SRichard Henderson     ctx->null_cond = cond;
1195869051eaSRichard Henderson     return DISAS_NEXT;
1196b2167459SRichard Henderson }
1197b2167459SRichard Henderson 
1198eaa3783bSRichard Henderson static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1199eaa3783bSRichard Henderson                                TCGv_reg in2, unsigned cf)
1200b2167459SRichard Henderson {
1201eaa3783bSRichard Henderson     TCGv_reg dest, sv;
1202b2167459SRichard Henderson     DisasCond cond;
1203b2167459SRichard Henderson 
1204b2167459SRichard Henderson     dest = tcg_temp_new();
1205eaa3783bSRichard Henderson     tcg_gen_sub_reg(dest, in1, in2);
1206b2167459SRichard Henderson 
1207b2167459SRichard Henderson     /* Compute signed overflow if required.  */
1208f764718dSRichard Henderson     sv = NULL;
1209b2167459SRichard Henderson     if ((cf >> 1) == 6) {
1210b2167459SRichard Henderson         sv = do_sub_sv(ctx, dest, in1, in2);
1211b2167459SRichard Henderson     }
1212b2167459SRichard Henderson 
1213b2167459SRichard Henderson     /* Form the condition for the compare.  */
1214b2167459SRichard Henderson     cond = do_sub_cond(cf, dest, in1, in2, sv);
1215b2167459SRichard Henderson 
1216b2167459SRichard Henderson     /* Clear.  */
1217eaa3783bSRichard Henderson     tcg_gen_movi_reg(dest, 0);
1218b2167459SRichard Henderson     save_gpr(ctx, rt, dest);
1219b2167459SRichard Henderson     tcg_temp_free(dest);
1220b2167459SRichard Henderson 
1221b2167459SRichard Henderson     /* Install the new nullification.  */
1222b2167459SRichard Henderson     cond_free(&ctx->null_cond);
1223b2167459SRichard Henderson     ctx->null_cond = cond;
1224869051eaSRichard Henderson     return DISAS_NEXT;
1225b2167459SRichard Henderson }
1226b2167459SRichard Henderson 
1227eaa3783bSRichard Henderson static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1228eaa3783bSRichard Henderson                             TCGv_reg in2, unsigned cf,
1229eaa3783bSRichard Henderson                             void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1230b2167459SRichard Henderson {
1231eaa3783bSRichard Henderson     TCGv_reg dest = dest_gpr(ctx, rt);
1232b2167459SRichard Henderson 
1233b2167459SRichard Henderson     /* Perform the operation, and writeback.  */
1234b2167459SRichard Henderson     fn(dest, in1, in2);
1235b2167459SRichard Henderson     save_gpr(ctx, rt, dest);
1236b2167459SRichard Henderson 
1237b2167459SRichard Henderson     /* Install the new nullification.  */
1238b2167459SRichard Henderson     cond_free(&ctx->null_cond);
1239b2167459SRichard Henderson     if (cf) {
1240b2167459SRichard Henderson         ctx->null_cond = do_log_cond(cf, dest);
1241b2167459SRichard Henderson     }
1242869051eaSRichard Henderson     return DISAS_NEXT;
1243b2167459SRichard Henderson }
1244b2167459SRichard Henderson 
1245eaa3783bSRichard Henderson static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1246eaa3783bSRichard Henderson                              TCGv_reg in2, unsigned cf, bool is_tc,
1247eaa3783bSRichard Henderson                              void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1248b2167459SRichard Henderson {
1249eaa3783bSRichard Henderson     TCGv_reg dest;
1250b2167459SRichard Henderson     DisasCond cond;
1251b2167459SRichard Henderson 
1252b2167459SRichard Henderson     if (cf == 0) {
1253b2167459SRichard Henderson         dest = dest_gpr(ctx, rt);
1254b2167459SRichard Henderson         fn(dest, in1, in2);
1255b2167459SRichard Henderson         save_gpr(ctx, rt, dest);
1256b2167459SRichard Henderson         cond_free(&ctx->null_cond);
1257b2167459SRichard Henderson     } else {
1258b2167459SRichard Henderson         dest = tcg_temp_new();
1259b2167459SRichard Henderson         fn(dest, in1, in2);
1260b2167459SRichard Henderson 
1261b2167459SRichard Henderson         cond = do_unit_cond(cf, dest, in1, in2);
1262b2167459SRichard Henderson 
1263b2167459SRichard Henderson         if (is_tc) {
1264eaa3783bSRichard Henderson             TCGv_reg tmp = tcg_temp_new();
1265b2167459SRichard Henderson             cond_prep(&cond);
1266eaa3783bSRichard Henderson             tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1267b2167459SRichard Henderson             gen_helper_tcond(cpu_env, tmp);
1268b2167459SRichard Henderson             tcg_temp_free(tmp);
1269b2167459SRichard Henderson         }
1270b2167459SRichard Henderson         save_gpr(ctx, rt, dest);
1271b2167459SRichard Henderson 
1272b2167459SRichard Henderson         cond_free(&ctx->null_cond);
1273b2167459SRichard Henderson         ctx->null_cond = cond;
1274b2167459SRichard Henderson     }
1275869051eaSRichard Henderson     return DISAS_NEXT;
1276b2167459SRichard Henderson }
1277b2167459SRichard Henderson 
127896d6407fSRichard Henderson /* Emit a memory load.  The modify parameter should be
127996d6407fSRichard Henderson  * < 0 for pre-modify,
128096d6407fSRichard Henderson  * > 0 for post-modify,
128196d6407fSRichard Henderson  * = 0 for no base register update.
128296d6407fSRichard Henderson  */
128396d6407fSRichard Henderson static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1284eaa3783bSRichard Henderson                        unsigned rx, int scale, target_sreg disp,
128596d6407fSRichard Henderson                        int modify, TCGMemOp mop)
128696d6407fSRichard Henderson {
1287eaa3783bSRichard Henderson     TCGv_reg addr, base;
128896d6407fSRichard Henderson 
128996d6407fSRichard Henderson     /* Caller uses nullify_over/nullify_end.  */
129096d6407fSRichard Henderson     assert(ctx->null_cond.c == TCG_COND_NEVER);
129196d6407fSRichard Henderson 
129296d6407fSRichard Henderson     addr = tcg_temp_new();
129396d6407fSRichard Henderson     base = load_gpr(ctx, rb);
129496d6407fSRichard Henderson 
129596d6407fSRichard Henderson     /* Note that RX is mutually exclusive with DISP.  */
129696d6407fSRichard Henderson     if (rx) {
1297eaa3783bSRichard Henderson         tcg_gen_shli_reg(addr, cpu_gr[rx], scale);
1298eaa3783bSRichard Henderson         tcg_gen_add_reg(addr, addr, base);
129996d6407fSRichard Henderson     } else {
1300eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, base, disp);
130196d6407fSRichard Henderson     }
130296d6407fSRichard Henderson 
130396d6407fSRichard Henderson     if (modify == 0) {
1304*3d68ee7bSRichard Henderson         tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop);
130596d6407fSRichard Henderson     } else {
130696d6407fSRichard Henderson         tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base),
1307*3d68ee7bSRichard Henderson                             ctx->mmu_idx, mop);
130896d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
130996d6407fSRichard Henderson     }
131096d6407fSRichard Henderson     tcg_temp_free(addr);
131196d6407fSRichard Henderson }
131296d6407fSRichard Henderson 
131396d6407fSRichard Henderson static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1314eaa3783bSRichard Henderson                        unsigned rx, int scale, target_sreg disp,
131596d6407fSRichard Henderson                        int modify, TCGMemOp mop)
131696d6407fSRichard Henderson {
1317eaa3783bSRichard Henderson     TCGv_reg addr, base;
131896d6407fSRichard Henderson 
131996d6407fSRichard Henderson     /* Caller uses nullify_over/nullify_end.  */
132096d6407fSRichard Henderson     assert(ctx->null_cond.c == TCG_COND_NEVER);
132196d6407fSRichard Henderson 
132296d6407fSRichard Henderson     addr = tcg_temp_new();
132396d6407fSRichard Henderson     base = load_gpr(ctx, rb);
132496d6407fSRichard Henderson 
132596d6407fSRichard Henderson     /* Note that RX is mutually exclusive with DISP.  */
132696d6407fSRichard Henderson     if (rx) {
1327eaa3783bSRichard Henderson         tcg_gen_shli_reg(addr, cpu_gr[rx], scale);
1328eaa3783bSRichard Henderson         tcg_gen_add_reg(addr, addr, base);
132996d6407fSRichard Henderson     } else {
1330eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, base, disp);
133196d6407fSRichard Henderson     }
133296d6407fSRichard Henderson 
133396d6407fSRichard Henderson     if (modify == 0) {
1334*3d68ee7bSRichard Henderson         tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
133596d6407fSRichard Henderson     } else {
133696d6407fSRichard Henderson         tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base),
1337*3d68ee7bSRichard Henderson                             ctx->mmu_idx, mop);
133896d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
133996d6407fSRichard Henderson     }
134096d6407fSRichard Henderson     tcg_temp_free(addr);
134196d6407fSRichard Henderson }
134296d6407fSRichard Henderson 
134396d6407fSRichard Henderson static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1344eaa3783bSRichard Henderson                         unsigned rx, int scale, target_sreg disp,
134596d6407fSRichard Henderson                         int modify, TCGMemOp mop)
134696d6407fSRichard Henderson {
1347eaa3783bSRichard Henderson     TCGv_reg addr, base;
134896d6407fSRichard Henderson 
134996d6407fSRichard Henderson     /* Caller uses nullify_over/nullify_end.  */
135096d6407fSRichard Henderson     assert(ctx->null_cond.c == TCG_COND_NEVER);
135196d6407fSRichard Henderson 
135296d6407fSRichard Henderson     addr = tcg_temp_new();
135396d6407fSRichard Henderson     base = load_gpr(ctx, rb);
135496d6407fSRichard Henderson 
135596d6407fSRichard Henderson     /* Note that RX is mutually exclusive with DISP.  */
135696d6407fSRichard Henderson     if (rx) {
1357eaa3783bSRichard Henderson         tcg_gen_shli_reg(addr, cpu_gr[rx], scale);
1358eaa3783bSRichard Henderson         tcg_gen_add_reg(addr, addr, base);
135996d6407fSRichard Henderson     } else {
1360eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, base, disp);
136196d6407fSRichard Henderson     }
136296d6407fSRichard Henderson 
1363*3d68ee7bSRichard Henderson     tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop);
136496d6407fSRichard Henderson 
136596d6407fSRichard Henderson     if (modify != 0) {
136696d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
136796d6407fSRichard Henderson     }
136896d6407fSRichard Henderson     tcg_temp_free(addr);
136996d6407fSRichard Henderson }
137096d6407fSRichard Henderson 
137196d6407fSRichard Henderson static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1372eaa3783bSRichard Henderson                         unsigned rx, int scale, target_sreg disp,
137396d6407fSRichard Henderson                         int modify, TCGMemOp mop)
137496d6407fSRichard Henderson {
1375eaa3783bSRichard Henderson     TCGv_reg addr, base;
137696d6407fSRichard Henderson 
137796d6407fSRichard Henderson     /* Caller uses nullify_over/nullify_end.  */
137896d6407fSRichard Henderson     assert(ctx->null_cond.c == TCG_COND_NEVER);
137996d6407fSRichard Henderson 
138096d6407fSRichard Henderson     addr = tcg_temp_new();
138196d6407fSRichard Henderson     base = load_gpr(ctx, rb);
138296d6407fSRichard Henderson 
138396d6407fSRichard Henderson     /* Note that RX is mutually exclusive with DISP.  */
138496d6407fSRichard Henderson     if (rx) {
1385eaa3783bSRichard Henderson         tcg_gen_shli_reg(addr, cpu_gr[rx], scale);
1386eaa3783bSRichard Henderson         tcg_gen_add_reg(addr, addr, base);
138796d6407fSRichard Henderson     } else {
1388eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, base, disp);
138996d6407fSRichard Henderson     }
139096d6407fSRichard Henderson 
1391*3d68ee7bSRichard Henderson     tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop);
139296d6407fSRichard Henderson 
139396d6407fSRichard Henderson     if (modify != 0) {
139496d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
139596d6407fSRichard Henderson     }
139696d6407fSRichard Henderson     tcg_temp_free(addr);
139796d6407fSRichard Henderson }
139896d6407fSRichard Henderson 
1399eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64
1400eaa3783bSRichard Henderson #define do_load_reg   do_load_64
1401eaa3783bSRichard Henderson #define do_store_reg  do_store_64
140296d6407fSRichard Henderson #else
1403eaa3783bSRichard Henderson #define do_load_reg   do_load_32
1404eaa3783bSRichard Henderson #define do_store_reg  do_store_32
140596d6407fSRichard Henderson #endif
140696d6407fSRichard Henderson 
1407869051eaSRichard Henderson static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1408eaa3783bSRichard Henderson                              unsigned rx, int scale, target_sreg disp,
140996d6407fSRichard Henderson                              int modify, TCGMemOp mop)
141096d6407fSRichard Henderson {
1411eaa3783bSRichard Henderson     TCGv_reg dest;
141296d6407fSRichard Henderson 
141396d6407fSRichard Henderson     nullify_over(ctx);
141496d6407fSRichard Henderson 
141596d6407fSRichard Henderson     if (modify == 0) {
141696d6407fSRichard Henderson         /* No base register update.  */
141796d6407fSRichard Henderson         dest = dest_gpr(ctx, rt);
141896d6407fSRichard Henderson     } else {
141996d6407fSRichard Henderson         /* Make sure if RT == RB, we see the result of the load.  */
142096d6407fSRichard Henderson         dest = get_temp(ctx);
142196d6407fSRichard Henderson     }
1422eaa3783bSRichard Henderson     do_load_reg(ctx, dest, rb, rx, scale, disp, modify, mop);
142396d6407fSRichard Henderson     save_gpr(ctx, rt, dest);
142496d6407fSRichard Henderson 
1425869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
142696d6407fSRichard Henderson }
142796d6407fSRichard Henderson 
1428869051eaSRichard Henderson static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1429eaa3783bSRichard Henderson                                unsigned rx, int scale, target_sreg disp,
143096d6407fSRichard Henderson                                int modify)
143196d6407fSRichard Henderson {
143296d6407fSRichard Henderson     TCGv_i32 tmp;
143396d6407fSRichard Henderson 
143496d6407fSRichard Henderson     nullify_over(ctx);
143596d6407fSRichard Henderson 
143696d6407fSRichard Henderson     tmp = tcg_temp_new_i32();
143796d6407fSRichard Henderson     do_load_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL);
143896d6407fSRichard Henderson     save_frw_i32(rt, tmp);
143996d6407fSRichard Henderson     tcg_temp_free_i32(tmp);
144096d6407fSRichard Henderson 
144196d6407fSRichard Henderson     if (rt == 0) {
144296d6407fSRichard Henderson         gen_helper_loaded_fr0(cpu_env);
144396d6407fSRichard Henderson     }
144496d6407fSRichard Henderson 
1445869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
144696d6407fSRichard Henderson }
144796d6407fSRichard Henderson 
1448869051eaSRichard Henderson static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1449eaa3783bSRichard Henderson                                unsigned rx, int scale, target_sreg disp,
145096d6407fSRichard Henderson                                int modify)
145196d6407fSRichard Henderson {
145296d6407fSRichard Henderson     TCGv_i64 tmp;
145396d6407fSRichard Henderson 
145496d6407fSRichard Henderson     nullify_over(ctx);
145596d6407fSRichard Henderson 
145696d6407fSRichard Henderson     tmp = tcg_temp_new_i64();
145796d6407fSRichard Henderson     do_load_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ);
145896d6407fSRichard Henderson     save_frd(rt, tmp);
145996d6407fSRichard Henderson     tcg_temp_free_i64(tmp);
146096d6407fSRichard Henderson 
146196d6407fSRichard Henderson     if (rt == 0) {
146296d6407fSRichard Henderson         gen_helper_loaded_fr0(cpu_env);
146396d6407fSRichard Henderson     }
146496d6407fSRichard Henderson 
1465869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
146696d6407fSRichard Henderson }
146796d6407fSRichard Henderson 
1468869051eaSRichard Henderson static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1469eaa3783bSRichard Henderson                               target_sreg disp, int modify, TCGMemOp mop)
147096d6407fSRichard Henderson {
147196d6407fSRichard Henderson     nullify_over(ctx);
1472eaa3783bSRichard Henderson     do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop);
1473869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
147496d6407fSRichard Henderson }
147596d6407fSRichard Henderson 
1476869051eaSRichard Henderson static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1477eaa3783bSRichard Henderson                                 unsigned rx, int scale, target_sreg disp,
147896d6407fSRichard Henderson                                 int modify)
147996d6407fSRichard Henderson {
148096d6407fSRichard Henderson     TCGv_i32 tmp;
148196d6407fSRichard Henderson 
148296d6407fSRichard Henderson     nullify_over(ctx);
148396d6407fSRichard Henderson 
148496d6407fSRichard Henderson     tmp = load_frw_i32(rt);
148596d6407fSRichard Henderson     do_store_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL);
148696d6407fSRichard Henderson     tcg_temp_free_i32(tmp);
148796d6407fSRichard Henderson 
1488869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
148996d6407fSRichard Henderson }
149096d6407fSRichard Henderson 
1491869051eaSRichard Henderson static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1492eaa3783bSRichard Henderson                                 unsigned rx, int scale, target_sreg disp,
149396d6407fSRichard Henderson                                 int modify)
149496d6407fSRichard Henderson {
149596d6407fSRichard Henderson     TCGv_i64 tmp;
149696d6407fSRichard Henderson 
149796d6407fSRichard Henderson     nullify_over(ctx);
149896d6407fSRichard Henderson 
149996d6407fSRichard Henderson     tmp = load_frd(rt);
150096d6407fSRichard Henderson     do_store_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ);
150196d6407fSRichard Henderson     tcg_temp_free_i64(tmp);
150296d6407fSRichard Henderson 
1503869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
150496d6407fSRichard Henderson }
150596d6407fSRichard Henderson 
1506869051eaSRichard Henderson static DisasJumpType do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1507ebe9383cSRichard Henderson                                 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1508ebe9383cSRichard Henderson {
1509ebe9383cSRichard Henderson     TCGv_i32 tmp;
1510ebe9383cSRichard Henderson 
1511ebe9383cSRichard Henderson     nullify_over(ctx);
1512ebe9383cSRichard Henderson     tmp = load_frw0_i32(ra);
1513ebe9383cSRichard Henderson 
1514ebe9383cSRichard Henderson     func(tmp, cpu_env, tmp);
1515ebe9383cSRichard Henderson 
1516ebe9383cSRichard Henderson     save_frw_i32(rt, tmp);
1517ebe9383cSRichard Henderson     tcg_temp_free_i32(tmp);
1518869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1519ebe9383cSRichard Henderson }
1520ebe9383cSRichard Henderson 
1521869051eaSRichard Henderson static DisasJumpType do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1522ebe9383cSRichard Henderson                                 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1523ebe9383cSRichard Henderson {
1524ebe9383cSRichard Henderson     TCGv_i32 dst;
1525ebe9383cSRichard Henderson     TCGv_i64 src;
1526ebe9383cSRichard Henderson 
1527ebe9383cSRichard Henderson     nullify_over(ctx);
1528ebe9383cSRichard Henderson     src = load_frd(ra);
1529ebe9383cSRichard Henderson     dst = tcg_temp_new_i32();
1530ebe9383cSRichard Henderson 
1531ebe9383cSRichard Henderson     func(dst, cpu_env, src);
1532ebe9383cSRichard Henderson 
1533ebe9383cSRichard Henderson     tcg_temp_free_i64(src);
1534ebe9383cSRichard Henderson     save_frw_i32(rt, dst);
1535ebe9383cSRichard Henderson     tcg_temp_free_i32(dst);
1536869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1537ebe9383cSRichard Henderson }
1538ebe9383cSRichard Henderson 
1539869051eaSRichard Henderson static DisasJumpType do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1540ebe9383cSRichard Henderson                                 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1541ebe9383cSRichard Henderson {
1542ebe9383cSRichard Henderson     TCGv_i64 tmp;
1543ebe9383cSRichard Henderson 
1544ebe9383cSRichard Henderson     nullify_over(ctx);
1545ebe9383cSRichard Henderson     tmp = load_frd0(ra);
1546ebe9383cSRichard Henderson 
1547ebe9383cSRichard Henderson     func(tmp, cpu_env, tmp);
1548ebe9383cSRichard Henderson 
1549ebe9383cSRichard Henderson     save_frd(rt, tmp);
1550ebe9383cSRichard Henderson     tcg_temp_free_i64(tmp);
1551869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1552ebe9383cSRichard Henderson }
1553ebe9383cSRichard Henderson 
1554869051eaSRichard Henderson static DisasJumpType do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1555ebe9383cSRichard Henderson                                 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1556ebe9383cSRichard Henderson {
1557ebe9383cSRichard Henderson     TCGv_i32 src;
1558ebe9383cSRichard Henderson     TCGv_i64 dst;
1559ebe9383cSRichard Henderson 
1560ebe9383cSRichard Henderson     nullify_over(ctx);
1561ebe9383cSRichard Henderson     src = load_frw0_i32(ra);
1562ebe9383cSRichard Henderson     dst = tcg_temp_new_i64();
1563ebe9383cSRichard Henderson 
1564ebe9383cSRichard Henderson     func(dst, cpu_env, src);
1565ebe9383cSRichard Henderson 
1566ebe9383cSRichard Henderson     tcg_temp_free_i32(src);
1567ebe9383cSRichard Henderson     save_frd(rt, dst);
1568ebe9383cSRichard Henderson     tcg_temp_free_i64(dst);
1569869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1570ebe9383cSRichard Henderson }
1571ebe9383cSRichard Henderson 
1572869051eaSRichard Henderson static DisasJumpType do_fop_weww(DisasContext *ctx, unsigned rt,
1573ebe9383cSRichard Henderson                                  unsigned ra, unsigned rb,
1574ebe9383cSRichard Henderson                                  void (*func)(TCGv_i32, TCGv_env,
1575ebe9383cSRichard Henderson                                               TCGv_i32, TCGv_i32))
1576ebe9383cSRichard Henderson {
1577ebe9383cSRichard Henderson     TCGv_i32 a, b;
1578ebe9383cSRichard Henderson 
1579ebe9383cSRichard Henderson     nullify_over(ctx);
1580ebe9383cSRichard Henderson     a = load_frw0_i32(ra);
1581ebe9383cSRichard Henderson     b = load_frw0_i32(rb);
1582ebe9383cSRichard Henderson 
1583ebe9383cSRichard Henderson     func(a, cpu_env, a, b);
1584ebe9383cSRichard Henderson 
1585ebe9383cSRichard Henderson     tcg_temp_free_i32(b);
1586ebe9383cSRichard Henderson     save_frw_i32(rt, a);
1587ebe9383cSRichard Henderson     tcg_temp_free_i32(a);
1588869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1589ebe9383cSRichard Henderson }
1590ebe9383cSRichard Henderson 
1591869051eaSRichard Henderson static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt,
1592ebe9383cSRichard Henderson                                  unsigned ra, unsigned rb,
1593ebe9383cSRichard Henderson                                  void (*func)(TCGv_i64, TCGv_env,
1594ebe9383cSRichard Henderson                                               TCGv_i64, TCGv_i64))
1595ebe9383cSRichard Henderson {
1596ebe9383cSRichard Henderson     TCGv_i64 a, b;
1597ebe9383cSRichard Henderson 
1598ebe9383cSRichard Henderson     nullify_over(ctx);
1599ebe9383cSRichard Henderson     a = load_frd0(ra);
1600ebe9383cSRichard Henderson     b = load_frd0(rb);
1601ebe9383cSRichard Henderson 
1602ebe9383cSRichard Henderson     func(a, cpu_env, a, b);
1603ebe9383cSRichard Henderson 
1604ebe9383cSRichard Henderson     tcg_temp_free_i64(b);
1605ebe9383cSRichard Henderson     save_frd(rt, a);
1606ebe9383cSRichard Henderson     tcg_temp_free_i64(a);
1607869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
1608ebe9383cSRichard Henderson }
1609ebe9383cSRichard Henderson 
161098cd9ca7SRichard Henderson /* Emit an unconditional branch to a direct target, which may or may not
161198cd9ca7SRichard Henderson    have already had nullification handled.  */
1612eaa3783bSRichard Henderson static DisasJumpType do_dbranch(DisasContext *ctx, target_ureg dest,
161398cd9ca7SRichard Henderson                                 unsigned link, bool is_n)
161498cd9ca7SRichard Henderson {
161598cd9ca7SRichard Henderson     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
161698cd9ca7SRichard Henderson         if (link != 0) {
161798cd9ca7SRichard Henderson             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
161898cd9ca7SRichard Henderson         }
161998cd9ca7SRichard Henderson         ctx->iaoq_n = dest;
162098cd9ca7SRichard Henderson         if (is_n) {
162198cd9ca7SRichard Henderson             ctx->null_cond.c = TCG_COND_ALWAYS;
162298cd9ca7SRichard Henderson         }
1623869051eaSRichard Henderson         return DISAS_NEXT;
162498cd9ca7SRichard Henderson     } else {
162598cd9ca7SRichard Henderson         nullify_over(ctx);
162698cd9ca7SRichard Henderson 
162798cd9ca7SRichard Henderson         if (link != 0) {
162898cd9ca7SRichard Henderson             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
162998cd9ca7SRichard Henderson         }
163098cd9ca7SRichard Henderson 
163198cd9ca7SRichard Henderson         if (is_n && use_nullify_skip(ctx)) {
163298cd9ca7SRichard Henderson             nullify_set(ctx, 0);
163398cd9ca7SRichard Henderson             gen_goto_tb(ctx, 0, dest, dest + 4);
163498cd9ca7SRichard Henderson         } else {
163598cd9ca7SRichard Henderson             nullify_set(ctx, is_n);
163698cd9ca7SRichard Henderson             gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
163798cd9ca7SRichard Henderson         }
163898cd9ca7SRichard Henderson 
1639869051eaSRichard Henderson         nullify_end(ctx, DISAS_NEXT);
164098cd9ca7SRichard Henderson 
164198cd9ca7SRichard Henderson         nullify_set(ctx, 0);
164298cd9ca7SRichard Henderson         gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1643869051eaSRichard Henderson         return DISAS_NORETURN;
164498cd9ca7SRichard Henderson     }
164598cd9ca7SRichard Henderson }
164698cd9ca7SRichard Henderson 
164798cd9ca7SRichard Henderson /* Emit a conditional branch to a direct target.  If the branch itself
164898cd9ca7SRichard Henderson    is nullified, we should have already used nullify_over.  */
1649eaa3783bSRichard Henderson static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
165098cd9ca7SRichard Henderson                                 DisasCond *cond)
165198cd9ca7SRichard Henderson {
1652eaa3783bSRichard Henderson     target_ureg dest = iaoq_dest(ctx, disp);
165398cd9ca7SRichard Henderson     TCGLabel *taken = NULL;
165498cd9ca7SRichard Henderson     TCGCond c = cond->c;
165598cd9ca7SRichard Henderson     bool n;
165698cd9ca7SRichard Henderson 
165798cd9ca7SRichard Henderson     assert(ctx->null_cond.c == TCG_COND_NEVER);
165898cd9ca7SRichard Henderson 
165998cd9ca7SRichard Henderson     /* Handle TRUE and NEVER as direct branches.  */
166098cd9ca7SRichard Henderson     if (c == TCG_COND_ALWAYS) {
166198cd9ca7SRichard Henderson         return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
166298cd9ca7SRichard Henderson     }
166398cd9ca7SRichard Henderson     if (c == TCG_COND_NEVER) {
166498cd9ca7SRichard Henderson         return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
166598cd9ca7SRichard Henderson     }
166698cd9ca7SRichard Henderson 
166798cd9ca7SRichard Henderson     taken = gen_new_label();
166898cd9ca7SRichard Henderson     cond_prep(cond);
1669eaa3783bSRichard Henderson     tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
167098cd9ca7SRichard Henderson     cond_free(cond);
167198cd9ca7SRichard Henderson 
167298cd9ca7SRichard Henderson     /* Not taken: Condition not satisfied; nullify on backward branches. */
167398cd9ca7SRichard Henderson     n = is_n && disp < 0;
167498cd9ca7SRichard Henderson     if (n && use_nullify_skip(ctx)) {
167598cd9ca7SRichard Henderson         nullify_set(ctx, 0);
1676a881c8e7SRichard Henderson         gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
167798cd9ca7SRichard Henderson     } else {
167898cd9ca7SRichard Henderson         if (!n && ctx->null_lab) {
167998cd9ca7SRichard Henderson             gen_set_label(ctx->null_lab);
168098cd9ca7SRichard Henderson             ctx->null_lab = NULL;
168198cd9ca7SRichard Henderson         }
168298cd9ca7SRichard Henderson         nullify_set(ctx, n);
1683a881c8e7SRichard Henderson         gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
168498cd9ca7SRichard Henderson     }
168598cd9ca7SRichard Henderson 
168698cd9ca7SRichard Henderson     gen_set_label(taken);
168798cd9ca7SRichard Henderson 
168898cd9ca7SRichard Henderson     /* Taken: Condition satisfied; nullify on forward branches.  */
168998cd9ca7SRichard Henderson     n = is_n && disp >= 0;
169098cd9ca7SRichard Henderson     if (n && use_nullify_skip(ctx)) {
169198cd9ca7SRichard Henderson         nullify_set(ctx, 0);
1692a881c8e7SRichard Henderson         gen_goto_tb(ctx, 1, dest, dest + 4);
169398cd9ca7SRichard Henderson     } else {
169498cd9ca7SRichard Henderson         nullify_set(ctx, n);
1695a881c8e7SRichard Henderson         gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
169698cd9ca7SRichard Henderson     }
169798cd9ca7SRichard Henderson 
169898cd9ca7SRichard Henderson     /* Not taken: the branch itself was nullified.  */
169998cd9ca7SRichard Henderson     if (ctx->null_lab) {
170098cd9ca7SRichard Henderson         gen_set_label(ctx->null_lab);
170198cd9ca7SRichard Henderson         ctx->null_lab = NULL;
1702869051eaSRichard Henderson         return DISAS_IAQ_N_STALE;
170398cd9ca7SRichard Henderson     } else {
1704869051eaSRichard Henderson         return DISAS_NORETURN;
170598cd9ca7SRichard Henderson     }
170698cd9ca7SRichard Henderson }
170798cd9ca7SRichard Henderson 
170898cd9ca7SRichard Henderson /* Emit an unconditional branch to an indirect target.  This handles
170998cd9ca7SRichard Henderson    nullification of the branch itself.  */
1710eaa3783bSRichard Henderson static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest,
171198cd9ca7SRichard Henderson                                 unsigned link, bool is_n)
171298cd9ca7SRichard Henderson {
1713eaa3783bSRichard Henderson     TCGv_reg a0, a1, next, tmp;
171498cd9ca7SRichard Henderson     TCGCond c;
171598cd9ca7SRichard Henderson 
171698cd9ca7SRichard Henderson     assert(ctx->null_lab == NULL);
171798cd9ca7SRichard Henderson 
171898cd9ca7SRichard Henderson     if (ctx->null_cond.c == TCG_COND_NEVER) {
171998cd9ca7SRichard Henderson         if (link != 0) {
172098cd9ca7SRichard Henderson             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
172198cd9ca7SRichard Henderson         }
172298cd9ca7SRichard Henderson         next = get_temp(ctx);
1723eaa3783bSRichard Henderson         tcg_gen_mov_reg(next, dest);
172498cd9ca7SRichard Henderson         ctx->iaoq_n = -1;
172598cd9ca7SRichard Henderson         ctx->iaoq_n_var = next;
172698cd9ca7SRichard Henderson         if (is_n) {
172798cd9ca7SRichard Henderson             ctx->null_cond.c = TCG_COND_ALWAYS;
172898cd9ca7SRichard Henderson         }
172998cd9ca7SRichard Henderson     } else if (is_n && use_nullify_skip(ctx)) {
173098cd9ca7SRichard Henderson         /* The (conditional) branch, B, nullifies the next insn, N,
173198cd9ca7SRichard Henderson            and we're allowed to skip execution N (no single-step or
17324137cb83SRichard Henderson            tracepoint in effect).  Since the goto_ptr that we must use
173398cd9ca7SRichard Henderson            for the indirect branch consumes no special resources, we
173498cd9ca7SRichard Henderson            can (conditionally) skip B and continue execution.  */
173598cd9ca7SRichard Henderson         /* The use_nullify_skip test implies we have a known control path.  */
173698cd9ca7SRichard Henderson         tcg_debug_assert(ctx->iaoq_b != -1);
173798cd9ca7SRichard Henderson         tcg_debug_assert(ctx->iaoq_n != -1);
173898cd9ca7SRichard Henderson 
173998cd9ca7SRichard Henderson         /* We do have to handle the non-local temporary, DEST, before
174098cd9ca7SRichard Henderson            branching.  Since IOAQ_F is not really live at this point, we
174198cd9ca7SRichard Henderson            can simply store DEST optimistically.  Similarly with IAOQ_B.  */
1742eaa3783bSRichard Henderson         tcg_gen_mov_reg(cpu_iaoq_f, dest);
1743eaa3783bSRichard Henderson         tcg_gen_addi_reg(cpu_iaoq_b, dest, 4);
174498cd9ca7SRichard Henderson 
174598cd9ca7SRichard Henderson         nullify_over(ctx);
174698cd9ca7SRichard Henderson         if (link != 0) {
1747eaa3783bSRichard Henderson             tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n);
174898cd9ca7SRichard Henderson         }
17497f11636dSEmilio G. Cota         tcg_gen_lookup_and_goto_ptr();
1750869051eaSRichard Henderson         return nullify_end(ctx, DISAS_NEXT);
175198cd9ca7SRichard Henderson     } else {
175298cd9ca7SRichard Henderson         cond_prep(&ctx->null_cond);
175398cd9ca7SRichard Henderson         c = ctx->null_cond.c;
175498cd9ca7SRichard Henderson         a0 = ctx->null_cond.a0;
175598cd9ca7SRichard Henderson         a1 = ctx->null_cond.a1;
175698cd9ca7SRichard Henderson 
175798cd9ca7SRichard Henderson         tmp = tcg_temp_new();
175898cd9ca7SRichard Henderson         next = get_temp(ctx);
175998cd9ca7SRichard Henderson 
176098cd9ca7SRichard Henderson         copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1761eaa3783bSRichard Henderson         tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
176298cd9ca7SRichard Henderson         ctx->iaoq_n = -1;
176398cd9ca7SRichard Henderson         ctx->iaoq_n_var = next;
176498cd9ca7SRichard Henderson 
176598cd9ca7SRichard Henderson         if (link != 0) {
1766eaa3783bSRichard Henderson             tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
176798cd9ca7SRichard Henderson         }
176898cd9ca7SRichard Henderson 
176998cd9ca7SRichard Henderson         if (is_n) {
177098cd9ca7SRichard Henderson             /* The branch nullifies the next insn, which means the state of N
177198cd9ca7SRichard Henderson                after the branch is the inverse of the state of N that applied
177298cd9ca7SRichard Henderson                to the branch.  */
1773eaa3783bSRichard Henderson             tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1);
177498cd9ca7SRichard Henderson             cond_free(&ctx->null_cond);
177598cd9ca7SRichard Henderson             ctx->null_cond = cond_make_n();
177698cd9ca7SRichard Henderson             ctx->psw_n_nonzero = true;
177798cd9ca7SRichard Henderson         } else {
177898cd9ca7SRichard Henderson             cond_free(&ctx->null_cond);
177998cd9ca7SRichard Henderson         }
178098cd9ca7SRichard Henderson     }
178198cd9ca7SRichard Henderson 
1782869051eaSRichard Henderson     return DISAS_NEXT;
178398cd9ca7SRichard Henderson }
178498cd9ca7SRichard Henderson 
1785ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY
17867ad439dfSRichard Henderson /* On Linux, page zero is normally marked execute only + gateway.
17877ad439dfSRichard Henderson    Therefore normal read or write is supposed to fail, but specific
17887ad439dfSRichard Henderson    offsets have kernel code mapped to raise permissions to implement
17897ad439dfSRichard Henderson    system calls.  Handling this via an explicit check here, rather
17907ad439dfSRichard Henderson    in than the "be disp(sr2,r0)" instruction that probably sent us
17917ad439dfSRichard Henderson    here, is the easiest way to handle the branch delay slot on the
17927ad439dfSRichard Henderson    aforementioned BE.  */
1793869051eaSRichard Henderson static DisasJumpType do_page_zero(DisasContext *ctx)
17947ad439dfSRichard Henderson {
17957ad439dfSRichard Henderson     /* If by some means we get here with PSW[N]=1, that implies that
17967ad439dfSRichard Henderson        the B,GATE instruction would be skipped, and we'd fault on the
17977ad439dfSRichard Henderson        next insn within the privilaged page.  */
17987ad439dfSRichard Henderson     switch (ctx->null_cond.c) {
17997ad439dfSRichard Henderson     case TCG_COND_NEVER:
18007ad439dfSRichard Henderson         break;
18017ad439dfSRichard Henderson     case TCG_COND_ALWAYS:
1802eaa3783bSRichard Henderson         tcg_gen_movi_reg(cpu_psw_n, 0);
18037ad439dfSRichard Henderson         goto do_sigill;
18047ad439dfSRichard Henderson     default:
18057ad439dfSRichard Henderson         /* Since this is always the first (and only) insn within the
18067ad439dfSRichard Henderson            TB, we should know the state of PSW[N] from TB->FLAGS.  */
18077ad439dfSRichard Henderson         g_assert_not_reached();
18087ad439dfSRichard Henderson     }
18097ad439dfSRichard Henderson 
18107ad439dfSRichard Henderson     /* Check that we didn't arrive here via some means that allowed
18117ad439dfSRichard Henderson        non-sequential instruction execution.  Normally the PSW[B] bit
18127ad439dfSRichard Henderson        detects this by disallowing the B,GATE instruction to execute
18137ad439dfSRichard Henderson        under such conditions.  */
18147ad439dfSRichard Henderson     if (ctx->iaoq_b != ctx->iaoq_f + 4) {
18157ad439dfSRichard Henderson         goto do_sigill;
18167ad439dfSRichard Henderson     }
18177ad439dfSRichard Henderson 
18187ad439dfSRichard Henderson     switch (ctx->iaoq_f) {
18197ad439dfSRichard Henderson     case 0x00: /* Null pointer call */
18202986721dSRichard Henderson         gen_excp_1(EXCP_IMP);
1821869051eaSRichard Henderson         return DISAS_NORETURN;
18227ad439dfSRichard Henderson 
18237ad439dfSRichard Henderson     case 0xb0: /* LWS */
18247ad439dfSRichard Henderson         gen_excp_1(EXCP_SYSCALL_LWS);
1825869051eaSRichard Henderson         return DISAS_NORETURN;
18267ad439dfSRichard Henderson 
18277ad439dfSRichard Henderson     case 0xe0: /* SET_THREAD_POINTER */
1828eaa3783bSRichard Henderson         tcg_gen_mov_reg(cpu_cr27, cpu_gr[26]);
1829eaa3783bSRichard Henderson         tcg_gen_mov_reg(cpu_iaoq_f, cpu_gr[31]);
1830eaa3783bSRichard Henderson         tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
1831869051eaSRichard Henderson         return DISAS_IAQ_N_UPDATED;
18327ad439dfSRichard Henderson 
18337ad439dfSRichard Henderson     case 0x100: /* SYSCALL */
18347ad439dfSRichard Henderson         gen_excp_1(EXCP_SYSCALL);
1835869051eaSRichard Henderson         return DISAS_NORETURN;
18367ad439dfSRichard Henderson 
18377ad439dfSRichard Henderson     default:
18387ad439dfSRichard Henderson     do_sigill:
18392986721dSRichard Henderson         gen_excp_1(EXCP_ILL);
1840869051eaSRichard Henderson         return DISAS_NORETURN;
18417ad439dfSRichard Henderson     }
18427ad439dfSRichard Henderson }
1843ba1d0b44SRichard Henderson #endif
18447ad439dfSRichard Henderson 
1845869051eaSRichard Henderson static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
1846b2167459SRichard Henderson                                const DisasInsn *di)
1847b2167459SRichard Henderson {
1848b2167459SRichard Henderson     cond_free(&ctx->null_cond);
1849869051eaSRichard Henderson     return DISAS_NEXT;
1850b2167459SRichard Henderson }
1851b2167459SRichard Henderson 
1852869051eaSRichard Henderson static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
185398a9cb79SRichard Henderson                                  const DisasInsn *di)
185498a9cb79SRichard Henderson {
185598a9cb79SRichard Henderson     nullify_over(ctx);
18562986721dSRichard Henderson     return nullify_end(ctx, gen_excp(ctx, EXCP_BREAK));
185798a9cb79SRichard Henderson }
185898a9cb79SRichard Henderson 
1859869051eaSRichard Henderson static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn,
186098a9cb79SRichard Henderson                                 const DisasInsn *di)
186198a9cb79SRichard Henderson {
186298a9cb79SRichard Henderson     /* No point in nullifying the memory barrier.  */
186398a9cb79SRichard Henderson     tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
186498a9cb79SRichard Henderson 
186598a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1866869051eaSRichard Henderson     return DISAS_NEXT;
186798a9cb79SRichard Henderson }
186898a9cb79SRichard Henderson 
1869869051eaSRichard Henderson static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn,
187098a9cb79SRichard Henderson                                 const DisasInsn *di)
187198a9cb79SRichard Henderson {
187298a9cb79SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
1873eaa3783bSRichard Henderson     TCGv_reg tmp = dest_gpr(ctx, rt);
1874eaa3783bSRichard Henderson     tcg_gen_movi_reg(tmp, ctx->iaoq_f);
187598a9cb79SRichard Henderson     save_gpr(ctx, rt, tmp);
187698a9cb79SRichard Henderson 
187798a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1878869051eaSRichard Henderson     return DISAS_NEXT;
187998a9cb79SRichard Henderson }
188098a9cb79SRichard Henderson 
1881869051eaSRichard Henderson static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn,
188298a9cb79SRichard Henderson                                 const DisasInsn *di)
188398a9cb79SRichard Henderson {
188498a9cb79SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
1885eaa3783bSRichard Henderson     TCGv_reg tmp = dest_gpr(ctx, rt);
188698a9cb79SRichard Henderson 
188798a9cb79SRichard Henderson     /* ??? We don't implement space registers.  */
1888eaa3783bSRichard Henderson     tcg_gen_movi_reg(tmp, 0);
188998a9cb79SRichard Henderson     save_gpr(ctx, rt, tmp);
189098a9cb79SRichard Henderson 
189198a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1892869051eaSRichard Henderson     return DISAS_NEXT;
189398a9cb79SRichard Henderson }
189498a9cb79SRichard Henderson 
1895869051eaSRichard Henderson static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn,
189698a9cb79SRichard Henderson                                  const DisasInsn *di)
189798a9cb79SRichard Henderson {
189898a9cb79SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
189998a9cb79SRichard Henderson     unsigned ctl = extract32(insn, 21, 5);
1900eaa3783bSRichard Henderson     TCGv_reg tmp;
190198a9cb79SRichard Henderson 
190298a9cb79SRichard Henderson     switch (ctl) {
190398a9cb79SRichard Henderson     case 11: /* SAR */
190498a9cb79SRichard Henderson #ifdef TARGET_HPPA64
190598a9cb79SRichard Henderson         if (extract32(insn, 14, 1) == 0) {
190698a9cb79SRichard Henderson             /* MFSAR without ,W masks low 5 bits.  */
190798a9cb79SRichard Henderson             tmp = dest_gpr(ctx, rt);
1908eaa3783bSRichard Henderson             tcg_gen_andi_reg(tmp, cpu_sar, 31);
190998a9cb79SRichard Henderson             save_gpr(ctx, rt, tmp);
191098a9cb79SRichard Henderson             break;
191198a9cb79SRichard Henderson         }
191298a9cb79SRichard Henderson #endif
191398a9cb79SRichard Henderson         save_gpr(ctx, rt, cpu_sar);
191498a9cb79SRichard Henderson         break;
191598a9cb79SRichard Henderson     case 16: /* Interval Timer */
191698a9cb79SRichard Henderson         tmp = dest_gpr(ctx, rt);
191798a9cb79SRichard Henderson         tcg_gen_movi_tl(tmp, 0); /* FIXME */
191898a9cb79SRichard Henderson         save_gpr(ctx, rt, tmp);
191998a9cb79SRichard Henderson         break;
192098a9cb79SRichard Henderson     case 26:
192198a9cb79SRichard Henderson         save_gpr(ctx, rt, cpu_cr26);
192298a9cb79SRichard Henderson         break;
192398a9cb79SRichard Henderson     case 27:
192498a9cb79SRichard Henderson         save_gpr(ctx, rt, cpu_cr27);
192598a9cb79SRichard Henderson         break;
192698a9cb79SRichard Henderson     default:
192798a9cb79SRichard Henderson         /* All other control registers are privileged.  */
192898a9cb79SRichard Henderson         return gen_illegal(ctx);
192998a9cb79SRichard Henderson     }
193098a9cb79SRichard Henderson 
193198a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1932869051eaSRichard Henderson     return DISAS_NEXT;
193398a9cb79SRichard Henderson }
193498a9cb79SRichard Henderson 
1935869051eaSRichard Henderson static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn,
193698a9cb79SRichard Henderson                                  const DisasInsn *di)
193798a9cb79SRichard Henderson {
193898a9cb79SRichard Henderson     unsigned rin = extract32(insn, 16, 5);
193998a9cb79SRichard Henderson     unsigned ctl = extract32(insn, 21, 5);
1940eaa3783bSRichard Henderson     TCGv_reg tmp;
194198a9cb79SRichard Henderson 
194298a9cb79SRichard Henderson     if (ctl == 11) { /* SAR */
194398a9cb79SRichard Henderson         tmp = tcg_temp_new();
1944eaa3783bSRichard Henderson         tcg_gen_andi_reg(tmp, load_gpr(ctx, rin), TARGET_REGISTER_BITS - 1);
194598a9cb79SRichard Henderson         save_or_nullify(ctx, cpu_sar, tmp);
194698a9cb79SRichard Henderson         tcg_temp_free(tmp);
194798a9cb79SRichard Henderson     } else {
194898a9cb79SRichard Henderson         /* All other control registers are privileged or read-only.  */
194998a9cb79SRichard Henderson         return gen_illegal(ctx);
195098a9cb79SRichard Henderson     }
195198a9cb79SRichard Henderson 
195298a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1953869051eaSRichard Henderson     return DISAS_NEXT;
195498a9cb79SRichard Henderson }
195598a9cb79SRichard Henderson 
1956869051eaSRichard Henderson static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn,
195798a9cb79SRichard Henderson                                    const DisasInsn *di)
195898a9cb79SRichard Henderson {
195998a9cb79SRichard Henderson     unsigned rin = extract32(insn, 16, 5);
1960eaa3783bSRichard Henderson     TCGv_reg tmp = tcg_temp_new();
196198a9cb79SRichard Henderson 
1962eaa3783bSRichard Henderson     tcg_gen_not_reg(tmp, load_gpr(ctx, rin));
1963eaa3783bSRichard Henderson     tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
196498a9cb79SRichard Henderson     save_or_nullify(ctx, cpu_sar, tmp);
196598a9cb79SRichard Henderson     tcg_temp_free(tmp);
196698a9cb79SRichard Henderson 
196798a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1968869051eaSRichard Henderson     return DISAS_NEXT;
196998a9cb79SRichard Henderson }
197098a9cb79SRichard Henderson 
1971869051eaSRichard Henderson static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn,
197298a9cb79SRichard Henderson                                  const DisasInsn *di)
197398a9cb79SRichard Henderson {
197498a9cb79SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
1975eaa3783bSRichard Henderson     TCGv_reg dest = dest_gpr(ctx, rt);
197698a9cb79SRichard Henderson 
197798a9cb79SRichard Henderson     /* Since we don't implement space registers, this returns zero.  */
1978eaa3783bSRichard Henderson     tcg_gen_movi_reg(dest, 0);
197998a9cb79SRichard Henderson     save_gpr(ctx, rt, dest);
198098a9cb79SRichard Henderson 
198198a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
1982869051eaSRichard Henderson     return DISAS_NEXT;
198398a9cb79SRichard Henderson }
198498a9cb79SRichard Henderson 
198598a9cb79SRichard Henderson static const DisasInsn table_system[] = {
198698a9cb79SRichard Henderson     { 0x00000000u, 0xfc001fe0u, trans_break },
198798a9cb79SRichard Henderson     /* We don't implement space register, so MTSP is a nop.  */
198898a9cb79SRichard Henderson     { 0x00001820u, 0xffe01fffu, trans_nop },
198998a9cb79SRichard Henderson     { 0x00001840u, 0xfc00ffffu, trans_mtctl },
199098a9cb79SRichard Henderson     { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm },
199198a9cb79SRichard Henderson     { 0x000014a0u, 0xffffffe0u, trans_mfia },
199298a9cb79SRichard Henderson     { 0x000004a0u, 0xffff1fe0u, trans_mfsp },
199398a9cb79SRichard Henderson     { 0x000008a0u, 0xfc1fffe0u, trans_mfctl },
199498a9cb79SRichard Henderson     { 0x00000400u, 0xffffffffu, trans_sync },
199598a9cb79SRichard Henderson     { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid },
199698a9cb79SRichard Henderson };
199798a9cb79SRichard Henderson 
1998869051eaSRichard Henderson static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn,
199998a9cb79SRichard Henderson                                         const DisasInsn *di)
200098a9cb79SRichard Henderson {
200198a9cb79SRichard Henderson     unsigned rb = extract32(insn, 21, 5);
200298a9cb79SRichard Henderson     unsigned rx = extract32(insn, 16, 5);
2003eaa3783bSRichard Henderson     TCGv_reg dest = dest_gpr(ctx, rb);
2004eaa3783bSRichard Henderson     TCGv_reg src1 = load_gpr(ctx, rb);
2005eaa3783bSRichard Henderson     TCGv_reg src2 = load_gpr(ctx, rx);
200698a9cb79SRichard Henderson 
200798a9cb79SRichard Henderson     /* The only thing we need to do is the base register modification.  */
2008eaa3783bSRichard Henderson     tcg_gen_add_reg(dest, src1, src2);
200998a9cb79SRichard Henderson     save_gpr(ctx, rb, dest);
201098a9cb79SRichard Henderson 
201198a9cb79SRichard Henderson     cond_free(&ctx->null_cond);
2012869051eaSRichard Henderson     return DISAS_NEXT;
201398a9cb79SRichard Henderson }
201498a9cb79SRichard Henderson 
2015869051eaSRichard Henderson static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn,
201698a9cb79SRichard Henderson                                  const DisasInsn *di)
201798a9cb79SRichard Henderson {
201898a9cb79SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
201998a9cb79SRichard Henderson     unsigned rb = extract32(insn, 21, 5);
202098a9cb79SRichard Henderson     unsigned is_write = extract32(insn, 6, 1);
2021eaa3783bSRichard Henderson     TCGv_reg dest;
202298a9cb79SRichard Henderson 
202398a9cb79SRichard Henderson     nullify_over(ctx);
202498a9cb79SRichard Henderson 
202598a9cb79SRichard Henderson     /* ??? Do something with priv level operand.  */
202698a9cb79SRichard Henderson     dest = dest_gpr(ctx, rt);
202798a9cb79SRichard Henderson     if (is_write) {
202898a9cb79SRichard Henderson         gen_helper_probe_w(dest, load_gpr(ctx, rb));
202998a9cb79SRichard Henderson     } else {
203098a9cb79SRichard Henderson         gen_helper_probe_r(dest, load_gpr(ctx, rb));
203198a9cb79SRichard Henderson     }
203298a9cb79SRichard Henderson     save_gpr(ctx, rt, dest);
2033869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
203498a9cb79SRichard Henderson }
203598a9cb79SRichard Henderson 
203698a9cb79SRichard Henderson static const DisasInsn table_mem_mgmt[] = {
203798a9cb79SRichard Henderson     { 0x04003280u, 0xfc003fffu, trans_nop },          /* fdc, disp */
203898a9cb79SRichard Henderson     { 0x04001280u, 0xfc003fffu, trans_nop },          /* fdc, index */
203998a9cb79SRichard Henderson     { 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */
204098a9cb79SRichard Henderson     { 0x040012c0u, 0xfc003fffu, trans_nop },          /* fdce */
204198a9cb79SRichard Henderson     { 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */
204298a9cb79SRichard Henderson     { 0x04000280u, 0xfc001fffu, trans_nop },          /* fic 0a */
204398a9cb79SRichard Henderson     { 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */
204498a9cb79SRichard Henderson     { 0x040013c0u, 0xfc003fffu, trans_nop },          /* fic 4f */
204598a9cb79SRichard Henderson     { 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */
204698a9cb79SRichard Henderson     { 0x040002c0u, 0xfc001fffu, trans_nop },          /* fice */
204798a9cb79SRichard Henderson     { 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */
204898a9cb79SRichard Henderson     { 0x04002700u, 0xfc003fffu, trans_nop },          /* pdc */
204998a9cb79SRichard Henderson     { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */
205098a9cb79SRichard Henderson     { 0x04001180u, 0xfc003fa0u, trans_probe },        /* probe */
205198a9cb79SRichard Henderson     { 0x04003180u, 0xfc003fa0u, trans_probe },        /* probei */
205298a9cb79SRichard Henderson };
205398a9cb79SRichard Henderson 
2054869051eaSRichard Henderson static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn,
2055b2167459SRichard Henderson                                const DisasInsn *di)
2056b2167459SRichard Henderson {
2057b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2058b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2059b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2060b2167459SRichard Henderson     unsigned ext = extract32(insn, 8, 4);
2061b2167459SRichard Henderson     unsigned shift = extract32(insn, 6, 2);
2062b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2063eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2;
2064b2167459SRichard Henderson     bool is_c = false;
2065b2167459SRichard Henderson     bool is_l = false;
2066b2167459SRichard Henderson     bool is_tc = false;
2067b2167459SRichard Henderson     bool is_tsv = false;
2068869051eaSRichard Henderson     DisasJumpType ret;
2069b2167459SRichard Henderson 
2070b2167459SRichard Henderson     switch (ext) {
2071b2167459SRichard Henderson     case 0x6: /* ADD, SHLADD */
2072b2167459SRichard Henderson         break;
2073b2167459SRichard Henderson     case 0xa: /* ADD,L, SHLADD,L */
2074b2167459SRichard Henderson         is_l = true;
2075b2167459SRichard Henderson         break;
2076b2167459SRichard Henderson     case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
2077b2167459SRichard Henderson         is_tsv = true;
2078b2167459SRichard Henderson         break;
2079b2167459SRichard Henderson     case 0x7: /* ADD,C */
2080b2167459SRichard Henderson         is_c = true;
2081b2167459SRichard Henderson         break;
2082b2167459SRichard Henderson     case 0xf: /* ADD,C,TSV */
2083b2167459SRichard Henderson         is_c = is_tsv = true;
2084b2167459SRichard Henderson         break;
2085b2167459SRichard Henderson     default:
2086b2167459SRichard Henderson         return gen_illegal(ctx);
2087b2167459SRichard Henderson     }
2088b2167459SRichard Henderson 
2089b2167459SRichard Henderson     if (cf) {
2090b2167459SRichard Henderson         nullify_over(ctx);
2091b2167459SRichard Henderson     }
2092b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2093b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2094b2167459SRichard Henderson     ret = do_add(ctx, rt, tcg_r1, tcg_r2, shift, is_l, is_tsv, is_tc, is_c, cf);
2095b2167459SRichard Henderson     return nullify_end(ctx, ret);
2096b2167459SRichard Henderson }
2097b2167459SRichard Henderson 
2098869051eaSRichard Henderson static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn,
2099b2167459SRichard Henderson                                const DisasInsn *di)
2100b2167459SRichard Henderson {
2101b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2102b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2103b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2104b2167459SRichard Henderson     unsigned ext = extract32(insn, 6, 6);
2105b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2106eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2;
2107b2167459SRichard Henderson     bool is_b = false;
2108b2167459SRichard Henderson     bool is_tc = false;
2109b2167459SRichard Henderson     bool is_tsv = false;
2110869051eaSRichard Henderson     DisasJumpType ret;
2111b2167459SRichard Henderson 
2112b2167459SRichard Henderson     switch (ext) {
2113b2167459SRichard Henderson     case 0x10: /* SUB */
2114b2167459SRichard Henderson         break;
2115b2167459SRichard Henderson     case 0x30: /* SUB,TSV */
2116b2167459SRichard Henderson         is_tsv = true;
2117b2167459SRichard Henderson         break;
2118b2167459SRichard Henderson     case 0x14: /* SUB,B */
2119b2167459SRichard Henderson         is_b = true;
2120b2167459SRichard Henderson         break;
2121b2167459SRichard Henderson     case 0x34: /* SUB,B,TSV */
2122b2167459SRichard Henderson         is_b = is_tsv = true;
2123b2167459SRichard Henderson         break;
2124b2167459SRichard Henderson     case 0x13: /* SUB,TC */
2125b2167459SRichard Henderson         is_tc = true;
2126b2167459SRichard Henderson         break;
2127b2167459SRichard Henderson     case 0x33: /* SUB,TSV,TC */
2128b2167459SRichard Henderson         is_tc = is_tsv = true;
2129b2167459SRichard Henderson         break;
2130b2167459SRichard Henderson     default:
2131b2167459SRichard Henderson         return gen_illegal(ctx);
2132b2167459SRichard Henderson     }
2133b2167459SRichard Henderson 
2134b2167459SRichard Henderson     if (cf) {
2135b2167459SRichard Henderson         nullify_over(ctx);
2136b2167459SRichard Henderson     }
2137b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2138b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2139b2167459SRichard Henderson     ret = do_sub(ctx, rt, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, cf);
2140b2167459SRichard Henderson     return nullify_end(ctx, ret);
2141b2167459SRichard Henderson }
2142b2167459SRichard Henderson 
2143869051eaSRichard Henderson static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn,
2144b2167459SRichard Henderson                                const DisasInsn *di)
2145b2167459SRichard Henderson {
2146b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2147b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2148b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2149b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2150eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2;
2151869051eaSRichard Henderson     DisasJumpType ret;
2152b2167459SRichard Henderson 
2153b2167459SRichard Henderson     if (cf) {
2154b2167459SRichard Henderson         nullify_over(ctx);
2155b2167459SRichard Henderson     }
2156b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2157b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2158eff235ebSPaolo Bonzini     ret = do_log(ctx, rt, tcg_r1, tcg_r2, cf, di->f.ttt);
2159b2167459SRichard Henderson     return nullify_end(ctx, ret);
2160b2167459SRichard Henderson }
2161b2167459SRichard Henderson 
2162b2167459SRichard Henderson /* OR r,0,t -> COPY (according to gas) */
2163869051eaSRichard Henderson static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn,
2164b2167459SRichard Henderson                                 const DisasInsn *di)
2165b2167459SRichard Henderson {
2166b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2167b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2168b2167459SRichard Henderson 
2169b2167459SRichard Henderson     if (r1 == 0) {
2170eaa3783bSRichard Henderson         TCGv_reg dest = dest_gpr(ctx, rt);
2171eaa3783bSRichard Henderson         tcg_gen_movi_reg(dest, 0);
2172b2167459SRichard Henderson         save_gpr(ctx, rt, dest);
2173b2167459SRichard Henderson     } else {
2174b2167459SRichard Henderson         save_gpr(ctx, rt, cpu_gr[r1]);
2175b2167459SRichard Henderson     }
2176b2167459SRichard Henderson     cond_free(&ctx->null_cond);
2177869051eaSRichard Henderson     return DISAS_NEXT;
2178b2167459SRichard Henderson }
2179b2167459SRichard Henderson 
2180869051eaSRichard Henderson static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn,
2181b2167459SRichard Henderson                                   const DisasInsn *di)
2182b2167459SRichard Henderson {
2183b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2184b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2185b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2186b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2187eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2;
2188869051eaSRichard Henderson     DisasJumpType ret;
2189b2167459SRichard Henderson 
2190b2167459SRichard Henderson     if (cf) {
2191b2167459SRichard Henderson         nullify_over(ctx);
2192b2167459SRichard Henderson     }
2193b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2194b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2195b2167459SRichard Henderson     ret = do_cmpclr(ctx, rt, tcg_r1, tcg_r2, cf);
2196b2167459SRichard Henderson     return nullify_end(ctx, ret);
2197b2167459SRichard Henderson }
2198b2167459SRichard Henderson 
2199869051eaSRichard Henderson static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn,
2200b2167459SRichard Henderson                                 const DisasInsn *di)
2201b2167459SRichard Henderson {
2202b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2203b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2204b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2205b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2206eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2;
2207869051eaSRichard Henderson     DisasJumpType ret;
2208b2167459SRichard Henderson 
2209b2167459SRichard Henderson     if (cf) {
2210b2167459SRichard Henderson         nullify_over(ctx);
2211b2167459SRichard Henderson     }
2212b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2213b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2214eaa3783bSRichard Henderson     ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_reg);
2215b2167459SRichard Henderson     return nullify_end(ctx, ret);
2216b2167459SRichard Henderson }
2217b2167459SRichard Henderson 
2218869051eaSRichard Henderson static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn,
2219b2167459SRichard Henderson                                   const DisasInsn *di)
2220b2167459SRichard Henderson {
2221b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2222b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2223b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2224b2167459SRichard Henderson     unsigned is_tc = extract32(insn, 6, 1);
2225b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2226eaa3783bSRichard Henderson     TCGv_reg tcg_r1, tcg_r2, tmp;
2227869051eaSRichard Henderson     DisasJumpType ret;
2228b2167459SRichard Henderson 
2229b2167459SRichard Henderson     if (cf) {
2230b2167459SRichard Henderson         nullify_over(ctx);
2231b2167459SRichard Henderson     }
2232b2167459SRichard Henderson     tcg_r1 = load_gpr(ctx, r1);
2233b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2234b2167459SRichard Henderson     tmp = get_temp(ctx);
2235eaa3783bSRichard Henderson     tcg_gen_not_reg(tmp, tcg_r2);
2236eaa3783bSRichard Henderson     ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_reg);
2237b2167459SRichard Henderson     return nullify_end(ctx, ret);
2238b2167459SRichard Henderson }
2239b2167459SRichard Henderson 
2240869051eaSRichard Henderson static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn,
2241b2167459SRichard Henderson                                 const DisasInsn *di)
2242b2167459SRichard Henderson {
2243b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2244b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2245b2167459SRichard Henderson     unsigned is_i = extract32(insn, 6, 1);
2246b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2247eaa3783bSRichard Henderson     TCGv_reg tmp;
2248869051eaSRichard Henderson     DisasJumpType ret;
2249b2167459SRichard Henderson 
2250b2167459SRichard Henderson     nullify_over(ctx);
2251b2167459SRichard Henderson 
2252b2167459SRichard Henderson     tmp = get_temp(ctx);
2253eaa3783bSRichard Henderson     tcg_gen_shri_reg(tmp, cpu_psw_cb, 3);
2254b2167459SRichard Henderson     if (!is_i) {
2255eaa3783bSRichard Henderson         tcg_gen_not_reg(tmp, tmp);
2256b2167459SRichard Henderson     }
2257eaa3783bSRichard Henderson     tcg_gen_andi_reg(tmp, tmp, 0x11111111);
2258eaa3783bSRichard Henderson     tcg_gen_muli_reg(tmp, tmp, 6);
2259b2167459SRichard Henderson     ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false,
2260eaa3783bSRichard Henderson                   is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
2261b2167459SRichard Henderson 
2262b2167459SRichard Henderson     return nullify_end(ctx, ret);
2263b2167459SRichard Henderson }
2264b2167459SRichard Henderson 
2265869051eaSRichard Henderson static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn,
2266b2167459SRichard Henderson                               const DisasInsn *di)
2267b2167459SRichard Henderson {
2268b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2269b2167459SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
2270b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2271b2167459SRichard Henderson     unsigned rt = extract32(insn,  0, 5);
2272eaa3783bSRichard Henderson     TCGv_reg dest, add1, add2, addc, zero, in1, in2;
2273b2167459SRichard Henderson 
2274b2167459SRichard Henderson     nullify_over(ctx);
2275b2167459SRichard Henderson 
2276b2167459SRichard Henderson     in1 = load_gpr(ctx, r1);
2277b2167459SRichard Henderson     in2 = load_gpr(ctx, r2);
2278b2167459SRichard Henderson 
2279b2167459SRichard Henderson     add1 = tcg_temp_new();
2280b2167459SRichard Henderson     add2 = tcg_temp_new();
2281b2167459SRichard Henderson     addc = tcg_temp_new();
2282b2167459SRichard Henderson     dest = tcg_temp_new();
2283eaa3783bSRichard Henderson     zero = tcg_const_reg(0);
2284b2167459SRichard Henderson 
2285b2167459SRichard Henderson     /* Form R1 << 1 | PSW[CB]{8}.  */
2286eaa3783bSRichard Henderson     tcg_gen_add_reg(add1, in1, in1);
2287eaa3783bSRichard Henderson     tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb);
2288b2167459SRichard Henderson 
2289b2167459SRichard Henderson     /* Add or subtract R2, depending on PSW[V].  Proper computation of
2290b2167459SRichard Henderson        carry{8} requires that we subtract via + ~R2 + 1, as described in
2291b2167459SRichard Henderson        the manual.  By extracting and masking V, we can produce the
2292b2167459SRichard Henderson        proper inputs to the addition without movcond.  */
2293eaa3783bSRichard Henderson     tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1);
2294eaa3783bSRichard Henderson     tcg_gen_xor_reg(add2, in2, addc);
2295eaa3783bSRichard Henderson     tcg_gen_andi_reg(addc, addc, 1);
2296b2167459SRichard Henderson     /* ??? This is only correct for 32-bit.  */
2297b2167459SRichard Henderson     tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
2298b2167459SRichard Henderson     tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
2299b2167459SRichard Henderson 
2300b2167459SRichard Henderson     tcg_temp_free(addc);
2301b2167459SRichard Henderson     tcg_temp_free(zero);
2302b2167459SRichard Henderson 
2303b2167459SRichard Henderson     /* Write back the result register.  */
2304b2167459SRichard Henderson     save_gpr(ctx, rt, dest);
2305b2167459SRichard Henderson 
2306b2167459SRichard Henderson     /* Write back PSW[CB].  */
2307eaa3783bSRichard Henderson     tcg_gen_xor_reg(cpu_psw_cb, add1, add2);
2308eaa3783bSRichard Henderson     tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest);
2309b2167459SRichard Henderson 
2310b2167459SRichard Henderson     /* Write back PSW[V] for the division step.  */
2311eaa3783bSRichard Henderson     tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb);
2312eaa3783bSRichard Henderson     tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
2313b2167459SRichard Henderson 
2314b2167459SRichard Henderson     /* Install the new nullification.  */
2315b2167459SRichard Henderson     if (cf) {
2316eaa3783bSRichard Henderson         TCGv_reg sv = NULL;
2317b2167459SRichard Henderson         if (cf >> 1 == 6) {
2318b2167459SRichard Henderson             /* ??? The lshift is supposed to contribute to overflow.  */
2319b2167459SRichard Henderson             sv = do_add_sv(ctx, dest, add1, add2);
2320b2167459SRichard Henderson         }
2321b2167459SRichard Henderson         ctx->null_cond = do_cond(cf, dest, cpu_psw_cb_msb, sv);
2322b2167459SRichard Henderson     }
2323b2167459SRichard Henderson 
2324b2167459SRichard Henderson     tcg_temp_free(add1);
2325b2167459SRichard Henderson     tcg_temp_free(add2);
2326b2167459SRichard Henderson     tcg_temp_free(dest);
2327b2167459SRichard Henderson 
2328869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
2329b2167459SRichard Henderson }
2330b2167459SRichard Henderson 
2331b2167459SRichard Henderson static const DisasInsn table_arith_log[] = {
2332b2167459SRichard Henderson     { 0x08000240u, 0xfc00ffffu, trans_nop },  /* or x,y,0 */
2333b2167459SRichard Henderson     { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */
2334eaa3783bSRichard Henderson     { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg },
2335eaa3783bSRichard Henderson     { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg },
2336eaa3783bSRichard Henderson     { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg },
2337eaa3783bSRichard Henderson     { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_reg },
2338b2167459SRichard Henderson     { 0x08000880u, 0xfc000fe0u, trans_cmpclr },
2339b2167459SRichard Henderson     { 0x08000380u, 0xfc000fe0u, trans_uxor },
2340b2167459SRichard Henderson     { 0x08000980u, 0xfc000fa0u, trans_uaddcm },
2341b2167459SRichard Henderson     { 0x08000b80u, 0xfc1f0fa0u, trans_dcor },
2342b2167459SRichard Henderson     { 0x08000440u, 0xfc000fe0u, trans_ds },
2343b2167459SRichard Henderson     { 0x08000700u, 0xfc0007e0u, trans_add }, /* add */
2344b2167459SRichard Henderson     { 0x08000400u, 0xfc0006e0u, trans_sub }, /* sub; sub,b; sub,tsv */
2345b2167459SRichard Henderson     { 0x080004c0u, 0xfc0007e0u, trans_sub }, /* sub,tc; sub,tsv,tc */
2346b2167459SRichard Henderson     { 0x08000200u, 0xfc000320u, trans_add }, /* shladd */
2347b2167459SRichard Henderson };
2348b2167459SRichard Henderson 
2349869051eaSRichard Henderson static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn)
2350b2167459SRichard Henderson {
2351eaa3783bSRichard Henderson     target_sreg im = low_sextract(insn, 0, 11);
2352b2167459SRichard Henderson     unsigned e1 = extract32(insn, 11, 1);
2353b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2354b2167459SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2355b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2356b2167459SRichard Henderson     unsigned o1 = extract32(insn, 26, 1);
2357eaa3783bSRichard Henderson     TCGv_reg tcg_im, tcg_r2;
2358869051eaSRichard Henderson     DisasJumpType ret;
2359b2167459SRichard Henderson 
2360b2167459SRichard Henderson     if (cf) {
2361b2167459SRichard Henderson         nullify_over(ctx);
2362b2167459SRichard Henderson     }
2363b2167459SRichard Henderson 
2364b2167459SRichard Henderson     tcg_im = load_const(ctx, im);
2365b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2366b2167459SRichard Henderson     ret = do_add(ctx, rt, tcg_im, tcg_r2, 0, false, e1, !o1, false, cf);
2367b2167459SRichard Henderson 
2368b2167459SRichard Henderson     return nullify_end(ctx, ret);
2369b2167459SRichard Henderson }
2370b2167459SRichard Henderson 
2371869051eaSRichard Henderson static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn)
2372b2167459SRichard Henderson {
2373eaa3783bSRichard Henderson     target_sreg im = low_sextract(insn, 0, 11);
2374b2167459SRichard Henderson     unsigned e1 = extract32(insn, 11, 1);
2375b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2376b2167459SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2377b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2378eaa3783bSRichard Henderson     TCGv_reg tcg_im, tcg_r2;
2379869051eaSRichard Henderson     DisasJumpType ret;
2380b2167459SRichard Henderson 
2381b2167459SRichard Henderson     if (cf) {
2382b2167459SRichard Henderson         nullify_over(ctx);
2383b2167459SRichard Henderson     }
2384b2167459SRichard Henderson 
2385b2167459SRichard Henderson     tcg_im = load_const(ctx, im);
2386b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2387b2167459SRichard Henderson     ret = do_sub(ctx, rt, tcg_im, tcg_r2, e1, false, false, cf);
2388b2167459SRichard Henderson 
2389b2167459SRichard Henderson     return nullify_end(ctx, ret);
2390b2167459SRichard Henderson }
2391b2167459SRichard Henderson 
2392869051eaSRichard Henderson static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn)
2393b2167459SRichard Henderson {
2394eaa3783bSRichard Henderson     target_sreg im = low_sextract(insn, 0, 11);
2395b2167459SRichard Henderson     unsigned cf = extract32(insn, 12, 4);
2396b2167459SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2397b2167459SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2398eaa3783bSRichard Henderson     TCGv_reg tcg_im, tcg_r2;
2399869051eaSRichard Henderson     DisasJumpType ret;
2400b2167459SRichard Henderson 
2401b2167459SRichard Henderson     if (cf) {
2402b2167459SRichard Henderson         nullify_over(ctx);
2403b2167459SRichard Henderson     }
2404b2167459SRichard Henderson 
2405b2167459SRichard Henderson     tcg_im = load_const(ctx, im);
2406b2167459SRichard Henderson     tcg_r2 = load_gpr(ctx, r2);
2407b2167459SRichard Henderson     ret = do_cmpclr(ctx, rt, tcg_im, tcg_r2, cf);
2408b2167459SRichard Henderson 
2409b2167459SRichard Henderson     return nullify_end(ctx, ret);
2410b2167459SRichard Henderson }
2411b2167459SRichard Henderson 
2412869051eaSRichard Henderson static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn,
241396d6407fSRichard Henderson                                     const DisasInsn *di)
241496d6407fSRichard Henderson {
241596d6407fSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
241696d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
241796d6407fSRichard Henderson     unsigned sz = extract32(insn, 6, 2);
241896d6407fSRichard Henderson     unsigned a = extract32(insn, 13, 1);
241996d6407fSRichard Henderson     int disp = low_sextract(insn, 16, 5);
242096d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
242196d6407fSRichard Henderson     int modify = (m ? (a ? -1 : 1) : 0);
242296d6407fSRichard Henderson     TCGMemOp mop = MO_TE | sz;
242396d6407fSRichard Henderson 
242496d6407fSRichard Henderson     return do_load(ctx, rt, rb, 0, 0, disp, modify, mop);
242596d6407fSRichard Henderson }
242696d6407fSRichard Henderson 
2427869051eaSRichard Henderson static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn,
242896d6407fSRichard Henderson                                     const DisasInsn *di)
242996d6407fSRichard Henderson {
243096d6407fSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
243196d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
243296d6407fSRichard Henderson     unsigned sz = extract32(insn, 6, 2);
243396d6407fSRichard Henderson     unsigned u = extract32(insn, 13, 1);
243496d6407fSRichard Henderson     unsigned rx = extract32(insn, 16, 5);
243596d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
243696d6407fSRichard Henderson     TCGMemOp mop = MO_TE | sz;
243796d6407fSRichard Henderson 
243896d6407fSRichard Henderson     return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, m, mop);
243996d6407fSRichard Henderson }
244096d6407fSRichard Henderson 
2441869051eaSRichard Henderson static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn,
244296d6407fSRichard Henderson                                     const DisasInsn *di)
244396d6407fSRichard Henderson {
244496d6407fSRichard Henderson     int disp = low_sextract(insn, 0, 5);
244596d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
244696d6407fSRichard Henderson     unsigned sz = extract32(insn, 6, 2);
244796d6407fSRichard Henderson     unsigned a = extract32(insn, 13, 1);
244896d6407fSRichard Henderson     unsigned rr = extract32(insn, 16, 5);
244996d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
245096d6407fSRichard Henderson     int modify = (m ? (a ? -1 : 1) : 0);
245196d6407fSRichard Henderson     TCGMemOp mop = MO_TE | sz;
245296d6407fSRichard Henderson 
245396d6407fSRichard Henderson     return do_store(ctx, rr, rb, disp, modify, mop);
245496d6407fSRichard Henderson }
245596d6407fSRichard Henderson 
2456869051eaSRichard Henderson static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn,
245796d6407fSRichard Henderson                                 const DisasInsn *di)
245896d6407fSRichard Henderson {
245996d6407fSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
246096d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
246196d6407fSRichard Henderson     unsigned i = extract32(insn, 12, 1);
246296d6407fSRichard Henderson     unsigned au = extract32(insn, 13, 1);
246396d6407fSRichard Henderson     unsigned rx = extract32(insn, 16, 5);
246496d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
246596d6407fSRichard Henderson     TCGMemOp mop = MO_TEUL | MO_ALIGN_16;
2466eaa3783bSRichard Henderson     TCGv_reg zero, addr, base, dest;
246796d6407fSRichard Henderson     int modify, disp = 0, scale = 0;
246896d6407fSRichard Henderson 
246996d6407fSRichard Henderson     nullify_over(ctx);
247096d6407fSRichard Henderson 
247196d6407fSRichard Henderson     /* ??? Share more code with do_load and do_load_{32,64}.  */
247296d6407fSRichard Henderson 
247396d6407fSRichard Henderson     if (i) {
247496d6407fSRichard Henderson         modify = (m ? (au ? -1 : 1) : 0);
247596d6407fSRichard Henderson         disp = low_sextract(rx, 0, 5);
247696d6407fSRichard Henderson         rx = 0;
247796d6407fSRichard Henderson     } else {
247896d6407fSRichard Henderson         modify = m;
247996d6407fSRichard Henderson         if (au) {
248096d6407fSRichard Henderson             scale = mop & MO_SIZE;
248196d6407fSRichard Henderson         }
248296d6407fSRichard Henderson     }
248396d6407fSRichard Henderson     if (modify) {
248496d6407fSRichard Henderson         /* Base register modification.  Make sure if RT == RB, we see
248596d6407fSRichard Henderson            the result of the load.  */
248696d6407fSRichard Henderson         dest = get_temp(ctx);
248796d6407fSRichard Henderson     } else {
248896d6407fSRichard Henderson         dest = dest_gpr(ctx, rt);
248996d6407fSRichard Henderson     }
249096d6407fSRichard Henderson 
249196d6407fSRichard Henderson     addr = tcg_temp_new();
249296d6407fSRichard Henderson     base = load_gpr(ctx, rb);
249396d6407fSRichard Henderson     if (rx) {
2494eaa3783bSRichard Henderson         tcg_gen_shli_reg(addr, cpu_gr[rx], scale);
2495eaa3783bSRichard Henderson         tcg_gen_add_reg(addr, addr, base);
249696d6407fSRichard Henderson     } else {
2497eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, base, disp);
249896d6407fSRichard Henderson     }
249996d6407fSRichard Henderson 
2500eaa3783bSRichard Henderson     zero = tcg_const_reg(0);
2501eaa3783bSRichard Henderson     tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base),
2502*3d68ee7bSRichard Henderson                             zero, ctx->mmu_idx, mop);
250396d6407fSRichard Henderson     if (modify) {
250496d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
250596d6407fSRichard Henderson     }
250696d6407fSRichard Henderson     save_gpr(ctx, rt, dest);
250796d6407fSRichard Henderson 
2508869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
250996d6407fSRichard Henderson }
251096d6407fSRichard Henderson 
2511869051eaSRichard Henderson static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn,
251296d6407fSRichard Henderson                                 const DisasInsn *di)
251396d6407fSRichard Henderson {
2514eaa3783bSRichard Henderson     target_sreg disp = low_sextract(insn, 0, 5);
251596d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
251696d6407fSRichard Henderson     unsigned a = extract32(insn, 13, 1);
251796d6407fSRichard Henderson     unsigned rt = extract32(insn, 16, 5);
251896d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
2519eaa3783bSRichard Henderson     TCGv_reg addr, val;
252096d6407fSRichard Henderson 
252196d6407fSRichard Henderson     nullify_over(ctx);
252296d6407fSRichard Henderson 
252396d6407fSRichard Henderson     addr = tcg_temp_new();
252496d6407fSRichard Henderson     if (m || disp == 0) {
2525eaa3783bSRichard Henderson         tcg_gen_mov_reg(addr, load_gpr(ctx, rb));
252696d6407fSRichard Henderson     } else {
2527eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, load_gpr(ctx, rb), disp);
252896d6407fSRichard Henderson     }
252996d6407fSRichard Henderson     val = load_gpr(ctx, rt);
253096d6407fSRichard Henderson 
253196d6407fSRichard Henderson     if (a) {
2532f9f46db4SEmilio G. Cota         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2533f9f46db4SEmilio G. Cota             gen_helper_stby_e_parallel(cpu_env, addr, val);
2534f9f46db4SEmilio G. Cota         } else {
253596d6407fSRichard Henderson             gen_helper_stby_e(cpu_env, addr, val);
2536f9f46db4SEmilio G. Cota         }
2537f9f46db4SEmilio G. Cota     } else {
2538f9f46db4SEmilio G. Cota         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2539f9f46db4SEmilio G. Cota             gen_helper_stby_b_parallel(cpu_env, addr, val);
254096d6407fSRichard Henderson         } else {
254196d6407fSRichard Henderson             gen_helper_stby_b(cpu_env, addr, val);
254296d6407fSRichard Henderson         }
2543f9f46db4SEmilio G. Cota     }
254496d6407fSRichard Henderson 
254596d6407fSRichard Henderson     if (m) {
2546eaa3783bSRichard Henderson         tcg_gen_addi_reg(addr, addr, disp);
2547eaa3783bSRichard Henderson         tcg_gen_andi_reg(addr, addr, ~3);
254896d6407fSRichard Henderson         save_gpr(ctx, rb, addr);
254996d6407fSRichard Henderson     }
255096d6407fSRichard Henderson     tcg_temp_free(addr);
255196d6407fSRichard Henderson 
2552869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
255396d6407fSRichard Henderson }
255496d6407fSRichard Henderson 
255596d6407fSRichard Henderson static const DisasInsn table_index_mem[] = {
255696d6407fSRichard Henderson     { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */
255796d6407fSRichard Henderson     { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */
255896d6407fSRichard Henderson     { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */
255996d6407fSRichard Henderson     { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
256096d6407fSRichard Henderson     { 0x0c001300u, 0xfc0013c0, trans_stby },
256196d6407fSRichard Henderson };
256296d6407fSRichard Henderson 
2563869051eaSRichard Henderson static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn)
2564b2167459SRichard Henderson {
2565b2167459SRichard Henderson     unsigned rt = extract32(insn, 21, 5);
2566eaa3783bSRichard Henderson     target_sreg i = assemble_21(insn);
2567eaa3783bSRichard Henderson     TCGv_reg tcg_rt = dest_gpr(ctx, rt);
2568b2167459SRichard Henderson 
2569eaa3783bSRichard Henderson     tcg_gen_movi_reg(tcg_rt, i);
2570b2167459SRichard Henderson     save_gpr(ctx, rt, tcg_rt);
2571b2167459SRichard Henderson     cond_free(&ctx->null_cond);
2572b2167459SRichard Henderson 
2573869051eaSRichard Henderson     return DISAS_NEXT;
2574b2167459SRichard Henderson }
2575b2167459SRichard Henderson 
2576869051eaSRichard Henderson static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn)
2577b2167459SRichard Henderson {
2578b2167459SRichard Henderson     unsigned rt = extract32(insn, 21, 5);
2579eaa3783bSRichard Henderson     target_sreg i = assemble_21(insn);
2580eaa3783bSRichard Henderson     TCGv_reg tcg_rt = load_gpr(ctx, rt);
2581eaa3783bSRichard Henderson     TCGv_reg tcg_r1 = dest_gpr(ctx, 1);
2582b2167459SRichard Henderson 
2583eaa3783bSRichard Henderson     tcg_gen_addi_reg(tcg_r1, tcg_rt, i);
2584b2167459SRichard Henderson     save_gpr(ctx, 1, tcg_r1);
2585b2167459SRichard Henderson     cond_free(&ctx->null_cond);
2586b2167459SRichard Henderson 
2587869051eaSRichard Henderson     return DISAS_NEXT;
2588b2167459SRichard Henderson }
2589b2167459SRichard Henderson 
2590869051eaSRichard Henderson static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn)
2591b2167459SRichard Henderson {
2592b2167459SRichard Henderson     unsigned rb = extract32(insn, 21, 5);
2593b2167459SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2594eaa3783bSRichard Henderson     target_sreg i = assemble_16(insn);
2595eaa3783bSRichard Henderson     TCGv_reg tcg_rt = dest_gpr(ctx, rt);
2596b2167459SRichard Henderson 
2597b2167459SRichard Henderson     /* Special case rb == 0, for the LDI pseudo-op.
2598b2167459SRichard Henderson        The COPY pseudo-op is handled for free within tcg_gen_addi_tl.  */
2599b2167459SRichard Henderson     if (rb == 0) {
2600eaa3783bSRichard Henderson         tcg_gen_movi_reg(tcg_rt, i);
2601b2167459SRichard Henderson     } else {
2602eaa3783bSRichard Henderson         tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i);
2603b2167459SRichard Henderson     }
2604b2167459SRichard Henderson     save_gpr(ctx, rt, tcg_rt);
2605b2167459SRichard Henderson     cond_free(&ctx->null_cond);
2606b2167459SRichard Henderson 
2607869051eaSRichard Henderson     return DISAS_NEXT;
2608b2167459SRichard Henderson }
2609b2167459SRichard Henderson 
2610869051eaSRichard Henderson static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn,
261196d6407fSRichard Henderson                                 bool is_mod, TCGMemOp mop)
261296d6407fSRichard Henderson {
261396d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
261496d6407fSRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2615eaa3783bSRichard Henderson     target_sreg i = assemble_16(insn);
261696d6407fSRichard Henderson 
261796d6407fSRichard Henderson     return do_load(ctx, rt, rb, 0, 0, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
261896d6407fSRichard Henderson }
261996d6407fSRichard Henderson 
2620869051eaSRichard Henderson static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn)
262196d6407fSRichard Henderson {
262296d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
262396d6407fSRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2624eaa3783bSRichard Henderson     target_sreg i = assemble_16a(insn);
262596d6407fSRichard Henderson     unsigned ext2 = extract32(insn, 1, 2);
262696d6407fSRichard Henderson 
262796d6407fSRichard Henderson     switch (ext2) {
262896d6407fSRichard Henderson     case 0:
262996d6407fSRichard Henderson     case 1:
263096d6407fSRichard Henderson         /* FLDW without modification.  */
263196d6407fSRichard Henderson         return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0);
263296d6407fSRichard Henderson     case 2:
263396d6407fSRichard Henderson         /* LDW with modification.  Note that the sign of I selects
263496d6407fSRichard Henderson            post-dec vs pre-inc.  */
263596d6407fSRichard Henderson         return do_load(ctx, rt, rb, 0, 0, i, (i < 0 ? 1 : -1), MO_TEUL);
263696d6407fSRichard Henderson     default:
263796d6407fSRichard Henderson         return gen_illegal(ctx);
263896d6407fSRichard Henderson     }
263996d6407fSRichard Henderson }
264096d6407fSRichard Henderson 
2641869051eaSRichard Henderson static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn)
264296d6407fSRichard Henderson {
2643eaa3783bSRichard Henderson     target_sreg i = assemble_16a(insn);
264496d6407fSRichard Henderson     unsigned t1 = extract32(insn, 1, 1);
264596d6407fSRichard Henderson     unsigned a = extract32(insn, 2, 1);
264696d6407fSRichard Henderson     unsigned t0 = extract32(insn, 16, 5);
264796d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
264896d6407fSRichard Henderson 
264996d6407fSRichard Henderson     /* FLDW with modification.  */
265096d6407fSRichard Henderson     return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1));
265196d6407fSRichard Henderson }
265296d6407fSRichard Henderson 
2653869051eaSRichard Henderson static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn,
265496d6407fSRichard Henderson                                  bool is_mod, TCGMemOp mop)
265596d6407fSRichard Henderson {
265696d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
265796d6407fSRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2658eaa3783bSRichard Henderson     target_sreg i = assemble_16(insn);
265996d6407fSRichard Henderson 
266096d6407fSRichard Henderson     return do_store(ctx, rt, rb, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
266196d6407fSRichard Henderson }
266296d6407fSRichard Henderson 
2663869051eaSRichard Henderson static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn)
266496d6407fSRichard Henderson {
266596d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
266696d6407fSRichard Henderson     unsigned rt = extract32(insn, 16, 5);
2667eaa3783bSRichard Henderson     target_sreg i = assemble_16a(insn);
266896d6407fSRichard Henderson     unsigned ext2 = extract32(insn, 1, 2);
266996d6407fSRichard Henderson 
267096d6407fSRichard Henderson     switch (ext2) {
267196d6407fSRichard Henderson     case 0:
267296d6407fSRichard Henderson     case 1:
267396d6407fSRichard Henderson         /* FSTW without modification.  */
267496d6407fSRichard Henderson         return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0);
267596d6407fSRichard Henderson     case 2:
267696d6407fSRichard Henderson         /* LDW with modification.  */
267796d6407fSRichard Henderson         return do_store(ctx, rt, rb, i, (i < 0 ? 1 : -1), MO_TEUL);
267896d6407fSRichard Henderson     default:
267996d6407fSRichard Henderson         return gen_illegal(ctx);
268096d6407fSRichard Henderson     }
268196d6407fSRichard Henderson }
268296d6407fSRichard Henderson 
2683869051eaSRichard Henderson static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn)
268496d6407fSRichard Henderson {
2685eaa3783bSRichard Henderson     target_sreg i = assemble_16a(insn);
268696d6407fSRichard Henderson     unsigned t1 = extract32(insn, 1, 1);
268796d6407fSRichard Henderson     unsigned a = extract32(insn, 2, 1);
268896d6407fSRichard Henderson     unsigned t0 = extract32(insn, 16, 5);
268996d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
269096d6407fSRichard Henderson 
269196d6407fSRichard Henderson     /* FSTW with modification.  */
269296d6407fSRichard Henderson     return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1));
269396d6407fSRichard Henderson }
269496d6407fSRichard Henderson 
2695869051eaSRichard Henderson static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn)
269696d6407fSRichard Henderson {
269796d6407fSRichard Henderson     unsigned t0 = extract32(insn, 0, 5);
269896d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
269996d6407fSRichard Henderson     unsigned t1 = extract32(insn, 6, 1);
270096d6407fSRichard Henderson     unsigned ext3 = extract32(insn, 7, 3);
270196d6407fSRichard Henderson     /* unsigned cc = extract32(insn, 10, 2); */
270296d6407fSRichard Henderson     unsigned i = extract32(insn, 12, 1);
270396d6407fSRichard Henderson     unsigned ua = extract32(insn, 13, 1);
270496d6407fSRichard Henderson     unsigned rx = extract32(insn, 16, 5);
270596d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
270696d6407fSRichard Henderson     unsigned rt = t1 * 32 + t0;
270796d6407fSRichard Henderson     int modify = (m ? (ua ? -1 : 1) : 0);
270896d6407fSRichard Henderson     int disp, scale;
270996d6407fSRichard Henderson 
271096d6407fSRichard Henderson     if (i == 0) {
271196d6407fSRichard Henderson         scale = (ua ? 2 : 0);
271296d6407fSRichard Henderson         disp = 0;
271396d6407fSRichard Henderson         modify = m;
271496d6407fSRichard Henderson     } else {
271596d6407fSRichard Henderson         disp = low_sextract(rx, 0, 5);
271696d6407fSRichard Henderson         scale = 0;
271796d6407fSRichard Henderson         rx = 0;
271896d6407fSRichard Henderson         modify = (m ? (ua ? -1 : 1) : 0);
271996d6407fSRichard Henderson     }
272096d6407fSRichard Henderson 
272196d6407fSRichard Henderson     switch (ext3) {
272296d6407fSRichard Henderson     case 0: /* FLDW */
272396d6407fSRichard Henderson         return do_floadw(ctx, rt, rb, rx, scale, disp, modify);
272496d6407fSRichard Henderson     case 4: /* FSTW */
272596d6407fSRichard Henderson         return do_fstorew(ctx, rt, rb, rx, scale, disp, modify);
272696d6407fSRichard Henderson     }
272796d6407fSRichard Henderson     return gen_illegal(ctx);
272896d6407fSRichard Henderson }
272996d6407fSRichard Henderson 
2730869051eaSRichard Henderson static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn)
273196d6407fSRichard Henderson {
273296d6407fSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
273396d6407fSRichard Henderson     unsigned m = extract32(insn, 5, 1);
273496d6407fSRichard Henderson     unsigned ext4 = extract32(insn, 6, 4);
273596d6407fSRichard Henderson     /* unsigned cc = extract32(insn, 10, 2); */
273696d6407fSRichard Henderson     unsigned i = extract32(insn, 12, 1);
273796d6407fSRichard Henderson     unsigned ua = extract32(insn, 13, 1);
273896d6407fSRichard Henderson     unsigned rx = extract32(insn, 16, 5);
273996d6407fSRichard Henderson     unsigned rb = extract32(insn, 21, 5);
274096d6407fSRichard Henderson     int modify = (m ? (ua ? -1 : 1) : 0);
274196d6407fSRichard Henderson     int disp, scale;
274296d6407fSRichard Henderson 
274396d6407fSRichard Henderson     if (i == 0) {
274496d6407fSRichard Henderson         scale = (ua ? 3 : 0);
274596d6407fSRichard Henderson         disp = 0;
274696d6407fSRichard Henderson         modify = m;
274796d6407fSRichard Henderson     } else {
274896d6407fSRichard Henderson         disp = low_sextract(rx, 0, 5);
274996d6407fSRichard Henderson         scale = 0;
275096d6407fSRichard Henderson         rx = 0;
275196d6407fSRichard Henderson         modify = (m ? (ua ? -1 : 1) : 0);
275296d6407fSRichard Henderson     }
275396d6407fSRichard Henderson 
275496d6407fSRichard Henderson     switch (ext4) {
275596d6407fSRichard Henderson     case 0: /* FLDD */
275696d6407fSRichard Henderson         return do_floadd(ctx, rt, rb, rx, scale, disp, modify);
275796d6407fSRichard Henderson     case 8: /* FSTD */
275896d6407fSRichard Henderson         return do_fstored(ctx, rt, rb, rx, scale, disp, modify);
275996d6407fSRichard Henderson     default:
276096d6407fSRichard Henderson         return gen_illegal(ctx);
276196d6407fSRichard Henderson     }
276296d6407fSRichard Henderson }
276396d6407fSRichard Henderson 
2764869051eaSRichard Henderson static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn,
276598cd9ca7SRichard Henderson                                 bool is_true, bool is_imm, bool is_dw)
276698cd9ca7SRichard Henderson {
2767eaa3783bSRichard Henderson     target_sreg disp = assemble_12(insn) * 4;
276898cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
276998cd9ca7SRichard Henderson     unsigned c = extract32(insn, 13, 3);
277098cd9ca7SRichard Henderson     unsigned r = extract32(insn, 21, 5);
277198cd9ca7SRichard Henderson     unsigned cf = c * 2 + !is_true;
2772eaa3783bSRichard Henderson     TCGv_reg dest, in1, in2, sv;
277398cd9ca7SRichard Henderson     DisasCond cond;
277498cd9ca7SRichard Henderson 
277598cd9ca7SRichard Henderson     nullify_over(ctx);
277698cd9ca7SRichard Henderson 
277798cd9ca7SRichard Henderson     if (is_imm) {
277898cd9ca7SRichard Henderson         in1 = load_const(ctx, low_sextract(insn, 16, 5));
277998cd9ca7SRichard Henderson     } else {
278098cd9ca7SRichard Henderson         in1 = load_gpr(ctx, extract32(insn, 16, 5));
278198cd9ca7SRichard Henderson     }
278298cd9ca7SRichard Henderson     in2 = load_gpr(ctx, r);
278398cd9ca7SRichard Henderson     dest = get_temp(ctx);
278498cd9ca7SRichard Henderson 
2785eaa3783bSRichard Henderson     tcg_gen_sub_reg(dest, in1, in2);
278698cd9ca7SRichard Henderson 
2787f764718dSRichard Henderson     sv = NULL;
278898cd9ca7SRichard Henderson     if (c == 6) {
278998cd9ca7SRichard Henderson         sv = do_sub_sv(ctx, dest, in1, in2);
279098cd9ca7SRichard Henderson     }
279198cd9ca7SRichard Henderson 
279298cd9ca7SRichard Henderson     cond = do_sub_cond(cf, dest, in1, in2, sv);
279398cd9ca7SRichard Henderson     return do_cbranch(ctx, disp, n, &cond);
279498cd9ca7SRichard Henderson }
279598cd9ca7SRichard Henderson 
2796869051eaSRichard Henderson static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn,
279798cd9ca7SRichard Henderson                                 bool is_true, bool is_imm)
279898cd9ca7SRichard Henderson {
2799eaa3783bSRichard Henderson     target_sreg disp = assemble_12(insn) * 4;
280098cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
280198cd9ca7SRichard Henderson     unsigned c = extract32(insn, 13, 3);
280298cd9ca7SRichard Henderson     unsigned r = extract32(insn, 21, 5);
280398cd9ca7SRichard Henderson     unsigned cf = c * 2 + !is_true;
2804eaa3783bSRichard Henderson     TCGv_reg dest, in1, in2, sv, cb_msb;
280598cd9ca7SRichard Henderson     DisasCond cond;
280698cd9ca7SRichard Henderson 
280798cd9ca7SRichard Henderson     nullify_over(ctx);
280898cd9ca7SRichard Henderson 
280998cd9ca7SRichard Henderson     if (is_imm) {
281098cd9ca7SRichard Henderson         in1 = load_const(ctx, low_sextract(insn, 16, 5));
281198cd9ca7SRichard Henderson     } else {
281298cd9ca7SRichard Henderson         in1 = load_gpr(ctx, extract32(insn, 16, 5));
281398cd9ca7SRichard Henderson     }
281498cd9ca7SRichard Henderson     in2 = load_gpr(ctx, r);
281598cd9ca7SRichard Henderson     dest = dest_gpr(ctx, r);
2816f764718dSRichard Henderson     sv = NULL;
2817f764718dSRichard Henderson     cb_msb = NULL;
281898cd9ca7SRichard Henderson 
281998cd9ca7SRichard Henderson     switch (c) {
282098cd9ca7SRichard Henderson     default:
2821eaa3783bSRichard Henderson         tcg_gen_add_reg(dest, in1, in2);
282298cd9ca7SRichard Henderson         break;
282398cd9ca7SRichard Henderson     case 4: case 5:
282498cd9ca7SRichard Henderson         cb_msb = get_temp(ctx);
2825eaa3783bSRichard Henderson         tcg_gen_movi_reg(cb_msb, 0);
2826eaa3783bSRichard Henderson         tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
282798cd9ca7SRichard Henderson         break;
282898cd9ca7SRichard Henderson     case 6:
2829eaa3783bSRichard Henderson         tcg_gen_add_reg(dest, in1, in2);
283098cd9ca7SRichard Henderson         sv = do_add_sv(ctx, dest, in1, in2);
283198cd9ca7SRichard Henderson         break;
283298cd9ca7SRichard Henderson     }
283398cd9ca7SRichard Henderson 
283498cd9ca7SRichard Henderson     cond = do_cond(cf, dest, cb_msb, sv);
283598cd9ca7SRichard Henderson     return do_cbranch(ctx, disp, n, &cond);
283698cd9ca7SRichard Henderson }
283798cd9ca7SRichard Henderson 
2838869051eaSRichard Henderson static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn)
283998cd9ca7SRichard Henderson {
2840eaa3783bSRichard Henderson     target_sreg disp = assemble_12(insn) * 4;
284198cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
284298cd9ca7SRichard Henderson     unsigned c = extract32(insn, 15, 1);
284398cd9ca7SRichard Henderson     unsigned r = extract32(insn, 16, 5);
284498cd9ca7SRichard Henderson     unsigned p = extract32(insn, 21, 5);
284598cd9ca7SRichard Henderson     unsigned i = extract32(insn, 26, 1);
2846eaa3783bSRichard Henderson     TCGv_reg tmp, tcg_r;
284798cd9ca7SRichard Henderson     DisasCond cond;
284898cd9ca7SRichard Henderson 
284998cd9ca7SRichard Henderson     nullify_over(ctx);
285098cd9ca7SRichard Henderson 
285198cd9ca7SRichard Henderson     tmp = tcg_temp_new();
285298cd9ca7SRichard Henderson     tcg_r = load_gpr(ctx, r);
285398cd9ca7SRichard Henderson     if (i) {
2854eaa3783bSRichard Henderson         tcg_gen_shli_reg(tmp, tcg_r, p);
285598cd9ca7SRichard Henderson     } else {
2856eaa3783bSRichard Henderson         tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
285798cd9ca7SRichard Henderson     }
285898cd9ca7SRichard Henderson 
285998cd9ca7SRichard Henderson     cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp);
286098cd9ca7SRichard Henderson     tcg_temp_free(tmp);
286198cd9ca7SRichard Henderson     return do_cbranch(ctx, disp, n, &cond);
286298cd9ca7SRichard Henderson }
286398cd9ca7SRichard Henderson 
2864869051eaSRichard Henderson static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm)
286598cd9ca7SRichard Henderson {
2866eaa3783bSRichard Henderson     target_sreg disp = assemble_12(insn) * 4;
286798cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
286898cd9ca7SRichard Henderson     unsigned c = extract32(insn, 13, 3);
286998cd9ca7SRichard Henderson     unsigned t = extract32(insn, 16, 5);
287098cd9ca7SRichard Henderson     unsigned r = extract32(insn, 21, 5);
2871eaa3783bSRichard Henderson     TCGv_reg dest;
287298cd9ca7SRichard Henderson     DisasCond cond;
287398cd9ca7SRichard Henderson 
287498cd9ca7SRichard Henderson     nullify_over(ctx);
287598cd9ca7SRichard Henderson 
287698cd9ca7SRichard Henderson     dest = dest_gpr(ctx, r);
287798cd9ca7SRichard Henderson     if (is_imm) {
2878eaa3783bSRichard Henderson         tcg_gen_movi_reg(dest, low_sextract(t, 0, 5));
287998cd9ca7SRichard Henderson     } else if (t == 0) {
2880eaa3783bSRichard Henderson         tcg_gen_movi_reg(dest, 0);
288198cd9ca7SRichard Henderson     } else {
2882eaa3783bSRichard Henderson         tcg_gen_mov_reg(dest, cpu_gr[t]);
288398cd9ca7SRichard Henderson     }
288498cd9ca7SRichard Henderson 
288598cd9ca7SRichard Henderson     cond = do_sed_cond(c, dest);
288698cd9ca7SRichard Henderson     return do_cbranch(ctx, disp, n, &cond);
288798cd9ca7SRichard Henderson }
288898cd9ca7SRichard Henderson 
2889869051eaSRichard Henderson static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn,
28900b1347d2SRichard Henderson                                     const DisasInsn *di)
28910b1347d2SRichard Henderson {
28920b1347d2SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
28930b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
28940b1347d2SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
28950b1347d2SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
2896eaa3783bSRichard Henderson     TCGv_reg dest;
28970b1347d2SRichard Henderson 
28980b1347d2SRichard Henderson     if (c) {
28990b1347d2SRichard Henderson         nullify_over(ctx);
29000b1347d2SRichard Henderson     }
29010b1347d2SRichard Henderson 
29020b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
29030b1347d2SRichard Henderson     if (r1 == 0) {
2904eaa3783bSRichard Henderson         tcg_gen_ext32u_reg(dest, load_gpr(ctx, r2));
2905eaa3783bSRichard Henderson         tcg_gen_shr_reg(dest, dest, cpu_sar);
29060b1347d2SRichard Henderson     } else if (r1 == r2) {
29070b1347d2SRichard Henderson         TCGv_i32 t32 = tcg_temp_new_i32();
2908eaa3783bSRichard Henderson         tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, r2));
29090b1347d2SRichard Henderson         tcg_gen_rotr_i32(t32, t32, cpu_sar);
2910eaa3783bSRichard Henderson         tcg_gen_extu_i32_reg(dest, t32);
29110b1347d2SRichard Henderson         tcg_temp_free_i32(t32);
29120b1347d2SRichard Henderson     } else {
29130b1347d2SRichard Henderson         TCGv_i64 t = tcg_temp_new_i64();
29140b1347d2SRichard Henderson         TCGv_i64 s = tcg_temp_new_i64();
29150b1347d2SRichard Henderson 
2916eaa3783bSRichard Henderson         tcg_gen_concat_reg_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1));
2917eaa3783bSRichard Henderson         tcg_gen_extu_reg_i64(s, cpu_sar);
29180b1347d2SRichard Henderson         tcg_gen_shr_i64(t, t, s);
2919eaa3783bSRichard Henderson         tcg_gen_trunc_i64_reg(dest, t);
29200b1347d2SRichard Henderson 
29210b1347d2SRichard Henderson         tcg_temp_free_i64(t);
29220b1347d2SRichard Henderson         tcg_temp_free_i64(s);
29230b1347d2SRichard Henderson     }
29240b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
29250b1347d2SRichard Henderson 
29260b1347d2SRichard Henderson     /* Install the new nullification.  */
29270b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
29280b1347d2SRichard Henderson     if (c) {
29290b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
29300b1347d2SRichard Henderson     }
2931869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
29320b1347d2SRichard Henderson }
29330b1347d2SRichard Henderson 
2934869051eaSRichard Henderson static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn,
29350b1347d2SRichard Henderson                                      const DisasInsn *di)
29360b1347d2SRichard Henderson {
29370b1347d2SRichard Henderson     unsigned rt = extract32(insn, 0, 5);
29380b1347d2SRichard Henderson     unsigned cpos = extract32(insn, 5, 5);
29390b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
29400b1347d2SRichard Henderson     unsigned r1 = extract32(insn, 16, 5);
29410b1347d2SRichard Henderson     unsigned r2 = extract32(insn, 21, 5);
29420b1347d2SRichard Henderson     unsigned sa = 31 - cpos;
2943eaa3783bSRichard Henderson     TCGv_reg dest, t2;
29440b1347d2SRichard Henderson 
29450b1347d2SRichard Henderson     if (c) {
29460b1347d2SRichard Henderson         nullify_over(ctx);
29470b1347d2SRichard Henderson     }
29480b1347d2SRichard Henderson 
29490b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
29500b1347d2SRichard Henderson     t2 = load_gpr(ctx, r2);
29510b1347d2SRichard Henderson     if (r1 == r2) {
29520b1347d2SRichard Henderson         TCGv_i32 t32 = tcg_temp_new_i32();
2953eaa3783bSRichard Henderson         tcg_gen_trunc_reg_i32(t32, t2);
29540b1347d2SRichard Henderson         tcg_gen_rotri_i32(t32, t32, sa);
2955eaa3783bSRichard Henderson         tcg_gen_extu_i32_reg(dest, t32);
29560b1347d2SRichard Henderson         tcg_temp_free_i32(t32);
29570b1347d2SRichard Henderson     } else if (r1 == 0) {
2958eaa3783bSRichard Henderson         tcg_gen_extract_reg(dest, t2, sa, 32 - sa);
29590b1347d2SRichard Henderson     } else {
2960eaa3783bSRichard Henderson         TCGv_reg t0 = tcg_temp_new();
2961eaa3783bSRichard Henderson         tcg_gen_extract_reg(t0, t2, sa, 32 - sa);
2962eaa3783bSRichard Henderson         tcg_gen_deposit_reg(dest, t0, cpu_gr[r1], 32 - sa, sa);
29630b1347d2SRichard Henderson         tcg_temp_free(t0);
29640b1347d2SRichard Henderson     }
29650b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
29660b1347d2SRichard Henderson 
29670b1347d2SRichard Henderson     /* Install the new nullification.  */
29680b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
29690b1347d2SRichard Henderson     if (c) {
29700b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
29710b1347d2SRichard Henderson     }
2972869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
29730b1347d2SRichard Henderson }
29740b1347d2SRichard Henderson 
2975869051eaSRichard Henderson static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn,
29760b1347d2SRichard Henderson                                      const DisasInsn *di)
29770b1347d2SRichard Henderson {
29780b1347d2SRichard Henderson     unsigned clen = extract32(insn, 0, 5);
29790b1347d2SRichard Henderson     unsigned is_se = extract32(insn, 10, 1);
29800b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
29810b1347d2SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
29820b1347d2SRichard Henderson     unsigned rr = extract32(insn, 21, 5);
29830b1347d2SRichard Henderson     unsigned len = 32 - clen;
2984eaa3783bSRichard Henderson     TCGv_reg dest, src, tmp;
29850b1347d2SRichard Henderson 
29860b1347d2SRichard Henderson     if (c) {
29870b1347d2SRichard Henderson         nullify_over(ctx);
29880b1347d2SRichard Henderson     }
29890b1347d2SRichard Henderson 
29900b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
29910b1347d2SRichard Henderson     src = load_gpr(ctx, rr);
29920b1347d2SRichard Henderson     tmp = tcg_temp_new();
29930b1347d2SRichard Henderson 
29940b1347d2SRichard Henderson     /* Recall that SAR is using big-endian bit numbering.  */
2995eaa3783bSRichard Henderson     tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1);
29960b1347d2SRichard Henderson     if (is_se) {
2997eaa3783bSRichard Henderson         tcg_gen_sar_reg(dest, src, tmp);
2998eaa3783bSRichard Henderson         tcg_gen_sextract_reg(dest, dest, 0, len);
29990b1347d2SRichard Henderson     } else {
3000eaa3783bSRichard Henderson         tcg_gen_shr_reg(dest, src, tmp);
3001eaa3783bSRichard Henderson         tcg_gen_extract_reg(dest, dest, 0, len);
30020b1347d2SRichard Henderson     }
30030b1347d2SRichard Henderson     tcg_temp_free(tmp);
30040b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
30050b1347d2SRichard Henderson 
30060b1347d2SRichard Henderson     /* Install the new nullification.  */
30070b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
30080b1347d2SRichard Henderson     if (c) {
30090b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
30100b1347d2SRichard Henderson     }
3011869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
30120b1347d2SRichard Henderson }
30130b1347d2SRichard Henderson 
3014869051eaSRichard Henderson static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn,
30150b1347d2SRichard Henderson                                      const DisasInsn *di)
30160b1347d2SRichard Henderson {
30170b1347d2SRichard Henderson     unsigned clen = extract32(insn, 0, 5);
30180b1347d2SRichard Henderson     unsigned pos = extract32(insn, 5, 5);
30190b1347d2SRichard Henderson     unsigned is_se = extract32(insn, 10, 1);
30200b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
30210b1347d2SRichard Henderson     unsigned rt = extract32(insn, 16, 5);
30220b1347d2SRichard Henderson     unsigned rr = extract32(insn, 21, 5);
30230b1347d2SRichard Henderson     unsigned len = 32 - clen;
30240b1347d2SRichard Henderson     unsigned cpos = 31 - pos;
3025eaa3783bSRichard Henderson     TCGv_reg dest, src;
30260b1347d2SRichard Henderson 
30270b1347d2SRichard Henderson     if (c) {
30280b1347d2SRichard Henderson         nullify_over(ctx);
30290b1347d2SRichard Henderson     }
30300b1347d2SRichard Henderson 
30310b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
30320b1347d2SRichard Henderson     src = load_gpr(ctx, rr);
30330b1347d2SRichard Henderson     if (is_se) {
3034eaa3783bSRichard Henderson         tcg_gen_sextract_reg(dest, src, cpos, len);
30350b1347d2SRichard Henderson     } else {
3036eaa3783bSRichard Henderson         tcg_gen_extract_reg(dest, src, cpos, len);
30370b1347d2SRichard Henderson     }
30380b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
30390b1347d2SRichard Henderson 
30400b1347d2SRichard Henderson     /* Install the new nullification.  */
30410b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
30420b1347d2SRichard Henderson     if (c) {
30430b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
30440b1347d2SRichard Henderson     }
3045869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
30460b1347d2SRichard Henderson }
30470b1347d2SRichard Henderson 
30480b1347d2SRichard Henderson static const DisasInsn table_sh_ex[] = {
30490b1347d2SRichard Henderson     { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar },
30500b1347d2SRichard Henderson     { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm },
30510b1347d2SRichard Henderson     { 0xd0001000u, 0xfc001be0u, trans_extrw_sar },
30520b1347d2SRichard Henderson     { 0xd0001800u, 0xfc001800u, trans_extrw_imm },
30530b1347d2SRichard Henderson };
30540b1347d2SRichard Henderson 
3055869051eaSRichard Henderson static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn,
30560b1347d2SRichard Henderson                                       const DisasInsn *di)
30570b1347d2SRichard Henderson {
30580b1347d2SRichard Henderson     unsigned clen = extract32(insn, 0, 5);
30590b1347d2SRichard Henderson     unsigned cpos = extract32(insn, 5, 5);
30600b1347d2SRichard Henderson     unsigned nz = extract32(insn, 10, 1);
30610b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
3062eaa3783bSRichard Henderson     target_sreg val = low_sextract(insn, 16, 5);
30630b1347d2SRichard Henderson     unsigned rt = extract32(insn, 21, 5);
30640b1347d2SRichard Henderson     unsigned len = 32 - clen;
3065eaa3783bSRichard Henderson     target_sreg mask0, mask1;
3066eaa3783bSRichard Henderson     TCGv_reg dest;
30670b1347d2SRichard Henderson 
30680b1347d2SRichard Henderson     if (c) {
30690b1347d2SRichard Henderson         nullify_over(ctx);
30700b1347d2SRichard Henderson     }
30710b1347d2SRichard Henderson     if (cpos + len > 32) {
30720b1347d2SRichard Henderson         len = 32 - cpos;
30730b1347d2SRichard Henderson     }
30740b1347d2SRichard Henderson 
30750b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
30760b1347d2SRichard Henderson     mask0 = deposit64(0, cpos, len, val);
30770b1347d2SRichard Henderson     mask1 = deposit64(-1, cpos, len, val);
30780b1347d2SRichard Henderson 
30790b1347d2SRichard Henderson     if (nz) {
3080eaa3783bSRichard Henderson         TCGv_reg src = load_gpr(ctx, rt);
30810b1347d2SRichard Henderson         if (mask1 != -1) {
3082eaa3783bSRichard Henderson             tcg_gen_andi_reg(dest, src, mask1);
30830b1347d2SRichard Henderson             src = dest;
30840b1347d2SRichard Henderson         }
3085eaa3783bSRichard Henderson         tcg_gen_ori_reg(dest, src, mask0);
30860b1347d2SRichard Henderson     } else {
3087eaa3783bSRichard Henderson         tcg_gen_movi_reg(dest, mask0);
30880b1347d2SRichard Henderson     }
30890b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
30900b1347d2SRichard Henderson 
30910b1347d2SRichard Henderson     /* Install the new nullification.  */
30920b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
30930b1347d2SRichard Henderson     if (c) {
30940b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
30950b1347d2SRichard Henderson     }
3096869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
30970b1347d2SRichard Henderson }
30980b1347d2SRichard Henderson 
3099869051eaSRichard Henderson static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn,
31000b1347d2SRichard Henderson                                     const DisasInsn *di)
31010b1347d2SRichard Henderson {
31020b1347d2SRichard Henderson     unsigned clen = extract32(insn, 0, 5);
31030b1347d2SRichard Henderson     unsigned cpos = extract32(insn, 5, 5);
31040b1347d2SRichard Henderson     unsigned nz = extract32(insn, 10, 1);
31050b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
31060b1347d2SRichard Henderson     unsigned rr = extract32(insn, 16, 5);
31070b1347d2SRichard Henderson     unsigned rt = extract32(insn, 21, 5);
31080b1347d2SRichard Henderson     unsigned rs = nz ? rt : 0;
31090b1347d2SRichard Henderson     unsigned len = 32 - clen;
3110eaa3783bSRichard Henderson     TCGv_reg dest, val;
31110b1347d2SRichard Henderson 
31120b1347d2SRichard Henderson     if (c) {
31130b1347d2SRichard Henderson         nullify_over(ctx);
31140b1347d2SRichard Henderson     }
31150b1347d2SRichard Henderson     if (cpos + len > 32) {
31160b1347d2SRichard Henderson         len = 32 - cpos;
31170b1347d2SRichard Henderson     }
31180b1347d2SRichard Henderson 
31190b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
31200b1347d2SRichard Henderson     val = load_gpr(ctx, rr);
31210b1347d2SRichard Henderson     if (rs == 0) {
3122eaa3783bSRichard Henderson         tcg_gen_deposit_z_reg(dest, val, cpos, len);
31230b1347d2SRichard Henderson     } else {
3124eaa3783bSRichard Henderson         tcg_gen_deposit_reg(dest, cpu_gr[rs], val, cpos, len);
31250b1347d2SRichard Henderson     }
31260b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
31270b1347d2SRichard Henderson 
31280b1347d2SRichard Henderson     /* Install the new nullification.  */
31290b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
31300b1347d2SRichard Henderson     if (c) {
31310b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
31320b1347d2SRichard Henderson     }
3133869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
31340b1347d2SRichard Henderson }
31350b1347d2SRichard Henderson 
3136869051eaSRichard Henderson static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn,
31370b1347d2SRichard Henderson                                     const DisasInsn *di)
31380b1347d2SRichard Henderson {
31390b1347d2SRichard Henderson     unsigned clen = extract32(insn, 0, 5);
31400b1347d2SRichard Henderson     unsigned nz = extract32(insn, 10, 1);
31410b1347d2SRichard Henderson     unsigned i = extract32(insn, 12, 1);
31420b1347d2SRichard Henderson     unsigned c = extract32(insn, 13, 3);
31430b1347d2SRichard Henderson     unsigned rt = extract32(insn, 21, 5);
31440b1347d2SRichard Henderson     unsigned rs = nz ? rt : 0;
31450b1347d2SRichard Henderson     unsigned len = 32 - clen;
3146eaa3783bSRichard Henderson     TCGv_reg val, mask, tmp, shift, dest;
31470b1347d2SRichard Henderson     unsigned msb = 1U << (len - 1);
31480b1347d2SRichard Henderson 
31490b1347d2SRichard Henderson     if (c) {
31500b1347d2SRichard Henderson         nullify_over(ctx);
31510b1347d2SRichard Henderson     }
31520b1347d2SRichard Henderson 
31530b1347d2SRichard Henderson     if (i) {
31540b1347d2SRichard Henderson         val = load_const(ctx, low_sextract(insn, 16, 5));
31550b1347d2SRichard Henderson     } else {
31560b1347d2SRichard Henderson         val = load_gpr(ctx, extract32(insn, 16, 5));
31570b1347d2SRichard Henderson     }
31580b1347d2SRichard Henderson     dest = dest_gpr(ctx, rt);
31590b1347d2SRichard Henderson     shift = tcg_temp_new();
31600b1347d2SRichard Henderson     tmp = tcg_temp_new();
31610b1347d2SRichard Henderson 
31620b1347d2SRichard Henderson     /* Convert big-endian bit numbering in SAR to left-shift.  */
3163eaa3783bSRichard Henderson     tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1);
31640b1347d2SRichard Henderson 
3165eaa3783bSRichard Henderson     mask = tcg_const_reg(msb + (msb - 1));
3166eaa3783bSRichard Henderson     tcg_gen_and_reg(tmp, val, mask);
31670b1347d2SRichard Henderson     if (rs) {
3168eaa3783bSRichard Henderson         tcg_gen_shl_reg(mask, mask, shift);
3169eaa3783bSRichard Henderson         tcg_gen_shl_reg(tmp, tmp, shift);
3170eaa3783bSRichard Henderson         tcg_gen_andc_reg(dest, cpu_gr[rs], mask);
3171eaa3783bSRichard Henderson         tcg_gen_or_reg(dest, dest, tmp);
31720b1347d2SRichard Henderson     } else {
3173eaa3783bSRichard Henderson         tcg_gen_shl_reg(dest, tmp, shift);
31740b1347d2SRichard Henderson     }
31750b1347d2SRichard Henderson     tcg_temp_free(shift);
31760b1347d2SRichard Henderson     tcg_temp_free(mask);
31770b1347d2SRichard Henderson     tcg_temp_free(tmp);
31780b1347d2SRichard Henderson     save_gpr(ctx, rt, dest);
31790b1347d2SRichard Henderson 
31800b1347d2SRichard Henderson     /* Install the new nullification.  */
31810b1347d2SRichard Henderson     cond_free(&ctx->null_cond);
31820b1347d2SRichard Henderson     if (c) {
31830b1347d2SRichard Henderson         ctx->null_cond = do_sed_cond(c, dest);
31840b1347d2SRichard Henderson     }
3185869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
31860b1347d2SRichard Henderson }
31870b1347d2SRichard Henderson 
31880b1347d2SRichard Henderson static const DisasInsn table_depw[] = {
31890b1347d2SRichard Henderson     { 0xd4000000u, 0xfc000be0u, trans_depw_sar },
31900b1347d2SRichard Henderson     { 0xd4000800u, 0xfc001800u, trans_depw_imm },
31910b1347d2SRichard Henderson     { 0xd4001800u, 0xfc001800u, trans_depw_imm_c },
31920b1347d2SRichard Henderson };
31930b1347d2SRichard Henderson 
3194869051eaSRichard Henderson static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l)
319598cd9ca7SRichard Henderson {
319698cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
319798cd9ca7SRichard Henderson     unsigned b = extract32(insn, 21, 5);
3198eaa3783bSRichard Henderson     target_sreg disp = assemble_17(insn);
319998cd9ca7SRichard Henderson 
320098cd9ca7SRichard Henderson     /* unsigned s = low_uextract(insn, 13, 3); */
320198cd9ca7SRichard Henderson     /* ??? It seems like there should be a good way of using
320298cd9ca7SRichard Henderson        "be disp(sr2, r0)", the canonical gateway entry mechanism
320398cd9ca7SRichard Henderson        to our advantage.  But that appears to be inconvenient to
320498cd9ca7SRichard Henderson        manage along side branch delay slots.  Therefore we handle
320598cd9ca7SRichard Henderson        entry into the gateway page via absolute address.  */
320698cd9ca7SRichard Henderson 
320798cd9ca7SRichard Henderson     /* Since we don't implement spaces, just branch.  Do notice the special
320898cd9ca7SRichard Henderson        case of "be disp(*,r0)" using a direct branch to disp, so that we can
320998cd9ca7SRichard Henderson        goto_tb to the TB containing the syscall.  */
321098cd9ca7SRichard Henderson     if (b == 0) {
321198cd9ca7SRichard Henderson         return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
321298cd9ca7SRichard Henderson     } else {
3213eaa3783bSRichard Henderson         TCGv_reg tmp = get_temp(ctx);
3214eaa3783bSRichard Henderson         tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp);
321598cd9ca7SRichard Henderson         return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
321698cd9ca7SRichard Henderson     }
321798cd9ca7SRichard Henderson }
321898cd9ca7SRichard Henderson 
3219869051eaSRichard Henderson static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
322098cd9ca7SRichard Henderson                               const DisasInsn *di)
322198cd9ca7SRichard Henderson {
322298cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
322398cd9ca7SRichard Henderson     unsigned link = extract32(insn, 21, 5);
3224eaa3783bSRichard Henderson     target_sreg disp = assemble_17(insn);
322598cd9ca7SRichard Henderson 
322698cd9ca7SRichard Henderson     return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
322798cd9ca7SRichard Henderson }
322898cd9ca7SRichard Henderson 
3229869051eaSRichard Henderson static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
323098cd9ca7SRichard Henderson                                    const DisasInsn *di)
323198cd9ca7SRichard Henderson {
323298cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
3233eaa3783bSRichard Henderson     target_sreg disp = assemble_22(insn);
323498cd9ca7SRichard Henderson 
323598cd9ca7SRichard Henderson     return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n);
323698cd9ca7SRichard Henderson }
323798cd9ca7SRichard Henderson 
3238869051eaSRichard Henderson static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn,
323998cd9ca7SRichard Henderson                                const DisasInsn *di)
324098cd9ca7SRichard Henderson {
324198cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
324298cd9ca7SRichard Henderson     unsigned rx = extract32(insn, 16, 5);
324398cd9ca7SRichard Henderson     unsigned link = extract32(insn, 21, 5);
3244eaa3783bSRichard Henderson     TCGv_reg tmp = get_temp(ctx);
324598cd9ca7SRichard Henderson 
3246eaa3783bSRichard Henderson     tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3);
3247eaa3783bSRichard Henderson     tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
324898cd9ca7SRichard Henderson     return do_ibranch(ctx, tmp, link, n);
324998cd9ca7SRichard Henderson }
325098cd9ca7SRichard Henderson 
3251869051eaSRichard Henderson static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn,
325298cd9ca7SRichard Henderson                               const DisasInsn *di)
325398cd9ca7SRichard Henderson {
325498cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
325598cd9ca7SRichard Henderson     unsigned rx = extract32(insn, 16, 5);
325698cd9ca7SRichard Henderson     unsigned rb = extract32(insn, 21, 5);
3257eaa3783bSRichard Henderson     TCGv_reg dest;
325898cd9ca7SRichard Henderson 
325998cd9ca7SRichard Henderson     if (rx == 0) {
326098cd9ca7SRichard Henderson         dest = load_gpr(ctx, rb);
326198cd9ca7SRichard Henderson     } else {
326298cd9ca7SRichard Henderson         dest = get_temp(ctx);
3263eaa3783bSRichard Henderson         tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3);
3264eaa3783bSRichard Henderson         tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb));
326598cd9ca7SRichard Henderson     }
326698cd9ca7SRichard Henderson     return do_ibranch(ctx, dest, 0, n);
326798cd9ca7SRichard Henderson }
326898cd9ca7SRichard Henderson 
3269869051eaSRichard Henderson static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn,
327098cd9ca7SRichard Henderson                                const DisasInsn *di)
327198cd9ca7SRichard Henderson {
327298cd9ca7SRichard Henderson     unsigned n = extract32(insn, 1, 1);
327398cd9ca7SRichard Henderson     unsigned rb = extract32(insn, 21, 5);
327498cd9ca7SRichard Henderson     unsigned link = extract32(insn, 13, 1) ? 2 : 0;
327598cd9ca7SRichard Henderson 
327698cd9ca7SRichard Henderson     return do_ibranch(ctx, load_gpr(ctx, rb), link, n);
327798cd9ca7SRichard Henderson }
327898cd9ca7SRichard Henderson 
327998cd9ca7SRichard Henderson static const DisasInsn table_branch[] = {
328098cd9ca7SRichard Henderson     { 0xe8000000u, 0xfc006000u, trans_bl }, /* B,L and B,L,PUSH */
328198cd9ca7SRichard Henderson     { 0xe800a000u, 0xfc00e000u, trans_bl_long },
328298cd9ca7SRichard Henderson     { 0xe8004000u, 0xfc00fffdu, trans_blr },
328398cd9ca7SRichard Henderson     { 0xe800c000u, 0xfc00fffdu, trans_bv },
328498cd9ca7SRichard Henderson     { 0xe800d000u, 0xfc00dffcu, trans_bve },
328598cd9ca7SRichard Henderson };
328698cd9ca7SRichard Henderson 
3287869051eaSRichard Henderson static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
3288ebe9383cSRichard Henderson                                       const DisasInsn *di)
3289ebe9383cSRichard Henderson {
3290ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3291ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3292eff235ebSPaolo Bonzini     return do_fop_wew(ctx, rt, ra, di->f.wew);
3293ebe9383cSRichard Henderson }
3294ebe9383cSRichard Henderson 
3295869051eaSRichard Henderson static DisasJumpType trans_fop_wew_0e(DisasContext *ctx, uint32_t insn,
3296ebe9383cSRichard Henderson                                       const DisasInsn *di)
3297ebe9383cSRichard Henderson {
3298ebe9383cSRichard Henderson     unsigned rt = assemble_rt64(insn);
3299ebe9383cSRichard Henderson     unsigned ra = assemble_ra64(insn);
3300eff235ebSPaolo Bonzini     return do_fop_wew(ctx, rt, ra, di->f.wew);
3301ebe9383cSRichard Henderson }
3302ebe9383cSRichard Henderson 
3303869051eaSRichard Henderson static DisasJumpType trans_fop_ded(DisasContext *ctx, uint32_t insn,
3304ebe9383cSRichard Henderson                                    const DisasInsn *di)
3305ebe9383cSRichard Henderson {
3306ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3307ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3308eff235ebSPaolo Bonzini     return do_fop_ded(ctx, rt, ra, di->f.ded);
3309ebe9383cSRichard Henderson }
3310ebe9383cSRichard Henderson 
3311869051eaSRichard Henderson static DisasJumpType trans_fop_wed_0c(DisasContext *ctx, uint32_t insn,
3312ebe9383cSRichard Henderson                                       const DisasInsn *di)
3313ebe9383cSRichard Henderson {
3314ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3315ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3316eff235ebSPaolo Bonzini     return do_fop_wed(ctx, rt, ra, di->f.wed);
3317ebe9383cSRichard Henderson }
3318ebe9383cSRichard Henderson 
3319869051eaSRichard Henderson static DisasJumpType trans_fop_wed_0e(DisasContext *ctx, uint32_t insn,
3320ebe9383cSRichard Henderson                                       const DisasInsn *di)
3321ebe9383cSRichard Henderson {
3322ebe9383cSRichard Henderson     unsigned rt = assemble_rt64(insn);
3323ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3324eff235ebSPaolo Bonzini     return do_fop_wed(ctx, rt, ra, di->f.wed);
3325ebe9383cSRichard Henderson }
3326ebe9383cSRichard Henderson 
3327869051eaSRichard Henderson static DisasJumpType trans_fop_dew_0c(DisasContext *ctx, uint32_t insn,
3328ebe9383cSRichard Henderson                                       const DisasInsn *di)
3329ebe9383cSRichard Henderson {
3330ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3331ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3332eff235ebSPaolo Bonzini     return do_fop_dew(ctx, rt, ra, di->f.dew);
3333ebe9383cSRichard Henderson }
3334ebe9383cSRichard Henderson 
3335869051eaSRichard Henderson static DisasJumpType trans_fop_dew_0e(DisasContext *ctx, uint32_t insn,
3336ebe9383cSRichard Henderson                                       const DisasInsn *di)
3337ebe9383cSRichard Henderson {
3338ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3339ebe9383cSRichard Henderson     unsigned ra = assemble_ra64(insn);
3340eff235ebSPaolo Bonzini     return do_fop_dew(ctx, rt, ra, di->f.dew);
3341ebe9383cSRichard Henderson }
3342ebe9383cSRichard Henderson 
3343869051eaSRichard Henderson static DisasJumpType trans_fop_weww_0c(DisasContext *ctx, uint32_t insn,
3344ebe9383cSRichard Henderson                                        const DisasInsn *di)
3345ebe9383cSRichard Henderson {
3346ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3347ebe9383cSRichard Henderson     unsigned rb = extract32(insn, 16, 5);
3348ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3349eff235ebSPaolo Bonzini     return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
3350ebe9383cSRichard Henderson }
3351ebe9383cSRichard Henderson 
3352869051eaSRichard Henderson static DisasJumpType trans_fop_weww_0e(DisasContext *ctx, uint32_t insn,
3353ebe9383cSRichard Henderson                                        const DisasInsn *di)
3354ebe9383cSRichard Henderson {
3355ebe9383cSRichard Henderson     unsigned rt = assemble_rt64(insn);
3356ebe9383cSRichard Henderson     unsigned rb = assemble_rb64(insn);
3357ebe9383cSRichard Henderson     unsigned ra = assemble_ra64(insn);
3358eff235ebSPaolo Bonzini     return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
3359ebe9383cSRichard Henderson }
3360ebe9383cSRichard Henderson 
3361869051eaSRichard Henderson static DisasJumpType trans_fop_dedd(DisasContext *ctx, uint32_t insn,
3362ebe9383cSRichard Henderson                                     const DisasInsn *di)
3363ebe9383cSRichard Henderson {
3364ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3365ebe9383cSRichard Henderson     unsigned rb = extract32(insn, 16, 5);
3366ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3367eff235ebSPaolo Bonzini     return do_fop_dedd(ctx, rt, ra, rb, di->f.dedd);
3368ebe9383cSRichard Henderson }
3369ebe9383cSRichard Henderson 
3370ebe9383cSRichard Henderson static void gen_fcpy_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3371ebe9383cSRichard Henderson {
3372ebe9383cSRichard Henderson     tcg_gen_mov_i32(dst, src);
3373ebe9383cSRichard Henderson }
3374ebe9383cSRichard Henderson 
3375ebe9383cSRichard Henderson static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3376ebe9383cSRichard Henderson {
3377ebe9383cSRichard Henderson     tcg_gen_mov_i64(dst, src);
3378ebe9383cSRichard Henderson }
3379ebe9383cSRichard Henderson 
3380ebe9383cSRichard Henderson static void gen_fabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3381ebe9383cSRichard Henderson {
3382ebe9383cSRichard Henderson     tcg_gen_andi_i32(dst, src, INT32_MAX);
3383ebe9383cSRichard Henderson }
3384ebe9383cSRichard Henderson 
3385ebe9383cSRichard Henderson static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3386ebe9383cSRichard Henderson {
3387ebe9383cSRichard Henderson     tcg_gen_andi_i64(dst, src, INT64_MAX);
3388ebe9383cSRichard Henderson }
3389ebe9383cSRichard Henderson 
3390ebe9383cSRichard Henderson static void gen_fneg_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3391ebe9383cSRichard Henderson {
3392ebe9383cSRichard Henderson     tcg_gen_xori_i32(dst, src, INT32_MIN);
3393ebe9383cSRichard Henderson }
3394ebe9383cSRichard Henderson 
3395ebe9383cSRichard Henderson static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3396ebe9383cSRichard Henderson {
3397ebe9383cSRichard Henderson     tcg_gen_xori_i64(dst, src, INT64_MIN);
3398ebe9383cSRichard Henderson }
3399ebe9383cSRichard Henderson 
3400ebe9383cSRichard Henderson static void gen_fnegabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3401ebe9383cSRichard Henderson {
3402ebe9383cSRichard Henderson     tcg_gen_ori_i32(dst, src, INT32_MIN);
3403ebe9383cSRichard Henderson }
3404ebe9383cSRichard Henderson 
3405ebe9383cSRichard Henderson static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3406ebe9383cSRichard Henderson {
3407ebe9383cSRichard Henderson     tcg_gen_ori_i64(dst, src, INT64_MIN);
3408ebe9383cSRichard Henderson }
3409ebe9383cSRichard Henderson 
3410869051eaSRichard Henderson static DisasJumpType do_fcmp_s(DisasContext *ctx, unsigned ra, unsigned rb,
3411ebe9383cSRichard Henderson                                unsigned y, unsigned c)
3412ebe9383cSRichard Henderson {
3413ebe9383cSRichard Henderson     TCGv_i32 ta, tb, tc, ty;
3414ebe9383cSRichard Henderson 
3415ebe9383cSRichard Henderson     nullify_over(ctx);
3416ebe9383cSRichard Henderson 
3417ebe9383cSRichard Henderson     ta = load_frw0_i32(ra);
3418ebe9383cSRichard Henderson     tb = load_frw0_i32(rb);
3419ebe9383cSRichard Henderson     ty = tcg_const_i32(y);
3420ebe9383cSRichard Henderson     tc = tcg_const_i32(c);
3421ebe9383cSRichard Henderson 
3422ebe9383cSRichard Henderson     gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
3423ebe9383cSRichard Henderson 
3424ebe9383cSRichard Henderson     tcg_temp_free_i32(ta);
3425ebe9383cSRichard Henderson     tcg_temp_free_i32(tb);
3426ebe9383cSRichard Henderson     tcg_temp_free_i32(ty);
3427ebe9383cSRichard Henderson     tcg_temp_free_i32(tc);
3428ebe9383cSRichard Henderson 
3429869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3430ebe9383cSRichard Henderson }
3431ebe9383cSRichard Henderson 
3432869051eaSRichard Henderson static DisasJumpType trans_fcmp_s_0c(DisasContext *ctx, uint32_t insn,
3433ebe9383cSRichard Henderson                                      const DisasInsn *di)
3434ebe9383cSRichard Henderson {
3435ebe9383cSRichard Henderson     unsigned c = extract32(insn, 0, 5);
3436ebe9383cSRichard Henderson     unsigned y = extract32(insn, 13, 3);
3437ebe9383cSRichard Henderson     unsigned rb = extract32(insn, 16, 5);
3438ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3439ebe9383cSRichard Henderson     return do_fcmp_s(ctx, ra, rb, y, c);
3440ebe9383cSRichard Henderson }
3441ebe9383cSRichard Henderson 
3442869051eaSRichard Henderson static DisasJumpType trans_fcmp_s_0e(DisasContext *ctx, uint32_t insn,
3443ebe9383cSRichard Henderson                                      const DisasInsn *di)
3444ebe9383cSRichard Henderson {
3445ebe9383cSRichard Henderson     unsigned c = extract32(insn, 0, 5);
3446ebe9383cSRichard Henderson     unsigned y = extract32(insn, 13, 3);
3447ebe9383cSRichard Henderson     unsigned rb = assemble_rb64(insn);
3448ebe9383cSRichard Henderson     unsigned ra = assemble_ra64(insn);
3449ebe9383cSRichard Henderson     return do_fcmp_s(ctx, ra, rb, y, c);
3450ebe9383cSRichard Henderson }
3451ebe9383cSRichard Henderson 
3452869051eaSRichard Henderson static DisasJumpType trans_fcmp_d(DisasContext *ctx, uint32_t insn,
3453ebe9383cSRichard Henderson                                   const DisasInsn *di)
3454ebe9383cSRichard Henderson {
3455ebe9383cSRichard Henderson     unsigned c = extract32(insn, 0, 5);
3456ebe9383cSRichard Henderson     unsigned y = extract32(insn, 13, 3);
3457ebe9383cSRichard Henderson     unsigned rb = extract32(insn, 16, 5);
3458ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 21, 5);
3459ebe9383cSRichard Henderson     TCGv_i64 ta, tb;
3460ebe9383cSRichard Henderson     TCGv_i32 tc, ty;
3461ebe9383cSRichard Henderson 
3462ebe9383cSRichard Henderson     nullify_over(ctx);
3463ebe9383cSRichard Henderson 
3464ebe9383cSRichard Henderson     ta = load_frd0(ra);
3465ebe9383cSRichard Henderson     tb = load_frd0(rb);
3466ebe9383cSRichard Henderson     ty = tcg_const_i32(y);
3467ebe9383cSRichard Henderson     tc = tcg_const_i32(c);
3468ebe9383cSRichard Henderson 
3469ebe9383cSRichard Henderson     gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
3470ebe9383cSRichard Henderson 
3471ebe9383cSRichard Henderson     tcg_temp_free_i64(ta);
3472ebe9383cSRichard Henderson     tcg_temp_free_i64(tb);
3473ebe9383cSRichard Henderson     tcg_temp_free_i32(ty);
3474ebe9383cSRichard Henderson     tcg_temp_free_i32(tc);
3475ebe9383cSRichard Henderson 
3476869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3477ebe9383cSRichard Henderson }
3478ebe9383cSRichard Henderson 
3479869051eaSRichard Henderson static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn,
3480ebe9383cSRichard Henderson                                    const DisasInsn *di)
3481ebe9383cSRichard Henderson {
3482ebe9383cSRichard Henderson     unsigned y = extract32(insn, 13, 3);
3483ebe9383cSRichard Henderson     unsigned cbit = (y ^ 1) - 1;
3484eaa3783bSRichard Henderson     TCGv_reg t;
3485ebe9383cSRichard Henderson 
3486ebe9383cSRichard Henderson     nullify_over(ctx);
3487ebe9383cSRichard Henderson 
3488ebe9383cSRichard Henderson     t = tcg_temp_new();
3489eaa3783bSRichard Henderson     tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3490eaa3783bSRichard Henderson     tcg_gen_extract_reg(t, t, 21 - cbit, 1);
3491ebe9383cSRichard Henderson     ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3492ebe9383cSRichard Henderson     tcg_temp_free(t);
3493ebe9383cSRichard Henderson 
3494869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3495ebe9383cSRichard Henderson }
3496ebe9383cSRichard Henderson 
3497869051eaSRichard Henderson static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn,
3498ebe9383cSRichard Henderson                                    const DisasInsn *di)
3499ebe9383cSRichard Henderson {
3500ebe9383cSRichard Henderson     unsigned c = extract32(insn, 0, 5);
3501ebe9383cSRichard Henderson     int mask;
3502ebe9383cSRichard Henderson     bool inv = false;
3503eaa3783bSRichard Henderson     TCGv_reg t;
3504ebe9383cSRichard Henderson 
3505ebe9383cSRichard Henderson     nullify_over(ctx);
3506ebe9383cSRichard Henderson 
3507ebe9383cSRichard Henderson     t = tcg_temp_new();
3508eaa3783bSRichard Henderson     tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3509ebe9383cSRichard Henderson 
3510ebe9383cSRichard Henderson     switch (c) {
3511ebe9383cSRichard Henderson     case 0: /* simple */
3512eaa3783bSRichard Henderson         tcg_gen_andi_reg(t, t, 0x4000000);
3513ebe9383cSRichard Henderson         ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3514ebe9383cSRichard Henderson         goto done;
3515ebe9383cSRichard Henderson     case 2: /* rej */
3516ebe9383cSRichard Henderson         inv = true;
3517ebe9383cSRichard Henderson         /* fallthru */
3518ebe9383cSRichard Henderson     case 1: /* acc */
3519ebe9383cSRichard Henderson         mask = 0x43ff800;
3520ebe9383cSRichard Henderson         break;
3521ebe9383cSRichard Henderson     case 6: /* rej8 */
3522ebe9383cSRichard Henderson         inv = true;
3523ebe9383cSRichard Henderson         /* fallthru */
3524ebe9383cSRichard Henderson     case 5: /* acc8 */
3525ebe9383cSRichard Henderson         mask = 0x43f8000;
3526ebe9383cSRichard Henderson         break;
3527ebe9383cSRichard Henderson     case 9: /* acc6 */
3528ebe9383cSRichard Henderson         mask = 0x43e0000;
3529ebe9383cSRichard Henderson         break;
3530ebe9383cSRichard Henderson     case 13: /* acc4 */
3531ebe9383cSRichard Henderson         mask = 0x4380000;
3532ebe9383cSRichard Henderson         break;
3533ebe9383cSRichard Henderson     case 17: /* acc2 */
3534ebe9383cSRichard Henderson         mask = 0x4200000;
3535ebe9383cSRichard Henderson         break;
3536ebe9383cSRichard Henderson     default:
3537ebe9383cSRichard Henderson         return gen_illegal(ctx);
3538ebe9383cSRichard Henderson     }
3539ebe9383cSRichard Henderson     if (inv) {
3540eaa3783bSRichard Henderson         TCGv_reg c = load_const(ctx, mask);
3541eaa3783bSRichard Henderson         tcg_gen_or_reg(t, t, c);
3542ebe9383cSRichard Henderson         ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
3543ebe9383cSRichard Henderson     } else {
3544eaa3783bSRichard Henderson         tcg_gen_andi_reg(t, t, mask);
3545ebe9383cSRichard Henderson         ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
3546ebe9383cSRichard Henderson     }
3547ebe9383cSRichard Henderson  done:
3548869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3549ebe9383cSRichard Henderson }
3550ebe9383cSRichard Henderson 
3551869051eaSRichard Henderson static DisasJumpType trans_xmpyu(DisasContext *ctx, uint32_t insn,
3552ebe9383cSRichard Henderson                                  const DisasInsn *di)
3553ebe9383cSRichard Henderson {
3554ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3555ebe9383cSRichard Henderson     unsigned rb = assemble_rb64(insn);
3556ebe9383cSRichard Henderson     unsigned ra = assemble_ra64(insn);
3557ebe9383cSRichard Henderson     TCGv_i64 a, b;
3558ebe9383cSRichard Henderson 
3559ebe9383cSRichard Henderson     nullify_over(ctx);
3560ebe9383cSRichard Henderson 
3561ebe9383cSRichard Henderson     a = load_frw0_i64(ra);
3562ebe9383cSRichard Henderson     b = load_frw0_i64(rb);
3563ebe9383cSRichard Henderson     tcg_gen_mul_i64(a, a, b);
3564ebe9383cSRichard Henderson     save_frd(rt, a);
3565ebe9383cSRichard Henderson     tcg_temp_free_i64(a);
3566ebe9383cSRichard Henderson     tcg_temp_free_i64(b);
3567ebe9383cSRichard Henderson 
3568869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3569ebe9383cSRichard Henderson }
3570ebe9383cSRichard Henderson 
3571eff235ebSPaolo Bonzini #define FOP_DED  trans_fop_ded, .f.ded
3572eff235ebSPaolo Bonzini #define FOP_DEDD trans_fop_dedd, .f.dedd
3573ebe9383cSRichard Henderson 
3574eff235ebSPaolo Bonzini #define FOP_WEW  trans_fop_wew_0c, .f.wew
3575eff235ebSPaolo Bonzini #define FOP_DEW  trans_fop_dew_0c, .f.dew
3576eff235ebSPaolo Bonzini #define FOP_WED  trans_fop_wed_0c, .f.wed
3577eff235ebSPaolo Bonzini #define FOP_WEWW trans_fop_weww_0c, .f.weww
3578ebe9383cSRichard Henderson 
3579ebe9383cSRichard Henderson static const DisasInsn table_float_0c[] = {
3580ebe9383cSRichard Henderson     /* floating point class zero */
3581ebe9383cSRichard Henderson     { 0x30004000, 0xfc1fffe0, FOP_WEW = gen_fcpy_s },
3582ebe9383cSRichard Henderson     { 0x30006000, 0xfc1fffe0, FOP_WEW = gen_fabs_s },
3583ebe9383cSRichard Henderson     { 0x30008000, 0xfc1fffe0, FOP_WEW = gen_helper_fsqrt_s },
3584ebe9383cSRichard Henderson     { 0x3000a000, 0xfc1fffe0, FOP_WEW = gen_helper_frnd_s },
3585ebe9383cSRichard Henderson     { 0x3000c000, 0xfc1fffe0, FOP_WEW = gen_fneg_s },
3586ebe9383cSRichard Henderson     { 0x3000e000, 0xfc1fffe0, FOP_WEW = gen_fnegabs_s },
3587ebe9383cSRichard Henderson 
3588ebe9383cSRichard Henderson     { 0x30004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
3589ebe9383cSRichard Henderson     { 0x30006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
3590ebe9383cSRichard Henderson     { 0x30008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
3591ebe9383cSRichard Henderson     { 0x3000a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
3592ebe9383cSRichard Henderson     { 0x3000c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
3593ebe9383cSRichard Henderson     { 0x3000e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
3594ebe9383cSRichard Henderson 
3595ebe9383cSRichard Henderson     /* floating point class three */
3596ebe9383cSRichard Henderson     { 0x30000600, 0xfc00ffe0, FOP_WEWW = gen_helper_fadd_s },
3597ebe9383cSRichard Henderson     { 0x30002600, 0xfc00ffe0, FOP_WEWW = gen_helper_fsub_s },
3598ebe9383cSRichard Henderson     { 0x30004600, 0xfc00ffe0, FOP_WEWW = gen_helper_fmpy_s },
3599ebe9383cSRichard Henderson     { 0x30006600, 0xfc00ffe0, FOP_WEWW = gen_helper_fdiv_s },
3600ebe9383cSRichard Henderson 
3601ebe9383cSRichard Henderson     { 0x30000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
3602ebe9383cSRichard Henderson     { 0x30002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
3603ebe9383cSRichard Henderson     { 0x30004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
3604ebe9383cSRichard Henderson     { 0x30006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
3605ebe9383cSRichard Henderson 
3606ebe9383cSRichard Henderson     /* floating point class one */
3607ebe9383cSRichard Henderson     /* float/float */
3608ebe9383cSRichard Henderson     { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s },
3609ebe9383cSRichard Henderson     { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d },
3610ebe9383cSRichard Henderson     /* int/float */
3611ebe9383cSRichard Henderson     { 0x30008200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_w_s },
3612ebe9383cSRichard Henderson     { 0x30008a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_dw_s },
3613ebe9383cSRichard Henderson     { 0x3000a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_w_d },
3614ebe9383cSRichard Henderson     { 0x3000aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
3615ebe9383cSRichard Henderson     /* float/int */
3616ebe9383cSRichard Henderson     { 0x30010200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_w },
3617ebe9383cSRichard Henderson     { 0x30010a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_w },
3618ebe9383cSRichard Henderson     { 0x30012200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_dw },
3619ebe9383cSRichard Henderson     { 0x30012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
3620ebe9383cSRichard Henderson     /* float/int truncate */
3621ebe9383cSRichard Henderson     { 0x30018200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_w },
3622ebe9383cSRichard Henderson     { 0x30018a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_w },
3623ebe9383cSRichard Henderson     { 0x3001a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_dw },
3624ebe9383cSRichard Henderson     { 0x3001aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
3625ebe9383cSRichard Henderson     /* uint/float */
3626ebe9383cSRichard Henderson     { 0x30028200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_uw_s },
3627ebe9383cSRichard Henderson     { 0x30028a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_udw_s },
3628ebe9383cSRichard Henderson     { 0x3002a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_uw_d },
3629ebe9383cSRichard Henderson     { 0x3002aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
3630ebe9383cSRichard Henderson     /* float/uint */
3631ebe9383cSRichard Henderson     { 0x30030200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_uw },
3632ebe9383cSRichard Henderson     { 0x30030a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_uw },
3633ebe9383cSRichard Henderson     { 0x30032200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_udw },
3634ebe9383cSRichard Henderson     { 0x30032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
3635ebe9383cSRichard Henderson     /* float/uint truncate */
3636ebe9383cSRichard Henderson     { 0x30038200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_uw },
3637ebe9383cSRichard Henderson     { 0x30038a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_uw },
3638ebe9383cSRichard Henderson     { 0x3003a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_udw },
3639ebe9383cSRichard Henderson     { 0x3003aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
3640ebe9383cSRichard Henderson 
3641ebe9383cSRichard Henderson     /* floating point class two */
3642ebe9383cSRichard Henderson     { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c },
3643ebe9383cSRichard Henderson     { 0x30000c00, 0xfc001fe0, trans_fcmp_d },
3644ebe9383cSRichard Henderson     { 0x30002420, 0xffffffe0, trans_ftest_q },
3645ebe9383cSRichard Henderson     { 0x30000420, 0xffff1fff, trans_ftest_t },
3646ebe9383cSRichard Henderson 
3647ebe9383cSRichard Henderson     /* FID.  Note that ra == rt == 0, which via fcpy puts 0 into fr0.
3648ebe9383cSRichard Henderson        This is machine/revision == 0, which is reserved for simulator.  */
3649ebe9383cSRichard Henderson     { 0x30000000, 0xffffffff, FOP_WEW = gen_fcpy_s },
3650ebe9383cSRichard Henderson };
3651ebe9383cSRichard Henderson 
3652ebe9383cSRichard Henderson #undef FOP_WEW
3653ebe9383cSRichard Henderson #undef FOP_DEW
3654ebe9383cSRichard Henderson #undef FOP_WED
3655ebe9383cSRichard Henderson #undef FOP_WEWW
3656eff235ebSPaolo Bonzini #define FOP_WEW  trans_fop_wew_0e, .f.wew
3657eff235ebSPaolo Bonzini #define FOP_DEW  trans_fop_dew_0e, .f.dew
3658eff235ebSPaolo Bonzini #define FOP_WED  trans_fop_wed_0e, .f.wed
3659eff235ebSPaolo Bonzini #define FOP_WEWW trans_fop_weww_0e, .f.weww
3660ebe9383cSRichard Henderson 
3661ebe9383cSRichard Henderson static const DisasInsn table_float_0e[] = {
3662ebe9383cSRichard Henderson     /* floating point class zero */
3663ebe9383cSRichard Henderson     { 0x38004000, 0xfc1fff20, FOP_WEW = gen_fcpy_s },
3664ebe9383cSRichard Henderson     { 0x38006000, 0xfc1fff20, FOP_WEW = gen_fabs_s },
3665ebe9383cSRichard Henderson     { 0x38008000, 0xfc1fff20, FOP_WEW = gen_helper_fsqrt_s },
3666ebe9383cSRichard Henderson     { 0x3800a000, 0xfc1fff20, FOP_WEW = gen_helper_frnd_s },
3667ebe9383cSRichard Henderson     { 0x3800c000, 0xfc1fff20, FOP_WEW = gen_fneg_s },
3668ebe9383cSRichard Henderson     { 0x3800e000, 0xfc1fff20, FOP_WEW = gen_fnegabs_s },
3669ebe9383cSRichard Henderson 
3670ebe9383cSRichard Henderson     { 0x38004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
3671ebe9383cSRichard Henderson     { 0x38006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
3672ebe9383cSRichard Henderson     { 0x38008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
3673ebe9383cSRichard Henderson     { 0x3800a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
3674ebe9383cSRichard Henderson     { 0x3800c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
3675ebe9383cSRichard Henderson     { 0x3800e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
3676ebe9383cSRichard Henderson 
3677ebe9383cSRichard Henderson     /* floating point class three */
3678ebe9383cSRichard Henderson     { 0x38000600, 0xfc00ef20, FOP_WEWW = gen_helper_fadd_s },
3679ebe9383cSRichard Henderson     { 0x38002600, 0xfc00ef20, FOP_WEWW = gen_helper_fsub_s },
3680ebe9383cSRichard Henderson     { 0x38004600, 0xfc00ef20, FOP_WEWW = gen_helper_fmpy_s },
3681ebe9383cSRichard Henderson     { 0x38006600, 0xfc00ef20, FOP_WEWW = gen_helper_fdiv_s },
3682ebe9383cSRichard Henderson 
3683ebe9383cSRichard Henderson     { 0x38000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
3684ebe9383cSRichard Henderson     { 0x38002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
3685ebe9383cSRichard Henderson     { 0x38004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
3686ebe9383cSRichard Henderson     { 0x38006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
3687ebe9383cSRichard Henderson 
3688ebe9383cSRichard Henderson     { 0x38004700, 0xfc00ef60, trans_xmpyu },
3689ebe9383cSRichard Henderson 
3690ebe9383cSRichard Henderson     /* floating point class one */
3691ebe9383cSRichard Henderson     /* float/float */
3692ebe9383cSRichard Henderson     { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
3693ebe9383cSRichard Henderson     { 0x38002200, 0xfc1fffc0, FOP_DEW = gen_helper_fcnv_s_d },
3694ebe9383cSRichard Henderson     /* int/float */
3695ebe9383cSRichard Henderson     { 0x38008200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_w_s },
3696ebe9383cSRichard Henderson     { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s },
3697ebe9383cSRichard Henderson     { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d },
3698ebe9383cSRichard Henderson     { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
3699ebe9383cSRichard Henderson     /* float/int */
3700ebe9383cSRichard Henderson     { 0x38010200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_w },
3701ebe9383cSRichard Henderson     { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w },
3702ebe9383cSRichard Henderson     { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw },
3703ebe9383cSRichard Henderson     { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
3704ebe9383cSRichard Henderson     /* float/int truncate */
3705ebe9383cSRichard Henderson     { 0x38018200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_w },
3706ebe9383cSRichard Henderson     { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w },
3707ebe9383cSRichard Henderson     { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw },
3708ebe9383cSRichard Henderson     { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
3709ebe9383cSRichard Henderson     /* uint/float */
3710ebe9383cSRichard Henderson     { 0x38028200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_uw_s },
3711ebe9383cSRichard Henderson     { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s },
3712ebe9383cSRichard Henderson     { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d },
3713ebe9383cSRichard Henderson     { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
3714ebe9383cSRichard Henderson     /* float/uint */
3715ebe9383cSRichard Henderson     { 0x38030200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_uw },
3716ebe9383cSRichard Henderson     { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw },
3717ebe9383cSRichard Henderson     { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw },
3718ebe9383cSRichard Henderson     { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
3719ebe9383cSRichard Henderson     /* float/uint truncate */
3720ebe9383cSRichard Henderson     { 0x38038200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_uw },
3721ebe9383cSRichard Henderson     { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw },
3722ebe9383cSRichard Henderson     { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw },
3723ebe9383cSRichard Henderson     { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
3724ebe9383cSRichard Henderson 
3725ebe9383cSRichard Henderson     /* floating point class two */
3726ebe9383cSRichard Henderson     { 0x38000400, 0xfc000f60, trans_fcmp_s_0e },
3727ebe9383cSRichard Henderson     { 0x38000c00, 0xfc001fe0, trans_fcmp_d },
3728ebe9383cSRichard Henderson };
3729ebe9383cSRichard Henderson 
3730ebe9383cSRichard Henderson #undef FOP_WEW
3731ebe9383cSRichard Henderson #undef FOP_DEW
3732ebe9383cSRichard Henderson #undef FOP_WED
3733ebe9383cSRichard Henderson #undef FOP_WEWW
3734ebe9383cSRichard Henderson #undef FOP_DED
3735ebe9383cSRichard Henderson #undef FOP_DEDD
3736ebe9383cSRichard Henderson 
3737ebe9383cSRichard Henderson /* Convert the fmpyadd single-precision register encodings to standard.  */
3738ebe9383cSRichard Henderson static inline int fmpyadd_s_reg(unsigned r)
3739ebe9383cSRichard Henderson {
3740ebe9383cSRichard Henderson     return (r & 16) * 2 + 16 + (r & 15);
3741ebe9383cSRichard Henderson }
3742ebe9383cSRichard Henderson 
3743869051eaSRichard Henderson static DisasJumpType trans_fmpyadd(DisasContext *ctx,
3744869051eaSRichard Henderson                                    uint32_t insn, bool is_sub)
3745ebe9383cSRichard Henderson {
3746ebe9383cSRichard Henderson     unsigned tm = extract32(insn, 0, 5);
3747ebe9383cSRichard Henderson     unsigned f = extract32(insn, 5, 1);
3748ebe9383cSRichard Henderson     unsigned ra = extract32(insn, 6, 5);
3749ebe9383cSRichard Henderson     unsigned ta = extract32(insn, 11, 5);
3750ebe9383cSRichard Henderson     unsigned rm2 = extract32(insn, 16, 5);
3751ebe9383cSRichard Henderson     unsigned rm1 = extract32(insn, 21, 5);
3752ebe9383cSRichard Henderson 
3753ebe9383cSRichard Henderson     nullify_over(ctx);
3754ebe9383cSRichard Henderson 
3755ebe9383cSRichard Henderson     /* Independent multiply & add/sub, with undefined behaviour
3756ebe9383cSRichard Henderson        if outputs overlap inputs.  */
3757ebe9383cSRichard Henderson     if (f == 0) {
3758ebe9383cSRichard Henderson         tm = fmpyadd_s_reg(tm);
3759ebe9383cSRichard Henderson         ra = fmpyadd_s_reg(ra);
3760ebe9383cSRichard Henderson         ta = fmpyadd_s_reg(ta);
3761ebe9383cSRichard Henderson         rm2 = fmpyadd_s_reg(rm2);
3762ebe9383cSRichard Henderson         rm1 = fmpyadd_s_reg(rm1);
3763ebe9383cSRichard Henderson         do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
3764ebe9383cSRichard Henderson         do_fop_weww(ctx, ta, ta, ra,
3765ebe9383cSRichard Henderson                     is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
3766ebe9383cSRichard Henderson     } else {
3767ebe9383cSRichard Henderson         do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d);
3768ebe9383cSRichard Henderson         do_fop_dedd(ctx, ta, ta, ra,
3769ebe9383cSRichard Henderson                     is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
3770ebe9383cSRichard Henderson     }
3771ebe9383cSRichard Henderson 
3772869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3773ebe9383cSRichard Henderson }
3774ebe9383cSRichard Henderson 
3775869051eaSRichard Henderson static DisasJumpType trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn,
3776ebe9383cSRichard Henderson                                       const DisasInsn *di)
3777ebe9383cSRichard Henderson {
3778ebe9383cSRichard Henderson     unsigned rt = assemble_rt64(insn);
3779ebe9383cSRichard Henderson     unsigned neg = extract32(insn, 5, 1);
3780ebe9383cSRichard Henderson     unsigned rm1 = assemble_ra64(insn);
3781ebe9383cSRichard Henderson     unsigned rm2 = assemble_rb64(insn);
3782ebe9383cSRichard Henderson     unsigned ra3 = assemble_rc64(insn);
3783ebe9383cSRichard Henderson     TCGv_i32 a, b, c;
3784ebe9383cSRichard Henderson 
3785ebe9383cSRichard Henderson     nullify_over(ctx);
3786ebe9383cSRichard Henderson     a = load_frw0_i32(rm1);
3787ebe9383cSRichard Henderson     b = load_frw0_i32(rm2);
3788ebe9383cSRichard Henderson     c = load_frw0_i32(ra3);
3789ebe9383cSRichard Henderson 
3790ebe9383cSRichard Henderson     if (neg) {
3791ebe9383cSRichard Henderson         gen_helper_fmpynfadd_s(a, cpu_env, a, b, c);
3792ebe9383cSRichard Henderson     } else {
3793ebe9383cSRichard Henderson         gen_helper_fmpyfadd_s(a, cpu_env, a, b, c);
3794ebe9383cSRichard Henderson     }
3795ebe9383cSRichard Henderson 
3796ebe9383cSRichard Henderson     tcg_temp_free_i32(b);
3797ebe9383cSRichard Henderson     tcg_temp_free_i32(c);
3798ebe9383cSRichard Henderson     save_frw_i32(rt, a);
3799ebe9383cSRichard Henderson     tcg_temp_free_i32(a);
3800869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3801ebe9383cSRichard Henderson }
3802ebe9383cSRichard Henderson 
3803869051eaSRichard Henderson static DisasJumpType trans_fmpyfadd_d(DisasContext *ctx, uint32_t insn,
3804ebe9383cSRichard Henderson                                       const DisasInsn *di)
3805ebe9383cSRichard Henderson {
3806ebe9383cSRichard Henderson     unsigned rt = extract32(insn, 0, 5);
3807ebe9383cSRichard Henderson     unsigned neg = extract32(insn, 5, 1);
3808ebe9383cSRichard Henderson     unsigned rm1 = extract32(insn, 21, 5);
3809ebe9383cSRichard Henderson     unsigned rm2 = extract32(insn, 16, 5);
3810ebe9383cSRichard Henderson     unsigned ra3 = assemble_rc64(insn);
3811ebe9383cSRichard Henderson     TCGv_i64 a, b, c;
3812ebe9383cSRichard Henderson 
3813ebe9383cSRichard Henderson     nullify_over(ctx);
3814ebe9383cSRichard Henderson     a = load_frd0(rm1);
3815ebe9383cSRichard Henderson     b = load_frd0(rm2);
3816ebe9383cSRichard Henderson     c = load_frd0(ra3);
3817ebe9383cSRichard Henderson 
3818ebe9383cSRichard Henderson     if (neg) {
3819ebe9383cSRichard Henderson         gen_helper_fmpynfadd_d(a, cpu_env, a, b, c);
3820ebe9383cSRichard Henderson     } else {
3821ebe9383cSRichard Henderson         gen_helper_fmpyfadd_d(a, cpu_env, a, b, c);
3822ebe9383cSRichard Henderson     }
3823ebe9383cSRichard Henderson 
3824ebe9383cSRichard Henderson     tcg_temp_free_i64(b);
3825ebe9383cSRichard Henderson     tcg_temp_free_i64(c);
3826ebe9383cSRichard Henderson     save_frd(rt, a);
3827ebe9383cSRichard Henderson     tcg_temp_free_i64(a);
3828869051eaSRichard Henderson     return nullify_end(ctx, DISAS_NEXT);
3829ebe9383cSRichard Henderson }
3830ebe9383cSRichard Henderson 
3831ebe9383cSRichard Henderson static const DisasInsn table_fp_fused[] = {
3832ebe9383cSRichard Henderson     { 0xb8000000u, 0xfc000800u, trans_fmpyfadd_s },
3833ebe9383cSRichard Henderson     { 0xb8000800u, 0xfc0019c0u, trans_fmpyfadd_d }
3834ebe9383cSRichard Henderson };
3835ebe9383cSRichard Henderson 
3836869051eaSRichard Henderson static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn,
383761766fe9SRichard Henderson                                          const DisasInsn table[], size_t n)
383861766fe9SRichard Henderson {
383961766fe9SRichard Henderson     size_t i;
384061766fe9SRichard Henderson     for (i = 0; i < n; ++i) {
384161766fe9SRichard Henderson         if ((insn & table[i].mask) == table[i].insn) {
384261766fe9SRichard Henderson             return table[i].trans(ctx, insn, &table[i]);
384361766fe9SRichard Henderson         }
384461766fe9SRichard Henderson     }
384561766fe9SRichard Henderson     return gen_illegal(ctx);
384661766fe9SRichard Henderson }
384761766fe9SRichard Henderson 
384861766fe9SRichard Henderson #define translate_table(ctx, insn, table) \
384961766fe9SRichard Henderson     translate_table_int(ctx, insn, table, ARRAY_SIZE(table))
385061766fe9SRichard Henderson 
3851869051eaSRichard Henderson static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
385261766fe9SRichard Henderson {
385361766fe9SRichard Henderson     uint32_t opc = extract32(insn, 26, 6);
385461766fe9SRichard Henderson 
385561766fe9SRichard Henderson     switch (opc) {
385698a9cb79SRichard Henderson     case 0x00: /* system op */
385798a9cb79SRichard Henderson         return translate_table(ctx, insn, table_system);
385898a9cb79SRichard Henderson     case 0x01:
385998a9cb79SRichard Henderson         return translate_table(ctx, insn, table_mem_mgmt);
3860b2167459SRichard Henderson     case 0x02:
3861b2167459SRichard Henderson         return translate_table(ctx, insn, table_arith_log);
386296d6407fSRichard Henderson     case 0x03:
386396d6407fSRichard Henderson         return translate_table(ctx, insn, table_index_mem);
3864ebe9383cSRichard Henderson     case 0x06:
3865ebe9383cSRichard Henderson         return trans_fmpyadd(ctx, insn, false);
3866b2167459SRichard Henderson     case 0x08:
3867b2167459SRichard Henderson         return trans_ldil(ctx, insn);
386896d6407fSRichard Henderson     case 0x09:
386996d6407fSRichard Henderson         return trans_copr_w(ctx, insn);
3870b2167459SRichard Henderson     case 0x0A:
3871b2167459SRichard Henderson         return trans_addil(ctx, insn);
387296d6407fSRichard Henderson     case 0x0B:
387396d6407fSRichard Henderson         return trans_copr_dw(ctx, insn);
3874ebe9383cSRichard Henderson     case 0x0C:
3875ebe9383cSRichard Henderson         return translate_table(ctx, insn, table_float_0c);
3876b2167459SRichard Henderson     case 0x0D:
3877b2167459SRichard Henderson         return trans_ldo(ctx, insn);
3878ebe9383cSRichard Henderson     case 0x0E:
3879ebe9383cSRichard Henderson         return translate_table(ctx, insn, table_float_0e);
388096d6407fSRichard Henderson 
388196d6407fSRichard Henderson     case 0x10:
388296d6407fSRichard Henderson         return trans_load(ctx, insn, false, MO_UB);
388396d6407fSRichard Henderson     case 0x11:
388496d6407fSRichard Henderson         return trans_load(ctx, insn, false, MO_TEUW);
388596d6407fSRichard Henderson     case 0x12:
388696d6407fSRichard Henderson         return trans_load(ctx, insn, false, MO_TEUL);
388796d6407fSRichard Henderson     case 0x13:
388896d6407fSRichard Henderson         return trans_load(ctx, insn, true, MO_TEUL);
388996d6407fSRichard Henderson     case 0x16:
389096d6407fSRichard Henderson         return trans_fload_mod(ctx, insn);
389196d6407fSRichard Henderson     case 0x17:
389296d6407fSRichard Henderson         return trans_load_w(ctx, insn);
389396d6407fSRichard Henderson     case 0x18:
389496d6407fSRichard Henderson         return trans_store(ctx, insn, false, MO_UB);
389596d6407fSRichard Henderson     case 0x19:
389696d6407fSRichard Henderson         return trans_store(ctx, insn, false, MO_TEUW);
389796d6407fSRichard Henderson     case 0x1A:
389896d6407fSRichard Henderson         return trans_store(ctx, insn, false, MO_TEUL);
389996d6407fSRichard Henderson     case 0x1B:
390096d6407fSRichard Henderson         return trans_store(ctx, insn, true, MO_TEUL);
390196d6407fSRichard Henderson     case 0x1E:
390296d6407fSRichard Henderson         return trans_fstore_mod(ctx, insn);
390396d6407fSRichard Henderson     case 0x1F:
390496d6407fSRichard Henderson         return trans_store_w(ctx, insn);
390596d6407fSRichard Henderson 
390698cd9ca7SRichard Henderson     case 0x20:
390798cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, true, false, false);
390898cd9ca7SRichard Henderson     case 0x21:
390998cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, true, true, false);
391098cd9ca7SRichard Henderson     case 0x22:
391198cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, false, false, false);
391298cd9ca7SRichard Henderson     case 0x23:
391398cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, false, true, false);
3914b2167459SRichard Henderson     case 0x24:
3915b2167459SRichard Henderson         return trans_cmpiclr(ctx, insn);
3916b2167459SRichard Henderson     case 0x25:
3917b2167459SRichard Henderson         return trans_subi(ctx, insn);
3918ebe9383cSRichard Henderson     case 0x26:
3919ebe9383cSRichard Henderson         return trans_fmpyadd(ctx, insn, true);
392098cd9ca7SRichard Henderson     case 0x27:
392198cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, true, false, true);
392298cd9ca7SRichard Henderson     case 0x28:
392398cd9ca7SRichard Henderson         return trans_addb(ctx, insn, true, false);
392498cd9ca7SRichard Henderson     case 0x29:
392598cd9ca7SRichard Henderson         return trans_addb(ctx, insn, true, true);
392698cd9ca7SRichard Henderson     case 0x2A:
392798cd9ca7SRichard Henderson         return trans_addb(ctx, insn, false, false);
392898cd9ca7SRichard Henderson     case 0x2B:
392998cd9ca7SRichard Henderson         return trans_addb(ctx, insn, false, true);
3930b2167459SRichard Henderson     case 0x2C:
3931b2167459SRichard Henderson     case 0x2D:
3932b2167459SRichard Henderson         return trans_addi(ctx, insn);
3933ebe9383cSRichard Henderson     case 0x2E:
3934ebe9383cSRichard Henderson         return translate_table(ctx, insn, table_fp_fused);
393598cd9ca7SRichard Henderson     case 0x2F:
393698cd9ca7SRichard Henderson         return trans_cmpb(ctx, insn, false, false, true);
393796d6407fSRichard Henderson 
393898cd9ca7SRichard Henderson     case 0x30:
393998cd9ca7SRichard Henderson     case 0x31:
394098cd9ca7SRichard Henderson         return trans_bb(ctx, insn);
394198cd9ca7SRichard Henderson     case 0x32:
394298cd9ca7SRichard Henderson         return trans_movb(ctx, insn, false);
394398cd9ca7SRichard Henderson     case 0x33:
394498cd9ca7SRichard Henderson         return trans_movb(ctx, insn, true);
39450b1347d2SRichard Henderson     case 0x34:
39460b1347d2SRichard Henderson         return translate_table(ctx, insn, table_sh_ex);
39470b1347d2SRichard Henderson     case 0x35:
39480b1347d2SRichard Henderson         return translate_table(ctx, insn, table_depw);
394998cd9ca7SRichard Henderson     case 0x38:
395098cd9ca7SRichard Henderson         return trans_be(ctx, insn, false);
395198cd9ca7SRichard Henderson     case 0x39:
395298cd9ca7SRichard Henderson         return trans_be(ctx, insn, true);
395398cd9ca7SRichard Henderson     case 0x3A:
395498cd9ca7SRichard Henderson         return translate_table(ctx, insn, table_branch);
395596d6407fSRichard Henderson 
395696d6407fSRichard Henderson     case 0x04: /* spopn */
395796d6407fSRichard Henderson     case 0x05: /* diag */
395896d6407fSRichard Henderson     case 0x0F: /* product specific */
395996d6407fSRichard Henderson         break;
396096d6407fSRichard Henderson 
396196d6407fSRichard Henderson     case 0x07: /* unassigned */
396296d6407fSRichard Henderson     case 0x15: /* unassigned */
396396d6407fSRichard Henderson     case 0x1D: /* unassigned */
396496d6407fSRichard Henderson     case 0x37: /* unassigned */
396596d6407fSRichard Henderson     case 0x3F: /* unassigned */
396661766fe9SRichard Henderson     default:
396761766fe9SRichard Henderson         break;
396861766fe9SRichard Henderson     }
396961766fe9SRichard Henderson     return gen_illegal(ctx);
397061766fe9SRichard Henderson }
397161766fe9SRichard Henderson 
397251b061fbSRichard Henderson static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
397351b061fbSRichard Henderson                                       CPUState *cs, int max_insns)
397461766fe9SRichard Henderson {
397551b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3976f764718dSRichard Henderson     int bound;
397761766fe9SRichard Henderson 
397851b061fbSRichard Henderson     ctx->cs = cs;
3979*3d68ee7bSRichard Henderson 
3980*3d68ee7bSRichard Henderson #ifdef CONFIG_USER_ONLY
3981*3d68ee7bSRichard Henderson     ctx->privilege = MMU_USER_IDX;
3982*3d68ee7bSRichard Henderson     ctx->mmu_idx = MMU_USER_IDX;
3983*3d68ee7bSRichard Henderson #else
3984*3d68ee7bSRichard Henderson     ctx->privilege = ctx->base.pc_first & 3;
3985*3d68ee7bSRichard Henderson     ctx->mmu_idx = (ctx->base.tb->flags & PSW_D
3986*3d68ee7bSRichard Henderson                     ? ctx->privilege : MMU_PHYS_IDX);
3987*3d68ee7bSRichard Henderson #endif
3988*3d68ee7bSRichard Henderson     ctx->iaoq_f = ctx->base.pc_first;
3989*3d68ee7bSRichard Henderson     ctx->iaoq_b = ctx->base.tb->cs_base;
3990*3d68ee7bSRichard Henderson     ctx->base.pc_first &= -4;
3991*3d68ee7bSRichard Henderson 
399251b061fbSRichard Henderson     ctx->iaoq_n = -1;
3993f764718dSRichard Henderson     ctx->iaoq_n_var = NULL;
399461766fe9SRichard Henderson 
3995*3d68ee7bSRichard Henderson     /* Bound the number of instructions by those left on the page.  */
3996*3d68ee7bSRichard Henderson     bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
3997*3d68ee7bSRichard Henderson     bound = MIN(max_insns, bound);
3998*3d68ee7bSRichard Henderson 
399951b061fbSRichard Henderson     ctx->ntemps = 0;
4000f764718dSRichard Henderson     memset(ctx->temps, 0, sizeof(ctx->temps));
400161766fe9SRichard Henderson 
4002*3d68ee7bSRichard Henderson     return bound;
400361766fe9SRichard Henderson }
400461766fe9SRichard Henderson 
400551b061fbSRichard Henderson static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
400651b061fbSRichard Henderson {
400751b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
400861766fe9SRichard Henderson 
4009*3d68ee7bSRichard Henderson     /* Seed the nullification status from PSW[N], as saved in TB->FLAGS.  */
401051b061fbSRichard Henderson     ctx->null_cond = cond_make_f();
401151b061fbSRichard Henderson     ctx->psw_n_nonzero = false;
4012*3d68ee7bSRichard Henderson     if (ctx->base.tb->flags & PSW_N) {
401351b061fbSRichard Henderson         ctx->null_cond.c = TCG_COND_ALWAYS;
401451b061fbSRichard Henderson         ctx->psw_n_nonzero = true;
4015129e9cc3SRichard Henderson     }
401651b061fbSRichard Henderson     ctx->null_lab = NULL;
401761766fe9SRichard Henderson }
401861766fe9SRichard Henderson 
401951b061fbSRichard Henderson static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
402051b061fbSRichard Henderson {
402151b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
402251b061fbSRichard Henderson 
402351b061fbSRichard Henderson     tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
402451b061fbSRichard Henderson }
402551b061fbSRichard Henderson 
402651b061fbSRichard Henderson static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
402751b061fbSRichard Henderson                                       const CPUBreakpoint *bp)
402851b061fbSRichard Henderson {
402951b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
403051b061fbSRichard Henderson 
403151b061fbSRichard Henderson     ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG);
4032*3d68ee7bSRichard Henderson     ctx->base.pc_next = (ctx->iaoq_f & -4) + 4;
403351b061fbSRichard Henderson     return true;
403451b061fbSRichard Henderson }
403551b061fbSRichard Henderson 
403651b061fbSRichard Henderson static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
403751b061fbSRichard Henderson {
403851b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
403951b061fbSRichard Henderson     CPUHPPAState *env = cs->env_ptr;
404051b061fbSRichard Henderson     DisasJumpType ret;
404151b061fbSRichard Henderson     int i, n;
404251b061fbSRichard Henderson 
404351b061fbSRichard Henderson     /* Execute one insn.  */
4044ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY
404551b061fbSRichard Henderson     if (ctx->iaoq_f < TARGET_PAGE_SIZE) {
404651b061fbSRichard Henderson         ret = do_page_zero(ctx);
4047869051eaSRichard Henderson         assert(ret != DISAS_NEXT);
4048ba1d0b44SRichard Henderson     } else
4049ba1d0b44SRichard Henderson #endif
4050ba1d0b44SRichard Henderson     {
405161766fe9SRichard Henderson         /* Always fetch the insn, even if nullified, so that we check
405261766fe9SRichard Henderson            the page permissions for execute.  */
4053*3d68ee7bSRichard Henderson         uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f & -4);
405461766fe9SRichard Henderson 
405561766fe9SRichard Henderson         /* Set up the IA queue for the next insn.
405661766fe9SRichard Henderson            This will be overwritten by a branch.  */
405751b061fbSRichard Henderson         if (ctx->iaoq_b == -1) {
405851b061fbSRichard Henderson             ctx->iaoq_n = -1;
405951b061fbSRichard Henderson             ctx->iaoq_n_var = get_temp(ctx);
4060eaa3783bSRichard Henderson             tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
406161766fe9SRichard Henderson         } else {
406251b061fbSRichard Henderson             ctx->iaoq_n = ctx->iaoq_b + 4;
4063f764718dSRichard Henderson             ctx->iaoq_n_var = NULL;
406461766fe9SRichard Henderson         }
406561766fe9SRichard Henderson 
406651b061fbSRichard Henderson         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
406751b061fbSRichard Henderson             ctx->null_cond.c = TCG_COND_NEVER;
4068869051eaSRichard Henderson             ret = DISAS_NEXT;
4069129e9cc3SRichard Henderson         } else {
407051b061fbSRichard Henderson             ret = translate_one(ctx, insn);
407151b061fbSRichard Henderson             assert(ctx->null_lab == NULL);
4072129e9cc3SRichard Henderson         }
407361766fe9SRichard Henderson     }
407461766fe9SRichard Henderson 
407551b061fbSRichard Henderson     /* Free any temporaries allocated.  */
407651b061fbSRichard Henderson     for (i = 0, n = ctx->ntemps; i < n; ++i) {
407751b061fbSRichard Henderson         tcg_temp_free(ctx->temps[i]);
4078f764718dSRichard Henderson         ctx->temps[i] = NULL;
407961766fe9SRichard Henderson     }
408051b061fbSRichard Henderson     ctx->ntemps = 0;
408161766fe9SRichard Henderson 
4082*3d68ee7bSRichard Henderson     /* Advance the insn queue.  Note that this check also detects
4083*3d68ee7bSRichard Henderson        a priority change within the instruction queue.  */
408451b061fbSRichard Henderson     if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
408551b061fbSRichard Henderson         if (ctx->null_cond.c == TCG_COND_NEVER
408651b061fbSRichard Henderson             || ctx->null_cond.c == TCG_COND_ALWAYS) {
408751b061fbSRichard Henderson             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
408851b061fbSRichard Henderson             gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
4089869051eaSRichard Henderson             ret = DISAS_NORETURN;
4090129e9cc3SRichard Henderson         } else {
4091869051eaSRichard Henderson             ret = DISAS_IAQ_N_STALE;
409261766fe9SRichard Henderson        }
4093129e9cc3SRichard Henderson     }
409451b061fbSRichard Henderson     ctx->iaoq_f = ctx->iaoq_b;
409551b061fbSRichard Henderson     ctx->iaoq_b = ctx->iaoq_n;
409651b061fbSRichard Henderson     ctx->base.is_jmp = ret;
409761766fe9SRichard Henderson 
4098869051eaSRichard Henderson     if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) {
409951b061fbSRichard Henderson         return;
410061766fe9SRichard Henderson     }
410151b061fbSRichard Henderson     if (ctx->iaoq_f == -1) {
4102eaa3783bSRichard Henderson         tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
410351b061fbSRichard Henderson         copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
410451b061fbSRichard Henderson         nullify_save(ctx);
410551b061fbSRichard Henderson         ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
410651b061fbSRichard Henderson     } else if (ctx->iaoq_b == -1) {
4107eaa3783bSRichard Henderson         tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
410861766fe9SRichard Henderson     }
410961766fe9SRichard Henderson }
411061766fe9SRichard Henderson 
411151b061fbSRichard Henderson static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
411251b061fbSRichard Henderson {
411351b061fbSRichard Henderson     DisasContext *ctx = container_of(dcbase, DisasContext, base);
411451b061fbSRichard Henderson 
411551b061fbSRichard Henderson     switch (ctx->base.is_jmp) {
4116869051eaSRichard Henderson     case DISAS_NORETURN:
411761766fe9SRichard Henderson         break;
411851b061fbSRichard Henderson     case DISAS_TOO_MANY:
4119869051eaSRichard Henderson     case DISAS_IAQ_N_STALE:
412051b061fbSRichard Henderson         copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
412151b061fbSRichard Henderson         copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
412251b061fbSRichard Henderson         nullify_save(ctx);
412361766fe9SRichard Henderson         /* FALLTHRU */
4124869051eaSRichard Henderson     case DISAS_IAQ_N_UPDATED:
412551b061fbSRichard Henderson         if (ctx->base.singlestep_enabled) {
412661766fe9SRichard Henderson             gen_excp_1(EXCP_DEBUG);
412761766fe9SRichard Henderson         } else {
41287f11636dSEmilio G. Cota             tcg_gen_lookup_and_goto_ptr();
412961766fe9SRichard Henderson         }
413061766fe9SRichard Henderson         break;
413161766fe9SRichard Henderson     default:
413251b061fbSRichard Henderson         g_assert_not_reached();
413361766fe9SRichard Henderson     }
413461766fe9SRichard Henderson 
413551b061fbSRichard Henderson     /* We don't actually use this during normal translation,
413651b061fbSRichard Henderson        but we should interact with the generic main loop.  */
4137*3d68ee7bSRichard Henderson     ctx->base.pc_next = ctx->base.pc_first + 4 * ctx->base.num_insns;
413851b061fbSRichard Henderson }
413961766fe9SRichard Henderson 
414051b061fbSRichard Henderson static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
414151b061fbSRichard Henderson {
4142eaa3783bSRichard Henderson     target_ureg pc = dcbase->pc_first;
414361766fe9SRichard Henderson 
4144ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY
4145ba1d0b44SRichard Henderson     switch (pc) {
41467ad439dfSRichard Henderson     case 0x00:
414751b061fbSRichard Henderson         qemu_log("IN:\n0x00000000:  (null)\n");
4148ba1d0b44SRichard Henderson         return;
41497ad439dfSRichard Henderson     case 0xb0:
415051b061fbSRichard Henderson         qemu_log("IN:\n0x000000b0:  light-weight-syscall\n");
4151ba1d0b44SRichard Henderson         return;
41527ad439dfSRichard Henderson     case 0xe0:
415351b061fbSRichard Henderson         qemu_log("IN:\n0x000000e0:  set-thread-pointer-syscall\n");
4154ba1d0b44SRichard Henderson         return;
41557ad439dfSRichard Henderson     case 0x100:
415651b061fbSRichard Henderson         qemu_log("IN:\n0x00000100:  syscall\n");
4157ba1d0b44SRichard Henderson         return;
41587ad439dfSRichard Henderson     }
4159ba1d0b44SRichard Henderson #endif
4160ba1d0b44SRichard Henderson 
4161ba1d0b44SRichard Henderson     qemu_log("IN: %s\n", lookup_symbol(pc));
4162eaa3783bSRichard Henderson     log_target_disas(cs, pc, dcbase->tb->size);
416361766fe9SRichard Henderson }
416451b061fbSRichard Henderson 
416551b061fbSRichard Henderson static const TranslatorOps hppa_tr_ops = {
416651b061fbSRichard Henderson     .init_disas_context = hppa_tr_init_disas_context,
416751b061fbSRichard Henderson     .tb_start           = hppa_tr_tb_start,
416851b061fbSRichard Henderson     .insn_start         = hppa_tr_insn_start,
416951b061fbSRichard Henderson     .breakpoint_check   = hppa_tr_breakpoint_check,
417051b061fbSRichard Henderson     .translate_insn     = hppa_tr_translate_insn,
417151b061fbSRichard Henderson     .tb_stop            = hppa_tr_tb_stop,
417251b061fbSRichard Henderson     .disas_log          = hppa_tr_disas_log,
417351b061fbSRichard Henderson };
417451b061fbSRichard Henderson 
417551b061fbSRichard Henderson void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
417651b061fbSRichard Henderson 
417751b061fbSRichard Henderson {
417851b061fbSRichard Henderson     DisasContext ctx;
417951b061fbSRichard Henderson     translator_loop(&hppa_tr_ops, &ctx.base, cs, tb);
418061766fe9SRichard Henderson }
418161766fe9SRichard Henderson 
418261766fe9SRichard Henderson void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
418361766fe9SRichard Henderson                           target_ulong *data)
418461766fe9SRichard Henderson {
418561766fe9SRichard Henderson     env->iaoq_f = data[0];
418661766fe9SRichard Henderson     if (data[1] != -1) {
418761766fe9SRichard Henderson         env->iaoq_b = data[1];
418861766fe9SRichard Henderson     }
418961766fe9SRichard Henderson     /* Since we were executing the instruction at IAOQ_F, and took some
419061766fe9SRichard Henderson        sort of action that provoked the cpu_restore_state, we can infer
419161766fe9SRichard Henderson        that the instruction was not nullified.  */
419261766fe9SRichard Henderson     env->psw_n = 0;
419361766fe9SRichard Henderson }
4194