2 * HPPA emulation cpu translation for qemu.
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
22 #include "disas/disas.h"
23 #include "qemu/host-utils.h"
24 #include "exec/exec-all.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/helper-proto.h"
28 #include "exec/helper-gen.h"
29 #include "exec/translator.h"
30 #include "trace-tcg.h"
33 /* Since we have a distinction between register size and address size,
34 we need to redefine all of these. */
38 #undef tcg_global_reg_new
39 #undef tcg_global_mem_new
40 #undef tcg_temp_local_new
43 #if TARGET_LONG_BITS == 64
44 #define TCGv_tl TCGv_i64
45 #define tcg_temp_new_tl tcg_temp_new_i64
46 #define tcg_temp_free_tl tcg_temp_free_i64
47 #if TARGET_REGISTER_BITS == 64
48 #define tcg_gen_extu_reg_tl tcg_gen_mov_i64
50 #define tcg_gen_extu_reg_tl tcg_gen_extu_i32_i64
53 #define TCGv_tl TCGv_i32
54 #define tcg_temp_new_tl tcg_temp_new_i32
55 #define tcg_temp_free_tl tcg_temp_free_i32
56 #define tcg_gen_extu_reg_tl tcg_gen_mov_i32
59 #if TARGET_REGISTER_BITS == 64
60 #define TCGv_reg TCGv_i64
62 #define tcg_temp_new tcg_temp_new_i64
63 #define tcg_global_reg_new tcg_global_reg_new_i64
64 #define tcg_global_mem_new tcg_global_mem_new_i64
65 #define tcg_temp_local_new tcg_temp_local_new_i64
66 #define tcg_temp_free tcg_temp_free_i64
68 #define tcg_gen_movi_reg tcg_gen_movi_i64
69 #define tcg_gen_mov_reg tcg_gen_mov_i64
70 #define tcg_gen_ld8u_reg tcg_gen_ld8u_i64
71 #define tcg_gen_ld8s_reg tcg_gen_ld8s_i64
72 #define tcg_gen_ld16u_reg tcg_gen_ld16u_i64
73 #define tcg_gen_ld16s_reg tcg_gen_ld16s_i64
74 #define tcg_gen_ld32u_reg tcg_gen_ld32u_i64
75 #define tcg_gen_ld32s_reg tcg_gen_ld32s_i64
76 #define tcg_gen_ld_reg tcg_gen_ld_i64
77 #define tcg_gen_st8_reg tcg_gen_st8_i64
78 #define tcg_gen_st16_reg tcg_gen_st16_i64
79 #define tcg_gen_st32_reg tcg_gen_st32_i64
80 #define tcg_gen_st_reg tcg_gen_st_i64
81 #define tcg_gen_add_reg tcg_gen_add_i64
82 #define tcg_gen_addi_reg tcg_gen_addi_i64
83 #define tcg_gen_sub_reg tcg_gen_sub_i64
84 #define tcg_gen_neg_reg tcg_gen_neg_i64
85 #define tcg_gen_subfi_reg tcg_gen_subfi_i64
86 #define tcg_gen_subi_reg tcg_gen_subi_i64
87 #define tcg_gen_and_reg tcg_gen_and_i64
88 #define tcg_gen_andi_reg tcg_gen_andi_i64
89 #define tcg_gen_or_reg tcg_gen_or_i64
90 #define tcg_gen_ori_reg tcg_gen_ori_i64
91 #define tcg_gen_xor_reg tcg_gen_xor_i64
92 #define tcg_gen_xori_reg tcg_gen_xori_i64
93 #define tcg_gen_not_reg tcg_gen_not_i64
94 #define tcg_gen_shl_reg tcg_gen_shl_i64
95 #define tcg_gen_shli_reg tcg_gen_shli_i64
96 #define tcg_gen_shr_reg tcg_gen_shr_i64
97 #define tcg_gen_shri_reg tcg_gen_shri_i64
98 #define tcg_gen_sar_reg tcg_gen_sar_i64
99 #define tcg_gen_sari_reg tcg_gen_sari_i64
100 #define tcg_gen_brcond_reg tcg_gen_brcond_i64
101 #define tcg_gen_brcondi_reg tcg_gen_brcondi_i64
102 #define tcg_gen_setcond_reg tcg_gen_setcond_i64
103 #define tcg_gen_setcondi_reg tcg_gen_setcondi_i64
104 #define tcg_gen_mul_reg tcg_gen_mul_i64
105 #define tcg_gen_muli_reg tcg_gen_muli_i64
106 #define tcg_gen_div_reg tcg_gen_div_i64
107 #define tcg_gen_rem_reg tcg_gen_rem_i64
108 #define tcg_gen_divu_reg tcg_gen_divu_i64
109 #define tcg_gen_remu_reg tcg_gen_remu_i64
110 #define tcg_gen_discard_reg tcg_gen_discard_i64
111 #define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32
112 #define tcg_gen_trunc_i64_reg tcg_gen_mov_i64
113 #define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64
114 #define tcg_gen_ext_i32_reg tcg_gen_ext_i32_i64
115 #define tcg_gen_extu_reg_i64 tcg_gen_mov_i64
116 #define tcg_gen_ext_reg_i64 tcg_gen_mov_i64
117 #define tcg_gen_ext8u_reg tcg_gen_ext8u_i64
118 #define tcg_gen_ext8s_reg tcg_gen_ext8s_i64
119 #define tcg_gen_ext16u_reg tcg_gen_ext16u_i64
120 #define tcg_gen_ext16s_reg tcg_gen_ext16s_i64
121 #define tcg_gen_ext32u_reg tcg_gen_ext32u_i64
122 #define tcg_gen_ext32s_reg tcg_gen_ext32s_i64
123 #define tcg_gen_bswap16_reg tcg_gen_bswap16_i64
124 #define tcg_gen_bswap32_reg tcg_gen_bswap32_i64
125 #define tcg_gen_bswap64_reg tcg_gen_bswap64_i64
126 #define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64
127 #define tcg_gen_andc_reg tcg_gen_andc_i64
128 #define tcg_gen_eqv_reg tcg_gen_eqv_i64
129 #define tcg_gen_nand_reg tcg_gen_nand_i64
130 #define tcg_gen_nor_reg tcg_gen_nor_i64
131 #define tcg_gen_orc_reg tcg_gen_orc_i64
132 #define tcg_gen_clz_reg tcg_gen_clz_i64
133 #define tcg_gen_ctz_reg tcg_gen_ctz_i64
134 #define tcg_gen_clzi_reg tcg_gen_clzi_i64
135 #define tcg_gen_ctzi_reg tcg_gen_ctzi_i64
136 #define tcg_gen_clrsb_reg tcg_gen_clrsb_i64
137 #define tcg_gen_ctpop_reg tcg_gen_ctpop_i64
138 #define tcg_gen_rotl_reg tcg_gen_rotl_i64
139 #define tcg_gen_rotli_reg tcg_gen_rotli_i64
140 #define tcg_gen_rotr_reg tcg_gen_rotr_i64
141 #define tcg_gen_rotri_reg tcg_gen_rotri_i64
142 #define tcg_gen_deposit_reg tcg_gen_deposit_i64
143 #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64
144 #define tcg_gen_extract_reg tcg_gen_extract_i64
145 #define tcg_gen_sextract_reg tcg_gen_sextract_i64
146 #define tcg_const_reg tcg_const_i64
147 #define tcg_const_local_reg tcg_const_local_i64
148 #define tcg_gen_movcond_reg tcg_gen_movcond_i64
149 #define tcg_gen_add2_reg tcg_gen_add2_i64
150 #define tcg_gen_sub2_reg tcg_gen_sub2_i64
151 #define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i64
152 #define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i64
153 #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64
154 #define tcg_gen_trunc_reg_ptr tcg_gen_trunc_i64_ptr
156 #define TCGv_reg TCGv_i32
157 #define tcg_temp_new tcg_temp_new_i32
158 #define tcg_global_reg_new tcg_global_reg_new_i32
159 #define tcg_global_mem_new tcg_global_mem_new_i32
160 #define tcg_temp_local_new tcg_temp_local_new_i32
161 #define tcg_temp_free tcg_temp_free_i32
163 #define tcg_gen_movi_reg tcg_gen_movi_i32
164 #define tcg_gen_mov_reg tcg_gen_mov_i32
165 #define tcg_gen_ld8u_reg tcg_gen_ld8u_i32
166 #define tcg_gen_ld8s_reg tcg_gen_ld8s_i32
167 #define tcg_gen_ld16u_reg tcg_gen_ld16u_i32
168 #define tcg_gen_ld16s_reg tcg_gen_ld16s_i32
169 #define tcg_gen_ld32u_reg tcg_gen_ld_i32
170 #define tcg_gen_ld32s_reg tcg_gen_ld_i32
171 #define tcg_gen_ld_reg tcg_gen_ld_i32
172 #define tcg_gen_st8_reg tcg_gen_st8_i32
173 #define tcg_gen_st16_reg tcg_gen_st16_i32
174 #define tcg_gen_st32_reg tcg_gen_st32_i32
175 #define tcg_gen_st_reg tcg_gen_st_i32
176 #define tcg_gen_add_reg tcg_gen_add_i32
177 #define tcg_gen_addi_reg tcg_gen_addi_i32
178 #define tcg_gen_sub_reg tcg_gen_sub_i32
179 #define tcg_gen_neg_reg tcg_gen_neg_i32
180 #define tcg_gen_subfi_reg tcg_gen_subfi_i32
181 #define tcg_gen_subi_reg tcg_gen_subi_i32
182 #define tcg_gen_and_reg tcg_gen_and_i32
183 #define tcg_gen_andi_reg tcg_gen_andi_i32
184 #define tcg_gen_or_reg tcg_gen_or_i32
185 #define tcg_gen_ori_reg tcg_gen_ori_i32
186 #define tcg_gen_xor_reg tcg_gen_xor_i32
187 #define tcg_gen_xori_reg tcg_gen_xori_i32
188 #define tcg_gen_not_reg tcg_gen_not_i32
189 #define tcg_gen_shl_reg tcg_gen_shl_i32
190 #define tcg_gen_shli_reg tcg_gen_shli_i32
191 #define tcg_gen_shr_reg tcg_gen_shr_i32
192 #define tcg_gen_shri_reg tcg_gen_shri_i32
193 #define tcg_gen_sar_reg tcg_gen_sar_i32
194 #define tcg_gen_sari_reg tcg_gen_sari_i32
195 #define tcg_gen_brcond_reg tcg_gen_brcond_i32
196 #define tcg_gen_brcondi_reg tcg_gen_brcondi_i32
197 #define tcg_gen_setcond_reg tcg_gen_setcond_i32
198 #define tcg_gen_setcondi_reg tcg_gen_setcondi_i32
199 #define tcg_gen_mul_reg tcg_gen_mul_i32
200 #define tcg_gen_muli_reg tcg_gen_muli_i32
201 #define tcg_gen_div_reg tcg_gen_div_i32
202 #define tcg_gen_rem_reg tcg_gen_rem_i32
203 #define tcg_gen_divu_reg tcg_gen_divu_i32
204 #define tcg_gen_remu_reg tcg_gen_remu_i32
205 #define tcg_gen_discard_reg tcg_gen_discard_i32
206 #define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32
207 #define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32
208 #define tcg_gen_extu_i32_reg tcg_gen_mov_i32
209 #define tcg_gen_ext_i32_reg tcg_gen_mov_i32
210 #define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64
211 #define tcg_gen_ext_reg_i64 tcg_gen_ext_i32_i64
212 #define tcg_gen_ext8u_reg tcg_gen_ext8u_i32
213 #define tcg_gen_ext8s_reg tcg_gen_ext8s_i32
214 #define tcg_gen_ext16u_reg tcg_gen_ext16u_i32
215 #define tcg_gen_ext16s_reg tcg_gen_ext16s_i32
216 #define tcg_gen_ext32u_reg tcg_gen_mov_i32
217 #define tcg_gen_ext32s_reg tcg_gen_mov_i32
218 #define tcg_gen_bswap16_reg tcg_gen_bswap16_i32
219 #define tcg_gen_bswap32_reg tcg_gen_bswap32_i32
220 #define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64
221 #define tcg_gen_andc_reg tcg_gen_andc_i32
222 #define tcg_gen_eqv_reg tcg_gen_eqv_i32
223 #define tcg_gen_nand_reg tcg_gen_nand_i32
224 #define tcg_gen_nor_reg tcg_gen_nor_i32
225 #define tcg_gen_orc_reg tcg_gen_orc_i32
226 #define tcg_gen_clz_reg tcg_gen_clz_i32
227 #define tcg_gen_ctz_reg tcg_gen_ctz_i32
228 #define tcg_gen_clzi_reg tcg_gen_clzi_i32
229 #define tcg_gen_ctzi_reg tcg_gen_ctzi_i32
230 #define tcg_gen_clrsb_reg tcg_gen_clrsb_i32
231 #define tcg_gen_ctpop_reg tcg_gen_ctpop_i32
232 #define tcg_gen_rotl_reg tcg_gen_rotl_i32
233 #define tcg_gen_rotli_reg tcg_gen_rotli_i32
234 #define tcg_gen_rotr_reg tcg_gen_rotr_i32
235 #define tcg_gen_rotri_reg tcg_gen_rotri_i32
236 #define tcg_gen_deposit_reg tcg_gen_deposit_i32
237 #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32
238 #define tcg_gen_extract_reg tcg_gen_extract_i32
239 #define tcg_gen_sextract_reg tcg_gen_sextract_i32
240 #define tcg_const_reg tcg_const_i32
241 #define tcg_const_local_reg tcg_const_local_i32
242 #define tcg_gen_movcond_reg tcg_gen_movcond_i32
243 #define tcg_gen_add2_reg tcg_gen_add2_i32
244 #define tcg_gen_sub2_reg tcg_gen_sub2_i32
245 #define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i32
246 #define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i32
247 #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
248 #define tcg_gen_trunc_reg_ptr tcg_gen_ext_i32_ptr
249 #endif /* TARGET_REGISTER_BITS */
251 typedef struct DisasCond
{
258 typedef struct DisasContext
{
259 DisasContextBase base
;
281 /* Target-specific return values from translate_one, indicating the
282 state of the TB. Note that DISAS_NEXT indicates that we are not
285 /* We are not using a goto_tb (for whatever reason), but have updated
286 the iaq (for whatever reason), so don't do it again on exit. */
287 #define DISAS_IAQ_N_UPDATED DISAS_TARGET_0
289 /* We are exiting the TB, but have neither emitted a goto_tb, nor
290 updated the iaq for the next instruction to be executed. */
291 #define DISAS_IAQ_N_STALE DISAS_TARGET_1
293 /* Similarly, but we want to return to the main loop immediately
294 to recognize unmasked interrupts. */
295 #define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2
297 typedef struct DisasInsn
{
299 DisasJumpType (*trans
)(DisasContext
*ctx
, uint32_t insn
,
300 const struct DisasInsn
*f
);
302 void (*ttt
)(TCGv_reg
, TCGv_reg
, TCGv_reg
);
303 void (*weww
)(TCGv_i32
, TCGv_env
, TCGv_i32
, TCGv_i32
);
304 void (*dedd
)(TCGv_i64
, TCGv_env
, TCGv_i64
, TCGv_i64
);
305 void (*wew
)(TCGv_i32
, TCGv_env
, TCGv_i32
);
306 void (*ded
)(TCGv_i64
, TCGv_env
, TCGv_i64
);
307 void (*wed
)(TCGv_i32
, TCGv_env
, TCGv_i64
);
308 void (*dew
)(TCGv_i64
, TCGv_env
, TCGv_i32
);
312 /* global register indexes */
313 static TCGv_reg cpu_gr
[32];
314 static TCGv_i64 cpu_sr
[4];
315 static TCGv_i64 cpu_srH
;
316 static TCGv_reg cpu_iaoq_f
;
317 static TCGv_reg cpu_iaoq_b
;
318 static TCGv_i64 cpu_iasq_f
;
319 static TCGv_i64 cpu_iasq_b
;
320 static TCGv_reg cpu_sar
;
321 static TCGv_reg cpu_psw_n
;
322 static TCGv_reg cpu_psw_v
;
323 static TCGv_reg cpu_psw_cb
;
324 static TCGv_reg cpu_psw_cb_msb
;
326 #include "exec/gen-icount.h"
328 void hppa_translate_init(void)
330 #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
332 typedef struct { TCGv_reg
*var
; const char *name
; int ofs
; } GlobalVar
;
333 static const GlobalVar vars
[] = {
334 { &cpu_sar
, "sar", offsetof(CPUHPPAState
, cr
[CR_SAR
]) },
345 /* Use the symbolic register names that match the disassembler. */
346 static const char gr_names
[32][4] = {
347 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
348 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
349 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
350 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
352 /* SR[4-7] are not global registers so that we can index them. */
353 static const char sr_names
[5][4] = {
354 "sr0", "sr1", "sr2", "sr3", "srH"
360 for (i
= 1; i
< 32; i
++) {
361 cpu_gr
[i
] = tcg_global_mem_new(cpu_env
,
362 offsetof(CPUHPPAState
, gr
[i
]),
365 for (i
= 0; i
< 4; i
++) {
366 cpu_sr
[i
] = tcg_global_mem_new_i64(cpu_env
,
367 offsetof(CPUHPPAState
, sr
[i
]),
370 cpu_srH
= tcg_global_mem_new_i64(cpu_env
,
371 offsetof(CPUHPPAState
, sr
[4]),
374 for (i
= 0; i
< ARRAY_SIZE(vars
); ++i
) {
375 const GlobalVar
*v
= &vars
[i
];
376 *v
->var
= tcg_global_mem_new(cpu_env
, v
->ofs
, v
->name
);
379 cpu_iasq_f
= tcg_global_mem_new_i64(cpu_env
,
380 offsetof(CPUHPPAState
, iasq_f
),
382 cpu_iasq_b
= tcg_global_mem_new_i64(cpu_env
,
383 offsetof(CPUHPPAState
, iasq_b
),
387 static DisasCond
cond_make_f(void)
396 static DisasCond
cond_make_n(void)
407 static DisasCond
cond_make_0(TCGCond c
, TCGv_reg a0
)
409 DisasCond r
= { .c
= c
, .a1
= NULL
, .a1_is_0
= true };
411 assert (c
!= TCG_COND_NEVER
&& c
!= TCG_COND_ALWAYS
);
412 r
.a0
= tcg_temp_new();
413 tcg_gen_mov_reg(r
.a0
, a0
);
418 static DisasCond
cond_make(TCGCond c
, TCGv_reg a0
, TCGv_reg a1
)
420 DisasCond r
= { .c
= c
};
422 assert (c
!= TCG_COND_NEVER
&& c
!= TCG_COND_ALWAYS
);
423 r
.a0
= tcg_temp_new();
424 tcg_gen_mov_reg(r
.a0
, a0
);
425 r
.a1
= tcg_temp_new();
426 tcg_gen_mov_reg(r
.a1
, a1
);
431 static void cond_prep(DisasCond
*cond
)
434 cond
->a1_is_0
= false;
435 cond
->a1
= tcg_const_reg(0);
439 static void cond_free(DisasCond
*cond
)
443 if (!cond
->a0_is_n
) {
444 tcg_temp_free(cond
->a0
);
446 if (!cond
->a1_is_0
) {
447 tcg_temp_free(cond
->a1
);
449 cond
->a0_is_n
= false;
450 cond
->a1_is_0
= false;
454 case TCG_COND_ALWAYS
:
455 cond
->c
= TCG_COND_NEVER
;
462 static TCGv_reg
get_temp(DisasContext
*ctx
)
464 unsigned i
= ctx
->ntempr
++;
465 g_assert(i
< ARRAY_SIZE(ctx
->tempr
));
466 return ctx
->tempr
[i
] = tcg_temp_new();
469 #ifndef CONFIG_USER_ONLY
470 static TCGv_tl
get_temp_tl(DisasContext
*ctx
)
472 unsigned i
= ctx
->ntempl
++;
473 g_assert(i
< ARRAY_SIZE(ctx
->templ
));
474 return ctx
->templ
[i
] = tcg_temp_new_tl();
478 static TCGv_reg
load_const(DisasContext
*ctx
, target_sreg v
)
480 TCGv_reg t
= get_temp(ctx
);
481 tcg_gen_movi_reg(t
, v
);
485 static TCGv_reg
load_gpr(DisasContext
*ctx
, unsigned reg
)
488 TCGv_reg t
= get_temp(ctx
);
489 tcg_gen_movi_reg(t
, 0);
496 static TCGv_reg
dest_gpr(DisasContext
*ctx
, unsigned reg
)
498 if (reg
== 0 || ctx
->null_cond
.c
!= TCG_COND_NEVER
) {
499 return get_temp(ctx
);
505 static void save_or_nullify(DisasContext
*ctx
, TCGv_reg dest
, TCGv_reg t
)
507 if (ctx
->null_cond
.c
!= TCG_COND_NEVER
) {
508 cond_prep(&ctx
->null_cond
);
509 tcg_gen_movcond_reg(ctx
->null_cond
.c
, dest
, ctx
->null_cond
.a0
,
510 ctx
->null_cond
.a1
, dest
, t
);
512 tcg_gen_mov_reg(dest
, t
);
516 static void save_gpr(DisasContext
*ctx
, unsigned reg
, TCGv_reg t
)
519 save_or_nullify(ctx
, cpu_gr
[reg
], t
);
523 #ifdef HOST_WORDS_BIGENDIAN
531 static TCGv_i32
load_frw_i32(unsigned rt
)
533 TCGv_i32 ret
= tcg_temp_new_i32();
534 tcg_gen_ld_i32(ret
, cpu_env
,
535 offsetof(CPUHPPAState
, fr
[rt
& 31])
536 + (rt
& 32 ? LO_OFS
: HI_OFS
));
540 static TCGv_i32
load_frw0_i32(unsigned rt
)
543 return tcg_const_i32(0);
545 return load_frw_i32(rt
);
549 static TCGv_i64
load_frw0_i64(unsigned rt
)
552 return tcg_const_i64(0);
554 TCGv_i64 ret
= tcg_temp_new_i64();
555 tcg_gen_ld32u_i64(ret
, cpu_env
,
556 offsetof(CPUHPPAState
, fr
[rt
& 31])
557 + (rt
& 32 ? LO_OFS
: HI_OFS
));
562 static void save_frw_i32(unsigned rt
, TCGv_i32 val
)
564 tcg_gen_st_i32(val
, cpu_env
,
565 offsetof(CPUHPPAState
, fr
[rt
& 31])
566 + (rt
& 32 ? LO_OFS
: HI_OFS
));
572 static TCGv_i64
load_frd(unsigned rt
)
574 TCGv_i64 ret
= tcg_temp_new_i64();
575 tcg_gen_ld_i64(ret
, cpu_env
, offsetof(CPUHPPAState
, fr
[rt
]));
579 static TCGv_i64
load_frd0(unsigned rt
)
582 return tcg_const_i64(0);
588 static void save_frd(unsigned rt
, TCGv_i64 val
)
590 tcg_gen_st_i64(val
, cpu_env
, offsetof(CPUHPPAState
, fr
[rt
]));
593 static void load_spr(DisasContext
*ctx
, TCGv_i64 dest
, unsigned reg
)
595 #ifdef CONFIG_USER_ONLY
596 tcg_gen_movi_i64(dest
, 0);
599 tcg_gen_mov_i64(dest
, cpu_sr
[reg
]);
600 } else if (ctx
->tb_flags
& TB_FLAG_SR_SAME
) {
601 tcg_gen_mov_i64(dest
, cpu_srH
);
603 tcg_gen_ld_i64(dest
, cpu_env
, offsetof(CPUHPPAState
, sr
[reg
]));
608 /* Skip over the implementation of an insn that has been nullified.
609 Use this when the insn is too complex for a conditional move. */
610 static void nullify_over(DisasContext
*ctx
)
612 if (ctx
->null_cond
.c
!= TCG_COND_NEVER
) {
613 /* The always condition should have been handled in the main loop. */
614 assert(ctx
->null_cond
.c
!= TCG_COND_ALWAYS
);
616 ctx
->null_lab
= gen_new_label();
617 cond_prep(&ctx
->null_cond
);
619 /* If we're using PSW[N], copy it to a temp because... */
620 if (ctx
->null_cond
.a0_is_n
) {
621 ctx
->null_cond
.a0_is_n
= false;
622 ctx
->null_cond
.a0
= tcg_temp_new();
623 tcg_gen_mov_reg(ctx
->null_cond
.a0
, cpu_psw_n
);
625 /* ... we clear it before branching over the implementation,
626 so that (1) it's clear after nullifying this insn and
627 (2) if this insn nullifies the next, PSW[N] is valid. */
628 if (ctx
->psw_n_nonzero
) {
629 ctx
->psw_n_nonzero
= false;
630 tcg_gen_movi_reg(cpu_psw_n
, 0);
633 tcg_gen_brcond_reg(ctx
->null_cond
.c
, ctx
->null_cond
.a0
,
634 ctx
->null_cond
.a1
, ctx
->null_lab
);
635 cond_free(&ctx
->null_cond
);
639 /* Save the current nullification state to PSW[N]. */
640 static void nullify_save(DisasContext
*ctx
)
642 if (ctx
->null_cond
.c
== TCG_COND_NEVER
) {
643 if (ctx
->psw_n_nonzero
) {
644 tcg_gen_movi_reg(cpu_psw_n
, 0);
648 if (!ctx
->null_cond
.a0_is_n
) {
649 cond_prep(&ctx
->null_cond
);
650 tcg_gen_setcond_reg(ctx
->null_cond
.c
, cpu_psw_n
,
651 ctx
->null_cond
.a0
, ctx
->null_cond
.a1
);
652 ctx
->psw_n_nonzero
= true;
654 cond_free(&ctx
->null_cond
);
657 /* Set a PSW[N] to X. The intention is that this is used immediately
658 before a goto_tb/exit_tb, so that there is no fallthru path to other
659 code within the TB. Therefore we do not update psw_n_nonzero. */
660 static void nullify_set(DisasContext
*ctx
, bool x
)
662 if (ctx
->psw_n_nonzero
|| x
) {
663 tcg_gen_movi_reg(cpu_psw_n
, x
);
667 /* Mark the end of an instruction that may have been nullified.
668 This is the pair to nullify_over. */
669 static DisasJumpType
nullify_end(DisasContext
*ctx
, DisasJumpType status
)
671 TCGLabel
*null_lab
= ctx
->null_lab
;
673 /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
674 For UPDATED, we cannot update on the nullified path. */
675 assert(status
!= DISAS_IAQ_N_UPDATED
);
677 if (likely(null_lab
== NULL
)) {
678 /* The current insn wasn't conditional or handled the condition
679 applied to it without a branch, so the (new) setting of
680 NULL_COND can be applied directly to the next insn. */
683 ctx
->null_lab
= NULL
;
685 if (likely(ctx
->null_cond
.c
== TCG_COND_NEVER
)) {
686 /* The next instruction will be unconditional,
687 and NULL_COND already reflects that. */
688 gen_set_label(null_lab
);
690 /* The insn that we just executed is itself nullifying the next
691 instruction. Store the condition in the PSW[N] global.
692 We asserted PSW[N] = 0 in nullify_over, so that after the
693 label we have the proper value in place. */
695 gen_set_label(null_lab
);
696 ctx
->null_cond
= cond_make_n();
698 if (status
== DISAS_NORETURN
) {
704 static void copy_iaoq_entry(TCGv_reg dest
, target_ureg ival
, TCGv_reg vval
)
706 if (unlikely(ival
== -1)) {
707 tcg_gen_mov_reg(dest
, vval
);
709 tcg_gen_movi_reg(dest
, ival
);
713 static inline target_ureg
iaoq_dest(DisasContext
*ctx
, target_sreg disp
)
715 return ctx
->iaoq_f
+ disp
+ 8;
718 static void gen_excp_1(int exception
)
720 TCGv_i32 t
= tcg_const_i32(exception
);
721 gen_helper_excp(cpu_env
, t
);
722 tcg_temp_free_i32(t
);
725 static DisasJumpType
gen_excp(DisasContext
*ctx
, int exception
)
727 copy_iaoq_entry(cpu_iaoq_f
, ctx
->iaoq_f
, cpu_iaoq_f
);
728 copy_iaoq_entry(cpu_iaoq_b
, ctx
->iaoq_b
, cpu_iaoq_b
);
730 gen_excp_1(exception
);
731 return DISAS_NORETURN
;
734 static DisasJumpType
gen_excp_iir(DisasContext
*ctx
, int exc
)
736 TCGv_reg tmp
= tcg_const_reg(ctx
->insn
);
737 tcg_gen_st_reg(tmp
, cpu_env
, offsetof(CPUHPPAState
, cr
[CR_IIR
]));
739 return gen_excp(ctx
, exc
);
742 static DisasJumpType
gen_illegal(DisasContext
*ctx
)
745 return nullify_end(ctx
, gen_excp_iir(ctx
, EXCP_ILL
));
748 #define CHECK_MOST_PRIVILEGED(EXCP) \
750 if (ctx->privilege != 0) { \
752 return nullify_end(ctx, gen_excp_iir(ctx, EXCP)); \
756 static bool use_goto_tb(DisasContext
*ctx
, target_ureg dest
)
758 /* Suppress goto_tb in the case of single-steping and IO. */
759 if ((tb_cflags(ctx
->base
.tb
) & CF_LAST_IO
) || ctx
->base
.singlestep_enabled
) {
765 /* If the next insn is to be nullified, and it's on the same page,
766 and we're not attempting to set a breakpoint on it, then we can
767 totally skip the nullified insn. This avoids creating and
768 executing a TB that merely branches to the next TB. */
769 static bool use_nullify_skip(DisasContext
*ctx
)
771 return (((ctx
->iaoq_b
^ ctx
->iaoq_f
) & TARGET_PAGE_MASK
) == 0
772 && !cpu_breakpoint_test(ctx
->cs
, ctx
->iaoq_b
, BP_ANY
));
775 static void gen_goto_tb(DisasContext
*ctx
, int which
,
776 target_ureg f
, target_ureg b
)
778 if (f
!= -1 && b
!= -1 && use_goto_tb(ctx
, f
)) {
779 tcg_gen_goto_tb(which
);
780 tcg_gen_movi_reg(cpu_iaoq_f
, f
);
781 tcg_gen_movi_reg(cpu_iaoq_b
, b
);
782 tcg_gen_exit_tb((uintptr_t)ctx
->base
.tb
+ which
);
784 copy_iaoq_entry(cpu_iaoq_f
, f
, cpu_iaoq_b
);
785 copy_iaoq_entry(cpu_iaoq_b
, b
, ctx
->iaoq_n_var
);
786 if (ctx
->base
.singlestep_enabled
) {
787 gen_excp_1(EXCP_DEBUG
);
789 tcg_gen_lookup_and_goto_ptr();
794 /* PA has a habit of taking the LSB of a field and using that as the sign,
795 with the rest of the field becoming the least significant bits. */
796 static target_sreg
low_sextract(uint32_t val
, int pos
, int len
)
798 target_ureg x
= -(target_ureg
)extract32(val
, pos
, 1);
799 x
= (x
<< (len
- 1)) | extract32(val
, pos
+ 1, len
- 1);
803 static unsigned assemble_rt64(uint32_t insn
)
805 unsigned r1
= extract32(insn
, 6, 1);
806 unsigned r0
= extract32(insn
, 0, 5);
810 static unsigned assemble_ra64(uint32_t insn
)
812 unsigned r1
= extract32(insn
, 7, 1);
813 unsigned r0
= extract32(insn
, 21, 5);
817 static unsigned assemble_rb64(uint32_t insn
)
819 unsigned r1
= extract32(insn
, 12, 1);
820 unsigned r0
= extract32(insn
, 16, 5);
824 static unsigned assemble_rc64(uint32_t insn
)
826 unsigned r2
= extract32(insn
, 8, 1);
827 unsigned r1
= extract32(insn
, 13, 3);
828 unsigned r0
= extract32(insn
, 9, 2);
829 return r2
* 32 + r1
* 4 + r0
;
832 static unsigned assemble_sr3(uint32_t insn
)
834 unsigned s2
= extract32(insn
, 13, 1);
835 unsigned s0
= extract32(insn
, 14, 2);
839 static target_sreg
assemble_12(uint32_t insn
)
841 target_ureg x
= -(target_ureg
)(insn
& 1);
842 x
= (x
<< 1) | extract32(insn
, 2, 1);
843 x
= (x
<< 10) | extract32(insn
, 3, 10);
847 static target_sreg
assemble_16(uint32_t insn
)
849 /* Take the name from PA2.0, which produces a 16-bit number
850 only with wide mode; otherwise a 14-bit number. Since we don't
851 implement wide mode, this is always the 14-bit number. */
852 return low_sextract(insn
, 0, 14);
855 static target_sreg
assemble_16a(uint32_t insn
)
857 /* Take the name from PA2.0, which produces a 14-bit shifted number
858 only with wide mode; otherwise a 12-bit shifted number. Since we
859 don't implement wide mode, this is always the 12-bit number. */
860 target_ureg x
= -(target_ureg
)(insn
& 1);
861 x
= (x
<< 11) | extract32(insn
, 2, 11);
865 static target_sreg
assemble_17(uint32_t insn
)
867 target_ureg x
= -(target_ureg
)(insn
& 1);
868 x
= (x
<< 5) | extract32(insn
, 16, 5);
869 x
= (x
<< 1) | extract32(insn
, 2, 1);
870 x
= (x
<< 10) | extract32(insn
, 3, 10);
874 static target_sreg
assemble_21(uint32_t insn
)
876 target_ureg x
= -(target_ureg
)(insn
& 1);
877 x
= (x
<< 11) | extract32(insn
, 1, 11);
878 x
= (x
<< 2) | extract32(insn
, 14, 2);
879 x
= (x
<< 5) | extract32(insn
, 16, 5);
880 x
= (x
<< 2) | extract32(insn
, 12, 2);
884 static target_sreg
assemble_22(uint32_t insn
)
886 target_ureg x
= -(target_ureg
)(insn
& 1);
887 x
= (x
<< 10) | extract32(insn
, 16, 10);
888 x
= (x
<< 1) | extract32(insn
, 2, 1);
889 x
= (x
<< 10) | extract32(insn
, 3, 10);
893 /* The parisc documentation describes only the general interpretation of
894 the conditions, without describing their exact implementation. The
895 interpretations do not stand up well when considering ADD,C and SUB,B.
896 However, considering the Addition, Subtraction and Logical conditions
897 as a whole it would appear that these relations are similar to what
898 a traditional NZCV set of flags would produce. */
900 static DisasCond
do_cond(unsigned cf
, TCGv_reg res
,
901 TCGv_reg cb_msb
, TCGv_reg sv
)
907 case 0: /* Never / TR */
908 cond
= cond_make_f();
910 case 1: /* = / <> (Z / !Z) */
911 cond
= cond_make_0(TCG_COND_EQ
, res
);
913 case 2: /* < / >= (N / !N) */
914 cond
= cond_make_0(TCG_COND_LT
, res
);
916 case 3: /* <= / > (N | Z / !N & !Z) */
917 cond
= cond_make_0(TCG_COND_LE
, res
);
919 case 4: /* NUV / UV (!C / C) */
920 cond
= cond_make_0(TCG_COND_EQ
, cb_msb
);
922 case 5: /* ZNV / VNZ (!C | Z / C & !Z) */
923 tmp
= tcg_temp_new();
924 tcg_gen_neg_reg(tmp
, cb_msb
);
925 tcg_gen_and_reg(tmp
, tmp
, res
);
926 cond
= cond_make_0(TCG_COND_EQ
, tmp
);
929 case 6: /* SV / NSV (V / !V) */
930 cond
= cond_make_0(TCG_COND_LT
, sv
);
932 case 7: /* OD / EV */
933 tmp
= tcg_temp_new();
934 tcg_gen_andi_reg(tmp
, res
, 1);
935 cond
= cond_make_0(TCG_COND_NE
, tmp
);
939 g_assert_not_reached();
942 cond
.c
= tcg_invert_cond(cond
.c
);
948 /* Similar, but for the special case of subtraction without borrow, we
949 can use the inputs directly. This can allow other computation to be
950 deleted as unused. */
952 static DisasCond
do_sub_cond(unsigned cf
, TCGv_reg res
,
953 TCGv_reg in1
, TCGv_reg in2
, TCGv_reg sv
)
959 cond
= cond_make(TCG_COND_EQ
, in1
, in2
);
962 cond
= cond_make(TCG_COND_LT
, in1
, in2
);
965 cond
= cond_make(TCG_COND_LE
, in1
, in2
);
967 case 4: /* << / >>= */
968 cond
= cond_make(TCG_COND_LTU
, in1
, in2
);
970 case 5: /* <<= / >> */
971 cond
= cond_make(TCG_COND_LEU
, in1
, in2
);
974 return do_cond(cf
, res
, sv
, sv
);
977 cond
.c
= tcg_invert_cond(cond
.c
);
983 /* Similar, but for logicals, where the carry and overflow bits are not
984 computed, and use of them is undefined. */
986 static DisasCond
do_log_cond(unsigned cf
, TCGv_reg res
)
989 case 4: case 5: case 6:
993 return do_cond(cf
, res
, res
, res
);
996 /* Similar, but for shift/extract/deposit conditions. */
998 static DisasCond
do_sed_cond(unsigned orig
, TCGv_reg res
)
1002 /* Convert the compressed condition codes to standard.
1003 0-2 are the same as logicals (nv,<,<=), while 3 is OD.
1004 4-7 are the reverse of 0-3. */
1011 return do_log_cond(c
* 2 + f
, res
);
1014 /* Similar, but for unit conditions. */
1016 static DisasCond
do_unit_cond(unsigned cf
, TCGv_reg res
,
1017 TCGv_reg in1
, TCGv_reg in2
)
1020 TCGv_reg tmp
, cb
= NULL
;
1023 /* Since we want to test lots of carry-out bits all at once, do not
1024 * do our normal thing and compute carry-in of bit B+1 since that
1025 * leaves us with carry bits spread across two words.
1027 cb
= tcg_temp_new();
1028 tmp
= tcg_temp_new();
1029 tcg_gen_or_reg(cb
, in1
, in2
);
1030 tcg_gen_and_reg(tmp
, in1
, in2
);
1031 tcg_gen_andc_reg(cb
, cb
, res
);
1032 tcg_gen_or_reg(cb
, cb
, tmp
);
1037 case 0: /* never / TR */
1038 case 1: /* undefined */
1039 case 5: /* undefined */
1040 cond
= cond_make_f();
1043 case 2: /* SBZ / NBZ */
1044 /* See hasless(v,1) from
1045 * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
1047 tmp
= tcg_temp_new();
1048 tcg_gen_subi_reg(tmp
, res
, 0x01010101u
);
1049 tcg_gen_andc_reg(tmp
, tmp
, res
);
1050 tcg_gen_andi_reg(tmp
, tmp
, 0x80808080u
);
1051 cond
= cond_make_0(TCG_COND_NE
, tmp
);
1055 case 3: /* SHZ / NHZ */
1056 tmp
= tcg_temp_new();
1057 tcg_gen_subi_reg(tmp
, res
, 0x00010001u
);
1058 tcg_gen_andc_reg(tmp
, tmp
, res
);
1059 tcg_gen_andi_reg(tmp
, tmp
, 0x80008000u
);
1060 cond
= cond_make_0(TCG_COND_NE
, tmp
);
1064 case 4: /* SDC / NDC */
1065 tcg_gen_andi_reg(cb
, cb
, 0x88888888u
);
1066 cond
= cond_make_0(TCG_COND_NE
, cb
);
1069 case 6: /* SBC / NBC */
1070 tcg_gen_andi_reg(cb
, cb
, 0x80808080u
);
1071 cond
= cond_make_0(TCG_COND_NE
, cb
);
1074 case 7: /* SHC / NHC */
1075 tcg_gen_andi_reg(cb
, cb
, 0x80008000u
);
1076 cond
= cond_make_0(TCG_COND_NE
, cb
);
1080 g_assert_not_reached();
1086 cond
.c
= tcg_invert_cond(cond
.c
);
1092 /* Compute signed overflow for addition. */
1093 static TCGv_reg
do_add_sv(DisasContext
*ctx
, TCGv_reg res
,
1094 TCGv_reg in1
, TCGv_reg in2
)
1096 TCGv_reg sv
= get_temp(ctx
);
1097 TCGv_reg tmp
= tcg_temp_new();
1099 tcg_gen_xor_reg(sv
, res
, in1
);
1100 tcg_gen_xor_reg(tmp
, in1
, in2
);
1101 tcg_gen_andc_reg(sv
, sv
, tmp
);
1107 /* Compute signed overflow for subtraction. */
1108 static TCGv_reg
do_sub_sv(DisasContext
*ctx
, TCGv_reg res
,
1109 TCGv_reg in1
, TCGv_reg in2
)
1111 TCGv_reg sv
= get_temp(ctx
);
1112 TCGv_reg tmp
= tcg_temp_new();
1114 tcg_gen_xor_reg(sv
, res
, in1
);
1115 tcg_gen_xor_reg(tmp
, in1
, in2
);
1116 tcg_gen_and_reg(sv
, sv
, tmp
);
1122 static DisasJumpType
do_add(DisasContext
*ctx
, unsigned rt
, TCGv_reg in1
,
1123 TCGv_reg in2
, unsigned shift
, bool is_l
,
1124 bool is_tsv
, bool is_tc
, bool is_c
, unsigned cf
)
1126 TCGv_reg dest
, cb
, cb_msb
, sv
, tmp
;
1127 unsigned c
= cf
>> 1;
1130 dest
= tcg_temp_new();
1135 tmp
= get_temp(ctx
);
1136 tcg_gen_shli_reg(tmp
, in1
, shift
);
1140 if (!is_l
|| c
== 4 || c
== 5) {
1141 TCGv_reg zero
= tcg_const_reg(0);
1142 cb_msb
= get_temp(ctx
);
1143 tcg_gen_add2_reg(dest
, cb_msb
, in1
, zero
, in2
, zero
);
1145 tcg_gen_add2_reg(dest
, cb_msb
, dest
, cb_msb
, cpu_psw_cb_msb
, zero
);
1147 tcg_temp_free(zero
);
1150 tcg_gen_xor_reg(cb
, in1
, in2
);
1151 tcg_gen_xor_reg(cb
, cb
, dest
);
1154 tcg_gen_add_reg(dest
, in1
, in2
);
1156 tcg_gen_add_reg(dest
, dest
, cpu_psw_cb_msb
);
1160 /* Compute signed overflow if required. */
1162 if (is_tsv
|| c
== 6) {
1163 sv
= do_add_sv(ctx
, dest
, in1
, in2
);
1165 /* ??? Need to include overflow from shift. */
1166 gen_helper_tsv(cpu_env
, sv
);
1170 /* Emit any conditional trap before any writeback. */
1171 cond
= do_cond(cf
, dest
, cb_msb
, sv
);
1174 tmp
= tcg_temp_new();
1175 tcg_gen_setcond_reg(cond
.c
, tmp
, cond
.a0
, cond
.a1
);
1176 gen_helper_tcond(cpu_env
, tmp
);
1180 /* Write back the result. */
1182 save_or_nullify(ctx
, cpu_psw_cb
, cb
);
1183 save_or_nullify(ctx
, cpu_psw_cb_msb
, cb_msb
);
1185 save_gpr(ctx
, rt
, dest
);
1186 tcg_temp_free(dest
);
1188 /* Install the new nullification. */
1189 cond_free(&ctx
->null_cond
);
1190 ctx
->null_cond
= cond
;
1194 static DisasJumpType
do_sub(DisasContext
*ctx
, unsigned rt
, TCGv_reg in1
,
1195 TCGv_reg in2
, bool is_tsv
, bool is_b
,
1196 bool is_tc
, unsigned cf
)
1198 TCGv_reg dest
, sv
, cb
, cb_msb
, zero
, tmp
;
1199 unsigned c
= cf
>> 1;
1202 dest
= tcg_temp_new();
1203 cb
= tcg_temp_new();
1204 cb_msb
= tcg_temp_new();
1206 zero
= tcg_const_reg(0);
1208 /* DEST,C = IN1 + ~IN2 + C. */
1209 tcg_gen_not_reg(cb
, in2
);
1210 tcg_gen_add2_reg(dest
, cb_msb
, in1
, zero
, cpu_psw_cb_msb
, zero
);
1211 tcg_gen_add2_reg(dest
, cb_msb
, dest
, cb_msb
, cb
, zero
);
1212 tcg_gen_xor_reg(cb
, cb
, in1
);
1213 tcg_gen_xor_reg(cb
, cb
, dest
);
1215 /* DEST,C = IN1 + ~IN2 + 1. We can produce the same result in fewer
1216 operations by seeding the high word with 1 and subtracting. */
1217 tcg_gen_movi_reg(cb_msb
, 1);
1218 tcg_gen_sub2_reg(dest
, cb_msb
, in1
, cb_msb
, in2
, zero
);
1219 tcg_gen_eqv_reg(cb
, in1
, in2
);
1220 tcg_gen_xor_reg(cb
, cb
, dest
);
1222 tcg_temp_free(zero
);
1224 /* Compute signed overflow if required. */
1226 if (is_tsv
|| c
== 6) {
1227 sv
= do_sub_sv(ctx
, dest
, in1
, in2
);
1229 gen_helper_tsv(cpu_env
, sv
);
1233 /* Compute the condition. We cannot use the special case for borrow. */
1235 cond
= do_sub_cond(cf
, dest
, in1
, in2
, sv
);
1237 cond
= do_cond(cf
, dest
, cb_msb
, sv
);
1240 /* Emit any conditional trap before any writeback. */
1243 tmp
= tcg_temp_new();
1244 tcg_gen_setcond_reg(cond
.c
, tmp
, cond
.a0
, cond
.a1
);
1245 gen_helper_tcond(cpu_env
, tmp
);
1249 /* Write back the result. */
1250 save_or_nullify(ctx
, cpu_psw_cb
, cb
);
1251 save_or_nullify(ctx
, cpu_psw_cb_msb
, cb_msb
);
1252 save_gpr(ctx
, rt
, dest
);
1253 tcg_temp_free(dest
);
1255 /* Install the new nullification. */
1256 cond_free(&ctx
->null_cond
);
1257 ctx
->null_cond
= cond
;
1261 static DisasJumpType
do_cmpclr(DisasContext
*ctx
, unsigned rt
, TCGv_reg in1
,
1262 TCGv_reg in2
, unsigned cf
)
1267 dest
= tcg_temp_new();
1268 tcg_gen_sub_reg(dest
, in1
, in2
);
1270 /* Compute signed overflow if required. */
1272 if ((cf
>> 1) == 6) {
1273 sv
= do_sub_sv(ctx
, dest
, in1
, in2
);
1276 /* Form the condition for the compare. */
1277 cond
= do_sub_cond(cf
, dest
, in1
, in2
, sv
);
1280 tcg_gen_movi_reg(dest
, 0);
1281 save_gpr(ctx
, rt
, dest
);
1282 tcg_temp_free(dest
);
1284 /* Install the new nullification. */
1285 cond_free(&ctx
->null_cond
);
1286 ctx
->null_cond
= cond
;
1290 static DisasJumpType
do_log(DisasContext
*ctx
, unsigned rt
, TCGv_reg in1
,
1291 TCGv_reg in2
, unsigned cf
,
1292 void (*fn
)(TCGv_reg
, TCGv_reg
, TCGv_reg
))
1294 TCGv_reg dest
= dest_gpr(ctx
, rt
);
1296 /* Perform the operation, and writeback. */
1298 save_gpr(ctx
, rt
, dest
);
1300 /* Install the new nullification. */
1301 cond_free(&ctx
->null_cond
);
1303 ctx
->null_cond
= do_log_cond(cf
, dest
);
1308 static DisasJumpType
do_unit(DisasContext
*ctx
, unsigned rt
, TCGv_reg in1
,
1309 TCGv_reg in2
, unsigned cf
, bool is_tc
,
1310 void (*fn
)(TCGv_reg
, TCGv_reg
, TCGv_reg
))
1316 dest
= dest_gpr(ctx
, rt
);
1318 save_gpr(ctx
, rt
, dest
);
1319 cond_free(&ctx
->null_cond
);
1321 dest
= tcg_temp_new();
1324 cond
= do_unit_cond(cf
, dest
, in1
, in2
);
1327 TCGv_reg tmp
= tcg_temp_new();
1329 tcg_gen_setcond_reg(cond
.c
, tmp
, cond
.a0
, cond
.a1
);
1330 gen_helper_tcond(cpu_env
, tmp
);
1333 save_gpr(ctx
, rt
, dest
);
1335 cond_free(&ctx
->null_cond
);
1336 ctx
->null_cond
= cond
;
1341 #ifndef CONFIG_USER_ONLY
1342 /* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
1343 from the top 2 bits of the base register. There are a few system
1344 instructions that have a 3-bit space specifier, for which SR0 is
1345 not special. To handle this, pass ~SP. */
1346 static TCGv_i64
space_select(DisasContext
*ctx
, int sp
, TCGv_reg base
)
1356 spc
= get_temp_tl(ctx
);
1357 load_spr(ctx
, spc
, sp
);
1360 if (ctx
->tb_flags
& TB_FLAG_SR_SAME
) {
1364 ptr
= tcg_temp_new_ptr();
1365 tmp
= tcg_temp_new();
1366 spc
= get_temp_tl(ctx
);
1368 tcg_gen_shri_reg(tmp
, base
, TARGET_REGISTER_BITS
- 5);
1369 tcg_gen_andi_reg(tmp
, tmp
, 030);
1370 tcg_gen_trunc_reg_ptr(ptr
, tmp
);
1373 tcg_gen_add_ptr(ptr
, ptr
, cpu_env
);
1374 tcg_gen_ld_i64(spc
, ptr
, offsetof(CPUHPPAState
, sr
[4]));
1375 tcg_temp_free_ptr(ptr
);
1381 static void form_gva(DisasContext
*ctx
, TCGv_tl
*pgva
, TCGv_reg
*pofs
,
1382 unsigned rb
, unsigned rx
, int scale
, target_sreg disp
,
1383 unsigned sp
, int modify
, bool is_phys
)
1385 TCGv_reg base
= load_gpr(ctx
, rb
);
1388 /* Note that RX is mutually exclusive with DISP. */
1390 ofs
= get_temp(ctx
);
1391 tcg_gen_shli_reg(ofs
, cpu_gr
[rx
], scale
);
1392 tcg_gen_add_reg(ofs
, ofs
, base
);
1393 } else if (disp
|| modify
) {
1394 ofs
= get_temp(ctx
);
1395 tcg_gen_addi_reg(ofs
, base
, disp
);
1401 #ifdef CONFIG_USER_ONLY
1402 *pgva
= (modify
<= 0 ? ofs
: base
);
1404 TCGv_tl addr
= get_temp_tl(ctx
);
1405 tcg_gen_extu_reg_tl(addr
, modify
<= 0 ? ofs
: base
);
1406 if (ctx
->tb_flags
& PSW_W
) {
1407 tcg_gen_andi_tl(addr
, addr
, 0x3fffffffffffffffull
);
1410 tcg_gen_or_tl(addr
, addr
, space_select(ctx
, sp
, base
));
1416 /* Emit a memory load. The modify parameter should be
1417 * < 0 for pre-modify,
1418 * > 0 for post-modify,
1419 * = 0 for no base register update.
1421 static void do_load_32(DisasContext
*ctx
, TCGv_i32 dest
, unsigned rb
,
1422 unsigned rx
, int scale
, target_sreg disp
,
1423 unsigned sp
, int modify
, TCGMemOp mop
)
1428 /* Caller uses nullify_over/nullify_end. */
1429 assert(ctx
->null_cond
.c
== TCG_COND_NEVER
);
1431 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, scale
, disp
, sp
, modify
,
1432 ctx
->mmu_idx
== MMU_PHYS_IDX
);
1433 tcg_gen_qemu_ld_reg(dest
, addr
, ctx
->mmu_idx
, mop
);
1435 save_gpr(ctx
, rb
, ofs
);
1439 static void do_load_64(DisasContext
*ctx
, TCGv_i64 dest
, unsigned rb
,
1440 unsigned rx
, int scale
, target_sreg disp
,
1441 unsigned sp
, int modify
, TCGMemOp mop
)
1446 /* Caller uses nullify_over/nullify_end. */
1447 assert(ctx
->null_cond
.c
== TCG_COND_NEVER
);
1449 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, scale
, disp
, sp
, modify
,
1450 ctx
->mmu_idx
== MMU_PHYS_IDX
);
1451 tcg_gen_qemu_ld_i64(dest
, addr
, ctx
->mmu_idx
, mop
);
1453 save_gpr(ctx
, rb
, ofs
);
1457 static void do_store_32(DisasContext
*ctx
, TCGv_i32 src
, unsigned rb
,
1458 unsigned rx
, int scale
, target_sreg disp
,
1459 unsigned sp
, int modify
, TCGMemOp mop
)
1464 /* Caller uses nullify_over/nullify_end. */
1465 assert(ctx
->null_cond
.c
== TCG_COND_NEVER
);
1467 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, scale
, disp
, sp
, modify
,
1468 ctx
->mmu_idx
== MMU_PHYS_IDX
);
1469 tcg_gen_qemu_st_i32(src
, addr
, ctx
->mmu_idx
, mop
);
1471 save_gpr(ctx
, rb
, ofs
);
1475 static void do_store_64(DisasContext
*ctx
, TCGv_i64 src
, unsigned rb
,
1476 unsigned rx
, int scale
, target_sreg disp
,
1477 unsigned sp
, int modify
, TCGMemOp mop
)
1482 /* Caller uses nullify_over/nullify_end. */
1483 assert(ctx
->null_cond
.c
== TCG_COND_NEVER
);
1485 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, scale
, disp
, sp
, modify
,
1486 ctx
->mmu_idx
== MMU_PHYS_IDX
);
1487 tcg_gen_qemu_st_i64(src
, addr
, ctx
->mmu_idx
, mop
);
1489 save_gpr(ctx
, rb
, ofs
);
1493 #if TARGET_REGISTER_BITS == 64
1494 #define do_load_reg do_load_64
1495 #define do_store_reg do_store_64
1497 #define do_load_reg do_load_32
1498 #define do_store_reg do_store_32
1501 static DisasJumpType
do_load(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1502 unsigned rx
, int scale
, target_sreg disp
,
1503 unsigned sp
, int modify
, TCGMemOp mop
)
1510 /* No base register update. */
1511 dest
= dest_gpr(ctx
, rt
);
1513 /* Make sure if RT == RB, we see the result of the load. */
1514 dest
= get_temp(ctx
);
1516 do_load_reg(ctx
, dest
, rb
, rx
, scale
, disp
, sp
, modify
, mop
);
1517 save_gpr(ctx
, rt
, dest
);
1519 return nullify_end(ctx
, DISAS_NEXT
);
1522 static DisasJumpType
do_floadw(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1523 unsigned rx
, int scale
, target_sreg disp
,
1524 unsigned sp
, int modify
)
1530 tmp
= tcg_temp_new_i32();
1531 do_load_32(ctx
, tmp
, rb
, rx
, scale
, disp
, sp
, modify
, MO_TEUL
);
1532 save_frw_i32(rt
, tmp
);
1533 tcg_temp_free_i32(tmp
);
1536 gen_helper_loaded_fr0(cpu_env
);
1539 return nullify_end(ctx
, DISAS_NEXT
);
1542 static DisasJumpType
do_floadd(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1543 unsigned rx
, int scale
, target_sreg disp
,
1544 unsigned sp
, int modify
)
1550 tmp
= tcg_temp_new_i64();
1551 do_load_64(ctx
, tmp
, rb
, rx
, scale
, disp
, sp
, modify
, MO_TEQ
);
1553 tcg_temp_free_i64(tmp
);
1556 gen_helper_loaded_fr0(cpu_env
);
1559 return nullify_end(ctx
, DISAS_NEXT
);
1562 static DisasJumpType
do_store(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1563 target_sreg disp
, unsigned sp
,
1564 int modify
, TCGMemOp mop
)
1567 do_store_reg(ctx
, load_gpr(ctx
, rt
), rb
, 0, 0, disp
, sp
, modify
, mop
);
1568 return nullify_end(ctx
, DISAS_NEXT
);
1571 static DisasJumpType
do_fstorew(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1572 unsigned rx
, int scale
, target_sreg disp
,
1573 unsigned sp
, int modify
)
1579 tmp
= load_frw_i32(rt
);
1580 do_store_32(ctx
, tmp
, rb
, rx
, scale
, disp
, sp
, modify
, MO_TEUL
);
1581 tcg_temp_free_i32(tmp
);
1583 return nullify_end(ctx
, DISAS_NEXT
);
1586 static DisasJumpType
do_fstored(DisasContext
*ctx
, unsigned rt
, unsigned rb
,
1587 unsigned rx
, int scale
, target_sreg disp
,
1588 unsigned sp
, int modify
)
1595 do_store_64(ctx
, tmp
, rb
, rx
, scale
, disp
, sp
, modify
, MO_TEQ
);
1596 tcg_temp_free_i64(tmp
);
1598 return nullify_end(ctx
, DISAS_NEXT
);
1601 static DisasJumpType
do_fop_wew(DisasContext
*ctx
, unsigned rt
, unsigned ra
,
1602 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i32
))
1607 tmp
= load_frw0_i32(ra
);
1609 func(tmp
, cpu_env
, tmp
);
1611 save_frw_i32(rt
, tmp
);
1612 tcg_temp_free_i32(tmp
);
1613 return nullify_end(ctx
, DISAS_NEXT
);
1616 static DisasJumpType
do_fop_wed(DisasContext
*ctx
, unsigned rt
, unsigned ra
,
1617 void (*func
)(TCGv_i32
, TCGv_env
, TCGv_i64
))
1624 dst
= tcg_temp_new_i32();
1626 func(dst
, cpu_env
, src
);
1628 tcg_temp_free_i64(src
);
1629 save_frw_i32(rt
, dst
);
1630 tcg_temp_free_i32(dst
);
1631 return nullify_end(ctx
, DISAS_NEXT
);
1634 static DisasJumpType
do_fop_ded(DisasContext
*ctx
, unsigned rt
, unsigned ra
,
1635 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i64
))
1640 tmp
= load_frd0(ra
);
1642 func(tmp
, cpu_env
, tmp
);
1645 tcg_temp_free_i64(tmp
);
1646 return nullify_end(ctx
, DISAS_NEXT
);
1649 static DisasJumpType
do_fop_dew(DisasContext
*ctx
, unsigned rt
, unsigned ra
,
1650 void (*func
)(TCGv_i64
, TCGv_env
, TCGv_i32
))
1656 src
= load_frw0_i32(ra
);
1657 dst
= tcg_temp_new_i64();
1659 func(dst
, cpu_env
, src
);
1661 tcg_temp_free_i32(src
);
1663 tcg_temp_free_i64(dst
);
1664 return nullify_end(ctx
, DISAS_NEXT
);
1667 static DisasJumpType
do_fop_weww(DisasContext
*ctx
, unsigned rt
,
1668 unsigned ra
, unsigned rb
,
1669 void (*func
)(TCGv_i32
, TCGv_env
,
1670 TCGv_i32
, TCGv_i32
))
1675 a
= load_frw0_i32(ra
);
1676 b
= load_frw0_i32(rb
);
1678 func(a
, cpu_env
, a
, b
);
1680 tcg_temp_free_i32(b
);
1681 save_frw_i32(rt
, a
);
1682 tcg_temp_free_i32(a
);
1683 return nullify_end(ctx
, DISAS_NEXT
);
1686 static DisasJumpType
do_fop_dedd(DisasContext
*ctx
, unsigned rt
,
1687 unsigned ra
, unsigned rb
,
1688 void (*func
)(TCGv_i64
, TCGv_env
,
1689 TCGv_i64
, TCGv_i64
))
1697 func(a
, cpu_env
, a
, b
);
1699 tcg_temp_free_i64(b
);
1701 tcg_temp_free_i64(a
);
1702 return nullify_end(ctx
, DISAS_NEXT
);
1705 /* Emit an unconditional branch to a direct target, which may or may not
1706 have already had nullification handled. */
1707 static DisasJumpType
do_dbranch(DisasContext
*ctx
, target_ureg dest
,
1708 unsigned link
, bool is_n
)
1710 if (ctx
->null_cond
.c
== TCG_COND_NEVER
&& ctx
->null_lab
== NULL
) {
1712 copy_iaoq_entry(cpu_gr
[link
], ctx
->iaoq_n
, ctx
->iaoq_n_var
);
1716 ctx
->null_cond
.c
= TCG_COND_ALWAYS
;
1723 copy_iaoq_entry(cpu_gr
[link
], ctx
->iaoq_n
, ctx
->iaoq_n_var
);
1726 if (is_n
&& use_nullify_skip(ctx
)) {
1727 nullify_set(ctx
, 0);
1728 gen_goto_tb(ctx
, 0, dest
, dest
+ 4);
1730 nullify_set(ctx
, is_n
);
1731 gen_goto_tb(ctx
, 0, ctx
->iaoq_b
, dest
);
1734 nullify_end(ctx
, DISAS_NEXT
);
1736 nullify_set(ctx
, 0);
1737 gen_goto_tb(ctx
, 1, ctx
->iaoq_b
, ctx
->iaoq_n
);
1738 return DISAS_NORETURN
;
1742 /* Emit a conditional branch to a direct target. If the branch itself
1743 is nullified, we should have already used nullify_over. */
1744 static DisasJumpType
do_cbranch(DisasContext
*ctx
, target_sreg disp
, bool is_n
,
1747 target_ureg dest
= iaoq_dest(ctx
, disp
);
1748 TCGLabel
*taken
= NULL
;
1749 TCGCond c
= cond
->c
;
1752 assert(ctx
->null_cond
.c
== TCG_COND_NEVER
);
1754 /* Handle TRUE and NEVER as direct branches. */
1755 if (c
== TCG_COND_ALWAYS
) {
1756 return do_dbranch(ctx
, dest
, 0, is_n
&& disp
>= 0);
1758 if (c
== TCG_COND_NEVER
) {
1759 return do_dbranch(ctx
, ctx
->iaoq_n
, 0, is_n
&& disp
< 0);
1762 taken
= gen_new_label();
1764 tcg_gen_brcond_reg(c
, cond
->a0
, cond
->a1
, taken
);
1767 /* Not taken: Condition not satisfied; nullify on backward branches. */
1768 n
= is_n
&& disp
< 0;
1769 if (n
&& use_nullify_skip(ctx
)) {
1770 nullify_set(ctx
, 0);
1771 gen_goto_tb(ctx
, 0, ctx
->iaoq_n
, ctx
->iaoq_n
+ 4);
1773 if (!n
&& ctx
->null_lab
) {
1774 gen_set_label(ctx
->null_lab
);
1775 ctx
->null_lab
= NULL
;
1777 nullify_set(ctx
, n
);
1778 if (ctx
->iaoq_n
== -1) {
1779 /* The temporary iaoq_n_var died at the branch above.
1780 Regenerate it here instead of saving it. */
1781 tcg_gen_addi_reg(ctx
->iaoq_n_var
, cpu_iaoq_b
, 4);
1783 gen_goto_tb(ctx
, 0, ctx
->iaoq_b
, ctx
->iaoq_n
);
1786 gen_set_label(taken
);
1788 /* Taken: Condition satisfied; nullify on forward branches. */
1789 n
= is_n
&& disp
>= 0;
1790 if (n
&& use_nullify_skip(ctx
)) {
1791 nullify_set(ctx
, 0);
1792 gen_goto_tb(ctx
, 1, dest
, dest
+ 4);
1794 nullify_set(ctx
, n
);
1795 gen_goto_tb(ctx
, 1, ctx
->iaoq_b
, dest
);
1798 /* Not taken: the branch itself was nullified. */
1799 if (ctx
->null_lab
) {
1800 gen_set_label(ctx
->null_lab
);
1801 ctx
->null_lab
= NULL
;
1802 return DISAS_IAQ_N_STALE
;
1804 return DISAS_NORETURN
;
1808 /* Emit an unconditional branch to an indirect target. This handles
1809 nullification of the branch itself. */
1810 static DisasJumpType
do_ibranch(DisasContext
*ctx
, TCGv_reg dest
,
1811 unsigned link
, bool is_n
)
1813 TCGv_reg a0
, a1
, next
, tmp
;
1816 assert(ctx
->null_lab
== NULL
);
1818 if (ctx
->null_cond
.c
== TCG_COND_NEVER
) {
1820 copy_iaoq_entry(cpu_gr
[link
], ctx
->iaoq_n
, ctx
->iaoq_n_var
);
1822 next
= get_temp(ctx
);
1823 tcg_gen_mov_reg(next
, dest
);
1825 if (use_nullify_skip(ctx
)) {
1826 tcg_gen_mov_reg(cpu_iaoq_f
, next
);
1827 tcg_gen_addi_reg(cpu_iaoq_b
, next
, 4);
1828 nullify_set(ctx
, 0);
1829 return DISAS_IAQ_N_UPDATED
;
1831 ctx
->null_cond
.c
= TCG_COND_ALWAYS
;
1834 ctx
->iaoq_n_var
= next
;
1835 } else if (is_n
&& use_nullify_skip(ctx
)) {
1836 /* The (conditional) branch, B, nullifies the next insn, N,
1837 and we're allowed to skip execution N (no single-step or
1838 tracepoint in effect). Since the goto_ptr that we must use
1839 for the indirect branch consumes no special resources, we
1840 can (conditionally) skip B and continue execution. */
1841 /* The use_nullify_skip test implies we have a known control path. */
1842 tcg_debug_assert(ctx
->iaoq_b
!= -1);
1843 tcg_debug_assert(ctx
->iaoq_n
!= -1);
1845 /* We do have to handle the non-local temporary, DEST, before
1846 branching. Since IOAQ_F is not really live at this point, we
1847 can simply store DEST optimistically. Similarly with IAOQ_B. */
1848 tcg_gen_mov_reg(cpu_iaoq_f
, dest
);
1849 tcg_gen_addi_reg(cpu_iaoq_b
, dest
, 4);
1853 tcg_gen_movi_reg(cpu_gr
[link
], ctx
->iaoq_n
);
1855 tcg_gen_lookup_and_goto_ptr();
1856 return nullify_end(ctx
, DISAS_NEXT
);
1858 cond_prep(&ctx
->null_cond
);
1859 c
= ctx
->null_cond
.c
;
1860 a0
= ctx
->null_cond
.a0
;
1861 a1
= ctx
->null_cond
.a1
;
1863 tmp
= tcg_temp_new();
1864 next
= get_temp(ctx
);
1866 copy_iaoq_entry(tmp
, ctx
->iaoq_n
, ctx
->iaoq_n_var
);
1867 tcg_gen_movcond_reg(c
, next
, a0
, a1
, tmp
, dest
);
1869 ctx
->iaoq_n_var
= next
;
1872 tcg_gen_movcond_reg(c
, cpu_gr
[link
], a0
, a1
, cpu_gr
[link
], tmp
);
1876 /* The branch nullifies the next insn, which means the state of N
1877 after the branch is the inverse of the state of N that applied
1879 tcg_gen_setcond_reg(tcg_invert_cond(c
), cpu_psw_n
, a0
, a1
);
1880 cond_free(&ctx
->null_cond
);
1881 ctx
->null_cond
= cond_make_n();
1882 ctx
->psw_n_nonzero
= true;
1884 cond_free(&ctx
->null_cond
);
1892 * if (IAOQ_Front{30..31} < GR[b]{30..31})
1893 * IAOQ_Next{30..31} ← GR[b]{30..31};
1895 * IAOQ_Next{30..31} ← IAOQ_Front{30..31};
1896 * which keeps the privilege level from being increased.
1898 static TCGv_reg
do_ibranch_priv(DisasContext
*ctx
, TCGv_reg offset
)
1901 switch (ctx
->privilege
) {
1903 /* Privilege 0 is maximum and is allowed to decrease. */
1906 /* Privilege 3 is minimum and is never allowed increase. */
1907 dest
= get_temp(ctx
);
1908 tcg_gen_ori_reg(dest
, offset
, 3);
1911 dest
= tcg_temp_new();
1912 tcg_gen_andi_reg(dest
, offset
, -4);
1913 tcg_gen_ori_reg(dest
, dest
, ctx
->privilege
);
1914 tcg_gen_movcond_reg(TCG_COND_GTU
, dest
, dest
, offset
, dest
, offset
);
1915 tcg_temp_free(dest
);
1921 #ifdef CONFIG_USER_ONLY
1922 /* On Linux, page zero is normally marked execute only + gateway.
1923 Therefore normal read or write is supposed to fail, but specific
1924 offsets have kernel code mapped to raise permissions to implement
1925 system calls. Handling this via an explicit check here, rather
1926 in than the "be disp(sr2,r0)" instruction that probably sent us
1927 here, is the easiest way to handle the branch delay slot on the
1928 aforementioned BE. */
1929 static DisasJumpType
do_page_zero(DisasContext
*ctx
)
1931 /* If by some means we get here with PSW[N]=1, that implies that
1932 the B,GATE instruction would be skipped, and we'd fault on the
1933 next insn within the privilaged page. */
1934 switch (ctx
->null_cond
.c
) {
1935 case TCG_COND_NEVER
:
1937 case TCG_COND_ALWAYS
:
1938 tcg_gen_movi_reg(cpu_psw_n
, 0);
1941 /* Since this is always the first (and only) insn within the
1942 TB, we should know the state of PSW[N] from TB->FLAGS. */
1943 g_assert_not_reached();
1946 /* Check that we didn't arrive here via some means that allowed
1947 non-sequential instruction execution. Normally the PSW[B] bit
1948 detects this by disallowing the B,GATE instruction to execute
1949 under such conditions. */
1950 if (ctx
->iaoq_b
!= ctx
->iaoq_f
+ 4) {
1954 switch (ctx
->iaoq_f
& -4) {
1955 case 0x00: /* Null pointer call */
1956 gen_excp_1(EXCP_IMP
);
1957 return DISAS_NORETURN
;
1959 case 0xb0: /* LWS */
1960 gen_excp_1(EXCP_SYSCALL_LWS
);
1961 return DISAS_NORETURN
;
1963 case 0xe0: /* SET_THREAD_POINTER */
1964 tcg_gen_st_reg(cpu_gr
[26], cpu_env
, offsetof(CPUHPPAState
, cr
[27]));
1965 tcg_gen_ori_reg(cpu_iaoq_f
, cpu_gr
[31], 3);
1966 tcg_gen_addi_reg(cpu_iaoq_b
, cpu_iaoq_f
, 4);
1967 return DISAS_IAQ_N_UPDATED
;
1969 case 0x100: /* SYSCALL */
1970 gen_excp_1(EXCP_SYSCALL
);
1971 return DISAS_NORETURN
;
1975 gen_excp_1(EXCP_ILL
);
1976 return DISAS_NORETURN
;
1981 static DisasJumpType
trans_nop(DisasContext
*ctx
, uint32_t insn
,
1982 const DisasInsn
*di
)
1984 cond_free(&ctx
->null_cond
);
1988 static DisasJumpType
trans_break(DisasContext
*ctx
, uint32_t insn
,
1989 const DisasInsn
*di
)
1992 return nullify_end(ctx
, gen_excp_iir(ctx
, EXCP_BREAK
));
1995 static DisasJumpType
trans_sync(DisasContext
*ctx
, uint32_t insn
,
1996 const DisasInsn
*di
)
1998 /* No point in nullifying the memory barrier. */
1999 tcg_gen_mb(TCG_BAR_SC
| TCG_MO_ALL
);
2001 cond_free(&ctx
->null_cond
);
2005 static DisasJumpType
trans_mfia(DisasContext
*ctx
, uint32_t insn
,
2006 const DisasInsn
*di
)
2008 unsigned rt
= extract32(insn
, 0, 5);
2009 TCGv_reg tmp
= dest_gpr(ctx
, rt
);
2010 tcg_gen_movi_reg(tmp
, ctx
->iaoq_f
);
2011 save_gpr(ctx
, rt
, tmp
);
2013 cond_free(&ctx
->null_cond
);
2017 static DisasJumpType
trans_mfsp(DisasContext
*ctx
, uint32_t insn
,
2018 const DisasInsn
*di
)
2020 unsigned rt
= extract32(insn
, 0, 5);
2021 unsigned rs
= assemble_sr3(insn
);
2022 TCGv_i64 t0
= tcg_temp_new_i64();
2023 TCGv_reg t1
= tcg_temp_new();
2025 load_spr(ctx
, t0
, rs
);
2026 tcg_gen_shri_i64(t0
, t0
, 32);
2027 tcg_gen_trunc_i64_reg(t1
, t0
);
2029 save_gpr(ctx
, rt
, t1
);
2031 tcg_temp_free_i64(t0
);
2033 cond_free(&ctx
->null_cond
);
2037 static DisasJumpType
trans_mfctl(DisasContext
*ctx
, uint32_t insn
,
2038 const DisasInsn
*di
)
2040 unsigned rt
= extract32(insn
, 0, 5);
2041 unsigned ctl
= extract32(insn
, 21, 5);
2047 #ifdef TARGET_HPPA64
2048 if (extract32(insn
, 14, 1) == 0) {
2049 /* MFSAR without ,W masks low 5 bits. */
2050 tmp
= dest_gpr(ctx
, rt
);
2051 tcg_gen_andi_reg(tmp
, cpu_sar
, 31);
2052 save_gpr(ctx
, rt
, tmp
);
2056 save_gpr(ctx
, rt
, cpu_sar
);
2058 case CR_IT
: /* Interval Timer */
2059 /* FIXME: Respect PSW_S bit. */
2061 tmp
= dest_gpr(ctx
, rt
);
2062 if (ctx
->base
.tb
->cflags
& CF_USE_ICOUNT
) {
2064 gen_helper_read_interval_timer(tmp
);
2066 ret
= DISAS_IAQ_N_STALE
;
2068 gen_helper_read_interval_timer(tmp
);
2071 save_gpr(ctx
, rt
, tmp
);
2072 return nullify_end(ctx
, ret
);
2077 /* All other control registers are privileged. */
2078 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG
);
2082 tmp
= get_temp(ctx
);
2083 tcg_gen_ld_reg(tmp
, cpu_env
, offsetof(CPUHPPAState
, cr
[ctl
]));
2084 save_gpr(ctx
, rt
, tmp
);
2087 cond_free(&ctx
->null_cond
);
2091 static DisasJumpType
trans_mtsp(DisasContext
*ctx
, uint32_t insn
,
2092 const DisasInsn
*di
)
2094 unsigned rr
= extract32(insn
, 16, 5);
2095 unsigned rs
= assemble_sr3(insn
);
2099 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG
);
2103 t64
= tcg_temp_new_i64();
2104 tcg_gen_extu_reg_i64(t64
, load_gpr(ctx
, rr
));
2105 tcg_gen_shli_i64(t64
, t64
, 32);
2108 tcg_gen_st_i64(t64
, cpu_env
, offsetof(CPUHPPAState
, sr
[rs
]));
2109 ctx
->tb_flags
&= ~TB_FLAG_SR_SAME
;
2111 tcg_gen_mov_i64(cpu_sr
[rs
], t64
);
2113 tcg_temp_free_i64(t64
);
2115 return nullify_end(ctx
, DISAS_NEXT
);
2118 static DisasJumpType
trans_mtctl(DisasContext
*ctx
, uint32_t insn
,
2119 const DisasInsn
*di
)
2121 unsigned rin
= extract32(insn
, 16, 5);
2122 unsigned ctl
= extract32(insn
, 21, 5);
2123 TCGv_reg reg
= load_gpr(ctx
, rin
);
2126 if (ctl
== CR_SAR
) {
2127 tmp
= tcg_temp_new();
2128 tcg_gen_andi_reg(tmp
, reg
, TARGET_REGISTER_BITS
- 1);
2129 save_or_nullify(ctx
, cpu_sar
, tmp
);
2132 cond_free(&ctx
->null_cond
);
2136 /* All other control registers are privileged or read-only. */
2137 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG
);
2139 #ifdef CONFIG_USER_ONLY
2140 g_assert_not_reached();
2142 DisasJumpType ret
= DISAS_NEXT
;
2147 gen_helper_write_interval_timer(cpu_env
, reg
);
2150 gen_helper_write_eirr(cpu_env
, reg
);
2153 gen_helper_write_eiem(cpu_env
, reg
);
2154 ret
= DISAS_IAQ_N_STALE_EXIT
;
2159 /* FIXME: Respect PSW_Q bit */
2160 /* The write advances the queue and stores to the back element. */
2161 tmp
= get_temp(ctx
);
2162 tcg_gen_ld_reg(tmp
, cpu_env
,
2163 offsetof(CPUHPPAState
, cr_back
[ctl
- CR_IIASQ
]));
2164 tcg_gen_st_reg(tmp
, cpu_env
, offsetof(CPUHPPAState
, cr
[ctl
]));
2165 tcg_gen_st_reg(reg
, cpu_env
,
2166 offsetof(CPUHPPAState
, cr_back
[ctl
- CR_IIASQ
]));
2170 tcg_gen_st_reg(reg
, cpu_env
, offsetof(CPUHPPAState
, cr
[ctl
]));
2173 return nullify_end(ctx
, ret
);
2177 static DisasJumpType
trans_mtsarcm(DisasContext
*ctx
, uint32_t insn
,
2178 const DisasInsn
*di
)
2180 unsigned rin
= extract32(insn
, 16, 5);
2181 TCGv_reg tmp
= tcg_temp_new();
2183 tcg_gen_not_reg(tmp
, load_gpr(ctx
, rin
));
2184 tcg_gen_andi_reg(tmp
, tmp
, TARGET_REGISTER_BITS
- 1);
2185 save_or_nullify(ctx
, cpu_sar
, tmp
);
2188 cond_free(&ctx
->null_cond
);
2192 static DisasJumpType
trans_ldsid(DisasContext
*ctx
, uint32_t insn
,
2193 const DisasInsn
*di
)
2195 unsigned rt
= extract32(insn
, 0, 5);
2196 TCGv_reg dest
= dest_gpr(ctx
, rt
);
2198 #ifdef CONFIG_USER_ONLY
2199 /* We don't implement space registers in user mode. */
2200 tcg_gen_movi_reg(dest
, 0);
2202 unsigned rb
= extract32(insn
, 21, 5);
2203 unsigned sp
= extract32(insn
, 14, 2);
2204 TCGv_i64 t0
= tcg_temp_new_i64();
2206 tcg_gen_mov_i64(t0
, space_select(ctx
, sp
, load_gpr(ctx
, rb
)));
2207 tcg_gen_shri_i64(t0
, t0
, 32);
2208 tcg_gen_trunc_i64_reg(dest
, t0
);
2210 tcg_temp_free_i64(t0
);
2212 save_gpr(ctx
, rt
, dest
);
2214 cond_free(&ctx
->null_cond
);
2218 #ifndef CONFIG_USER_ONLY
2219 /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
2220 static target_ureg
extract_sm_imm(uint32_t insn
)
2222 target_ureg val
= extract32(insn
, 16, 10);
2224 if (val
& PSW_SM_E
) {
2225 val
= (val
& ~PSW_SM_E
) | PSW_E
;
2227 if (val
& PSW_SM_W
) {
2228 val
= (val
& ~PSW_SM_W
) | PSW_W
;
2233 static DisasJumpType
trans_rsm(DisasContext
*ctx
, uint32_t insn
,
2234 const DisasInsn
*di
)
2236 unsigned rt
= extract32(insn
, 0, 5);
2237 target_ureg sm
= extract_sm_imm(insn
);
2240 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2243 tmp
= get_temp(ctx
);
2244 tcg_gen_ld_reg(tmp
, cpu_env
, offsetof(CPUHPPAState
, psw
));
2245 tcg_gen_andi_reg(tmp
, tmp
, ~sm
);
2246 gen_helper_swap_system_mask(tmp
, cpu_env
, tmp
);
2247 save_gpr(ctx
, rt
, tmp
);
2249 /* Exit the TB to recognize new interrupts, e.g. PSW_M. */
2250 return nullify_end(ctx
, DISAS_IAQ_N_STALE_EXIT
);
2253 static DisasJumpType
trans_ssm(DisasContext
*ctx
, uint32_t insn
,
2254 const DisasInsn
*di
)
2256 unsigned rt
= extract32(insn
, 0, 5);
2257 target_ureg sm
= extract_sm_imm(insn
);
2260 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2263 tmp
= get_temp(ctx
);
2264 tcg_gen_ld_reg(tmp
, cpu_env
, offsetof(CPUHPPAState
, psw
));
2265 tcg_gen_ori_reg(tmp
, tmp
, sm
);
2266 gen_helper_swap_system_mask(tmp
, cpu_env
, tmp
);
2267 save_gpr(ctx
, rt
, tmp
);
2269 /* Exit the TB to recognize new interrupts, e.g. PSW_I. */
2270 return nullify_end(ctx
, DISAS_IAQ_N_STALE_EXIT
);
2273 static DisasJumpType
trans_mtsm(DisasContext
*ctx
, uint32_t insn
,
2274 const DisasInsn
*di
)
2276 unsigned rr
= extract32(insn
, 16, 5);
2279 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2282 reg
= load_gpr(ctx
, rr
);
2283 tmp
= get_temp(ctx
);
2284 gen_helper_swap_system_mask(tmp
, cpu_env
, reg
);
2286 /* Exit the TB to recognize new interrupts. */
2287 return nullify_end(ctx
, DISAS_IAQ_N_STALE_EXIT
);
2290 static DisasJumpType
trans_rfi(DisasContext
*ctx
, uint32_t insn
,
2291 const DisasInsn
*di
)
2293 unsigned comp
= extract32(insn
, 5, 4);
2295 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2299 gen_helper_rfi_r(cpu_env
);
2301 gen_helper_rfi(cpu_env
);
2303 if (ctx
->base
.singlestep_enabled
) {
2304 gen_excp_1(EXCP_DEBUG
);
2309 /* Exit the TB to recognize new interrupts. */
2310 return nullify_end(ctx
, DISAS_NORETURN
);
2313 static DisasJumpType
gen_hlt(DisasContext
*ctx
, int reset
)
2315 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2318 gen_helper_reset(cpu_env
);
2320 gen_helper_halt(cpu_env
);
2322 return nullify_end(ctx
, DISAS_NORETURN
);
2324 #endif /* !CONFIG_USER_ONLY */
2326 static const DisasInsn table_system
[] = {
2327 { 0x00000000u
, 0xfc001fe0u
, trans_break
},
2328 { 0x00001820u
, 0xffe01fffu
, trans_mtsp
},
2329 { 0x00001840u
, 0xfc00ffffu
, trans_mtctl
},
2330 { 0x016018c0u
, 0xffe0ffffu
, trans_mtsarcm
},
2331 { 0x000014a0u
, 0xffffffe0u
, trans_mfia
},
2332 { 0x000004a0u
, 0xffff1fe0u
, trans_mfsp
},
2333 { 0x000008a0u
, 0xfc1fbfe0u
, trans_mfctl
},
2334 { 0x00000400u
, 0xffffffffu
, trans_sync
}, /* sync */
2335 { 0x00100400u
, 0xffffffffu
, trans_sync
}, /* syncdma */
2336 { 0x000010a0u
, 0xfc1f3fe0u
, trans_ldsid
},
2337 #ifndef CONFIG_USER_ONLY
2338 { 0x00000e60u
, 0xfc00ffe0u
, trans_rsm
},
2339 { 0x00000d60u
, 0xfc00ffe0u
, trans_ssm
},
2340 { 0x00001860u
, 0xffe0ffffu
, trans_mtsm
},
2341 { 0x00000c00u
, 0xfffffe1fu
, trans_rfi
},
2345 static DisasJumpType
trans_base_idx_mod(DisasContext
*ctx
, uint32_t insn
,
2346 const DisasInsn
*di
)
2348 unsigned rb
= extract32(insn
, 21, 5);
2349 unsigned rx
= extract32(insn
, 16, 5);
2350 TCGv_reg dest
= dest_gpr(ctx
, rb
);
2351 TCGv_reg src1
= load_gpr(ctx
, rb
);
2352 TCGv_reg src2
= load_gpr(ctx
, rx
);
2354 /* The only thing we need to do is the base register modification. */
2355 tcg_gen_add_reg(dest
, src1
, src2
);
2356 save_gpr(ctx
, rb
, dest
);
2358 cond_free(&ctx
->null_cond
);
2362 static DisasJumpType
trans_probe(DisasContext
*ctx
, uint32_t insn
,
2363 const DisasInsn
*di
)
2365 unsigned rt
= extract32(insn
, 0, 5);
2366 unsigned sp
= extract32(insn
, 14, 2);
2367 unsigned rr
= extract32(insn
, 16, 5);
2368 unsigned rb
= extract32(insn
, 21, 5);
2369 unsigned is_write
= extract32(insn
, 6, 1);
2370 unsigned is_imm
= extract32(insn
, 13, 1);
2372 TCGv_i32 level
, want
;
2377 dest
= dest_gpr(ctx
, rt
);
2378 form_gva(ctx
, &addr
, &ofs
, rb
, 0, 0, 0, sp
, 0, false);
2381 level
= tcg_const_i32(extract32(insn
, 16, 2));
2383 level
= tcg_temp_new_i32();
2384 tcg_gen_trunc_reg_i32(level
, load_gpr(ctx
, rr
));
2385 tcg_gen_andi_i32(level
, level
, 3);
2387 want
= tcg_const_i32(is_write
? PAGE_WRITE
: PAGE_READ
);
2389 gen_helper_probe(dest
, cpu_env
, addr
, level
, want
);
2391 tcg_temp_free_i32(want
);
2392 tcg_temp_free_i32(level
);
2394 save_gpr(ctx
, rt
, dest
);
2395 return nullify_end(ctx
, DISAS_NEXT
);
2398 #ifndef CONFIG_USER_ONLY
2399 static DisasJumpType
trans_ixtlbx(DisasContext
*ctx
, uint32_t insn
,
2400 const DisasInsn
*di
)
2403 unsigned rr
= extract32(insn
, 16, 5);
2404 unsigned rb
= extract32(insn
, 21, 5);
2405 unsigned is_data
= insn
& 0x1000;
2406 unsigned is_addr
= insn
& 0x40;
2411 sp
= extract32(insn
, 14, 2);
2413 sp
= ~assemble_sr3(insn
);
2416 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2419 form_gva(ctx
, &addr
, &ofs
, rb
, 0, 0, 0, sp
, 0, false);
2420 reg
= load_gpr(ctx
, rr
);
2422 gen_helper_itlba(cpu_env
, addr
, reg
);
2424 gen_helper_itlbp(cpu_env
, addr
, reg
);
2427 /* Exit TB for ITLB change if mmu is enabled. This *should* not be
2428 the case, since the OS TLB fill handler runs with mmu disabled. */
2429 return nullify_end(ctx
, !is_data
&& (ctx
->tb_flags
& PSW_C
)
2430 ? DISAS_IAQ_N_STALE
: DISAS_NEXT
);
2433 static DisasJumpType
trans_pxtlbx(DisasContext
*ctx
, uint32_t insn
,
2434 const DisasInsn
*di
)
2436 unsigned m
= extract32(insn
, 5, 1);
2438 unsigned rx
= extract32(insn
, 16, 5);
2439 unsigned rb
= extract32(insn
, 21, 5);
2440 unsigned is_data
= insn
& 0x1000;
2441 unsigned is_local
= insn
& 0x40;
2446 sp
= extract32(insn
, 14, 2);
2448 sp
= ~assemble_sr3(insn
);
2451 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2454 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, 0, 0, sp
, m
, false);
2456 save_gpr(ctx
, rb
, ofs
);
2459 gen_helper_ptlbe(cpu_env
);
2461 gen_helper_ptlb(cpu_env
, addr
);
2464 /* Exit TB for TLB change if mmu is enabled. */
2465 return nullify_end(ctx
, !is_data
&& (ctx
->tb_flags
& PSW_C
)
2466 ? DISAS_IAQ_N_STALE
: DISAS_NEXT
);
2469 static DisasJumpType
trans_lpa(DisasContext
*ctx
, uint32_t insn
,
2470 const DisasInsn
*di
)
2472 unsigned rt
= extract32(insn
, 0, 5);
2473 unsigned m
= extract32(insn
, 5, 1);
2474 unsigned sp
= extract32(insn
, 14, 2);
2475 unsigned rx
= extract32(insn
, 16, 5);
2476 unsigned rb
= extract32(insn
, 21, 5);
2478 TCGv_reg ofs
, paddr
;
2480 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2483 form_gva(ctx
, &vaddr
, &ofs
, rb
, rx
, 0, 0, sp
, m
, false);
2485 paddr
= tcg_temp_new();
2486 gen_helper_lpa(paddr
, cpu_env
, vaddr
);
2488 /* Note that physical address result overrides base modification. */
2490 save_gpr(ctx
, rb
, ofs
);
2492 save_gpr(ctx
, rt
, paddr
);
2493 tcg_temp_free(paddr
);
2495 return nullify_end(ctx
, DISAS_NEXT
);
2498 static DisasJumpType
trans_lci(DisasContext
*ctx
, uint32_t insn
,
2499 const DisasInsn
*di
)
2501 unsigned rt
= extract32(insn
, 0, 5);
2504 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
2506 /* The Coherence Index is an implementation-defined function of the
2507 physical address. Two addresses with the same CI have a coherent
2508 view of the cache. Our implementation is to return 0 for all,
2509 since the entire address space is coherent. */
2510 ci
= tcg_const_reg(0);
2511 save_gpr(ctx
, rt
, ci
);
2516 #endif /* !CONFIG_USER_ONLY */
2518 static const DisasInsn table_mem_mgmt
[] = {
2519 { 0x04003280u
, 0xfc003fffu
, trans_nop
}, /* fdc, disp */
2520 { 0x04001280u
, 0xfc003fffu
, trans_nop
}, /* fdc, index */
2521 { 0x040012a0u
, 0xfc003fffu
, trans_base_idx_mod
}, /* fdc, index, base mod */
2522 { 0x040012c0u
, 0xfc003fffu
, trans_nop
}, /* fdce */
2523 { 0x040012e0u
, 0xfc003fffu
, trans_base_idx_mod
}, /* fdce, base mod */
2524 { 0x04000280u
, 0xfc001fffu
, trans_nop
}, /* fic 0a */
2525 { 0x040002a0u
, 0xfc001fffu
, trans_base_idx_mod
}, /* fic 0a, base mod */
2526 { 0x040013c0u
, 0xfc003fffu
, trans_nop
}, /* fic 4f */
2527 { 0x040013e0u
, 0xfc003fffu
, trans_base_idx_mod
}, /* fic 4f, base mod */
2528 { 0x040002c0u
, 0xfc001fffu
, trans_nop
}, /* fice */
2529 { 0x040002e0u
, 0xfc001fffu
, trans_base_idx_mod
}, /* fice, base mod */
2530 { 0x04002700u
, 0xfc003fffu
, trans_nop
}, /* pdc */
2531 { 0x04002720u
, 0xfc003fffu
, trans_base_idx_mod
}, /* pdc, base mod */
2532 { 0x04001180u
, 0xfc003fa0u
, trans_probe
}, /* probe */
2533 { 0x04003180u
, 0xfc003fa0u
, trans_probe
}, /* probei */
2534 #ifndef CONFIG_USER_ONLY
2535 { 0x04000000u
, 0xfc001fffu
, trans_ixtlbx
}, /* iitlbp */
2536 { 0x04000040u
, 0xfc001fffu
, trans_ixtlbx
}, /* iitlba */
2537 { 0x04001000u
, 0xfc001fffu
, trans_ixtlbx
}, /* idtlbp */
2538 { 0x04001040u
, 0xfc001fffu
, trans_ixtlbx
}, /* idtlba */
2539 { 0x04000200u
, 0xfc001fdfu
, trans_pxtlbx
}, /* pitlb */
2540 { 0x04000240u
, 0xfc001fdfu
, trans_pxtlbx
}, /* pitlbe */
2541 { 0x04001200u
, 0xfc001fdfu
, trans_pxtlbx
}, /* pdtlb */
2542 { 0x04001240u
, 0xfc001fdfu
, trans_pxtlbx
}, /* pdtlbe */
2543 { 0x04001340u
, 0xfc003fc0u
, trans_lpa
},
2544 { 0x04001300u
, 0xfc003fe0u
, trans_lci
},
2548 static DisasJumpType
trans_add(DisasContext
*ctx
, uint32_t insn
,
2549 const DisasInsn
*di
)
2551 unsigned r2
= extract32(insn
, 21, 5);
2552 unsigned r1
= extract32(insn
, 16, 5);
2553 unsigned cf
= extract32(insn
, 12, 4);
2554 unsigned ext
= extract32(insn
, 8, 4);
2555 unsigned shift
= extract32(insn
, 6, 2);
2556 unsigned rt
= extract32(insn
, 0, 5);
2557 TCGv_reg tcg_r1
, tcg_r2
;
2561 bool is_tsv
= false;
2565 case 0x6: /* ADD, SHLADD */
2567 case 0xa: /* ADD,L, SHLADD,L */
2570 case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
2573 case 0x7: /* ADD,C */
2576 case 0xf: /* ADD,C,TSV */
2577 is_c
= is_tsv
= true;
2580 return gen_illegal(ctx
);
2586 tcg_r1
= load_gpr(ctx
, r1
);
2587 tcg_r2
= load_gpr(ctx
, r2
);
2588 ret
= do_add(ctx
, rt
, tcg_r1
, tcg_r2
, shift
, is_l
, is_tsv
, is_tc
, is_c
, cf
);
2589 return nullify_end(ctx
, ret
);
2592 static DisasJumpType
trans_sub(DisasContext
*ctx
, uint32_t insn
,
2593 const DisasInsn
*di
)
2595 unsigned r2
= extract32(insn
, 21, 5);
2596 unsigned r1
= extract32(insn
, 16, 5);
2597 unsigned cf
= extract32(insn
, 12, 4);
2598 unsigned ext
= extract32(insn
, 6, 6);
2599 unsigned rt
= extract32(insn
, 0, 5);
2600 TCGv_reg tcg_r1
, tcg_r2
;
2603 bool is_tsv
= false;
2607 case 0x10: /* SUB */
2609 case 0x30: /* SUB,TSV */
2612 case 0x14: /* SUB,B */
2615 case 0x34: /* SUB,B,TSV */
2616 is_b
= is_tsv
= true;
2618 case 0x13: /* SUB,TC */
2621 case 0x33: /* SUB,TSV,TC */
2622 is_tc
= is_tsv
= true;
2625 return gen_illegal(ctx
);
2631 tcg_r1
= load_gpr(ctx
, r1
);
2632 tcg_r2
= load_gpr(ctx
, r2
);
2633 ret
= do_sub(ctx
, rt
, tcg_r1
, tcg_r2
, is_tsv
, is_b
, is_tc
, cf
);
2634 return nullify_end(ctx
, ret
);
2637 static DisasJumpType
trans_log(DisasContext
*ctx
, uint32_t insn
,
2638 const DisasInsn
*di
)
2640 unsigned r2
= extract32(insn
, 21, 5);
2641 unsigned r1
= extract32(insn
, 16, 5);
2642 unsigned cf
= extract32(insn
, 12, 4);
2643 unsigned rt
= extract32(insn
, 0, 5);
2644 TCGv_reg tcg_r1
, tcg_r2
;
2650 tcg_r1
= load_gpr(ctx
, r1
);
2651 tcg_r2
= load_gpr(ctx
, r2
);
2652 ret
= do_log(ctx
, rt
, tcg_r1
, tcg_r2
, cf
, di
->f
.ttt
);
2653 return nullify_end(ctx
, ret
);
2656 /* OR r,0,t -> COPY (according to gas) */
2657 static DisasJumpType
trans_copy(DisasContext
*ctx
, uint32_t insn
,
2658 const DisasInsn
*di
)
2660 unsigned r1
= extract32(insn
, 16, 5);
2661 unsigned rt
= extract32(insn
, 0, 5);
2664 TCGv_reg dest
= dest_gpr(ctx
, rt
);
2665 tcg_gen_movi_reg(dest
, 0);
2666 save_gpr(ctx
, rt
, dest
);
2668 save_gpr(ctx
, rt
, cpu_gr
[r1
]);
2670 cond_free(&ctx
->null_cond
);
2674 static DisasJumpType
trans_cmpclr(DisasContext
*ctx
, uint32_t insn
,
2675 const DisasInsn
*di
)
2677 unsigned r2
= extract32(insn
, 21, 5);
2678 unsigned r1
= extract32(insn
, 16, 5);
2679 unsigned cf
= extract32(insn
, 12, 4);
2680 unsigned rt
= extract32(insn
, 0, 5);
2681 TCGv_reg tcg_r1
, tcg_r2
;
2687 tcg_r1
= load_gpr(ctx
, r1
);
2688 tcg_r2
= load_gpr(ctx
, r2
);
2689 ret
= do_cmpclr(ctx
, rt
, tcg_r1
, tcg_r2
, cf
);
2690 return nullify_end(ctx
, ret
);
2693 static DisasJumpType
trans_uxor(DisasContext
*ctx
, uint32_t insn
,
2694 const DisasInsn
*di
)
2696 unsigned r2
= extract32(insn
, 21, 5);
2697 unsigned r1
= extract32(insn
, 16, 5);
2698 unsigned cf
= extract32(insn
, 12, 4);
2699 unsigned rt
= extract32(insn
, 0, 5);
2700 TCGv_reg tcg_r1
, tcg_r2
;
2706 tcg_r1
= load_gpr(ctx
, r1
);
2707 tcg_r2
= load_gpr(ctx
, r2
);
2708 ret
= do_unit(ctx
, rt
, tcg_r1
, tcg_r2
, cf
, false, tcg_gen_xor_reg
);
2709 return nullify_end(ctx
, ret
);
2712 static DisasJumpType
trans_uaddcm(DisasContext
*ctx
, uint32_t insn
,
2713 const DisasInsn
*di
)
2715 unsigned r2
= extract32(insn
, 21, 5);
2716 unsigned r1
= extract32(insn
, 16, 5);
2717 unsigned cf
= extract32(insn
, 12, 4);
2718 unsigned is_tc
= extract32(insn
, 6, 1);
2719 unsigned rt
= extract32(insn
, 0, 5);
2720 TCGv_reg tcg_r1
, tcg_r2
, tmp
;
2726 tcg_r1
= load_gpr(ctx
, r1
);
2727 tcg_r2
= load_gpr(ctx
, r2
);
2728 tmp
= get_temp(ctx
);
2729 tcg_gen_not_reg(tmp
, tcg_r2
);
2730 ret
= do_unit(ctx
, rt
, tcg_r1
, tmp
, cf
, is_tc
, tcg_gen_add_reg
);
2731 return nullify_end(ctx
, ret
);
2734 static DisasJumpType
trans_dcor(DisasContext
*ctx
, uint32_t insn
,
2735 const DisasInsn
*di
)
2737 unsigned r2
= extract32(insn
, 21, 5);
2738 unsigned cf
= extract32(insn
, 12, 4);
2739 unsigned is_i
= extract32(insn
, 6, 1);
2740 unsigned rt
= extract32(insn
, 0, 5);
2746 tmp
= get_temp(ctx
);
2747 tcg_gen_shri_reg(tmp
, cpu_psw_cb
, 3);
2749 tcg_gen_not_reg(tmp
, tmp
);
2751 tcg_gen_andi_reg(tmp
, tmp
, 0x11111111);
2752 tcg_gen_muli_reg(tmp
, tmp
, 6);
2753 ret
= do_unit(ctx
, rt
, tmp
, load_gpr(ctx
, r2
), cf
, false,
2754 is_i
? tcg_gen_add_reg
: tcg_gen_sub_reg
);
2756 return nullify_end(ctx
, ret
);
2759 static DisasJumpType
trans_ds(DisasContext
*ctx
, uint32_t insn
,
2760 const DisasInsn
*di
)
2762 unsigned r2
= extract32(insn
, 21, 5);
2763 unsigned r1
= extract32(insn
, 16, 5);
2764 unsigned cf
= extract32(insn
, 12, 4);
2765 unsigned rt
= extract32(insn
, 0, 5);
2766 TCGv_reg dest
, add1
, add2
, addc
, zero
, in1
, in2
;
2770 in1
= load_gpr(ctx
, r1
);
2771 in2
= load_gpr(ctx
, r2
);
2773 add1
= tcg_temp_new();
2774 add2
= tcg_temp_new();
2775 addc
= tcg_temp_new();
2776 dest
= tcg_temp_new();
2777 zero
= tcg_const_reg(0);
2779 /* Form R1 << 1 | PSW[CB]{8}. */
2780 tcg_gen_add_reg(add1
, in1
, in1
);
2781 tcg_gen_add_reg(add1
, add1
, cpu_psw_cb_msb
);
2783 /* Add or subtract R2, depending on PSW[V]. Proper computation of
2784 carry{8} requires that we subtract via + ~R2 + 1, as described in
2785 the manual. By extracting and masking V, we can produce the
2786 proper inputs to the addition without movcond. */
2787 tcg_gen_sari_reg(addc
, cpu_psw_v
, TARGET_REGISTER_BITS
- 1);
2788 tcg_gen_xor_reg(add2
, in2
, addc
);
2789 tcg_gen_andi_reg(addc
, addc
, 1);
2790 /* ??? This is only correct for 32-bit. */
2791 tcg_gen_add2_i32(dest
, cpu_psw_cb_msb
, add1
, zero
, add2
, zero
);
2792 tcg_gen_add2_i32(dest
, cpu_psw_cb_msb
, dest
, cpu_psw_cb_msb
, addc
, zero
);
2794 tcg_temp_free(addc
);
2795 tcg_temp_free(zero
);
2797 /* Write back the result register. */
2798 save_gpr(ctx
, rt
, dest
);
2800 /* Write back PSW[CB]. */
2801 tcg_gen_xor_reg(cpu_psw_cb
, add1
, add2
);
2802 tcg_gen_xor_reg(cpu_psw_cb
, cpu_psw_cb
, dest
);
2804 /* Write back PSW[V] for the division step. */
2805 tcg_gen_neg_reg(cpu_psw_v
, cpu_psw_cb_msb
);
2806 tcg_gen_xor_reg(cpu_psw_v
, cpu_psw_v
, in2
);
2808 /* Install the new nullification. */
2812 /* ??? The lshift is supposed to contribute to overflow. */
2813 sv
= do_add_sv(ctx
, dest
, add1
, add2
);
2815 ctx
->null_cond
= do_cond(cf
, dest
, cpu_psw_cb_msb
, sv
);
2818 tcg_temp_free(add1
);
2819 tcg_temp_free(add2
);
2820 tcg_temp_free(dest
);
2822 return nullify_end(ctx
, DISAS_NEXT
);
2825 #ifndef CONFIG_USER_ONLY
2826 /* These are QEMU extensions and are nops in the real architecture:
2828 * or %r10,%r10,%r10 -- idle loop; wait for interrupt
2829 * or %r31,%r31,%r31 -- death loop; offline cpu
2830 * currently implemented as idle.
2832 static DisasJumpType
trans_pause(DisasContext
*ctx
, uint32_t insn
,
2833 const DisasInsn
*di
)
2837 /* No need to check for supervisor, as userland can only pause
2838 until the next timer interrupt. */
2841 /* Advance the instruction queue. */
2842 copy_iaoq_entry(cpu_iaoq_f
, ctx
->iaoq_b
, cpu_iaoq_b
);
2843 copy_iaoq_entry(cpu_iaoq_b
, ctx
->iaoq_n
, ctx
->iaoq_n_var
);
2844 nullify_set(ctx
, 0);
2846 /* Tell the qemu main loop to halt until this cpu has work. */
2847 tmp
= tcg_const_i32(1);
2848 tcg_gen_st_i32(tmp
, cpu_env
, -offsetof(HPPACPU
, env
) +
2849 offsetof(CPUState
, halted
));
2850 tcg_temp_free_i32(tmp
);
2851 gen_excp_1(EXCP_HALTED
);
2853 return nullify_end(ctx
, DISAS_NORETURN
);
2857 static const DisasInsn table_arith_log
[] = {
2858 { 0x08000240u
, 0xfc00ffffu
, trans_nop
}, /* or x,y,0 */
2859 { 0x08000240u
, 0xffe0ffe0u
, trans_copy
}, /* or x,0,t */
2860 #ifndef CONFIG_USER_ONLY
2861 { 0x094a024au
, 0xffffffffu
, trans_pause
}, /* or r10,r10,r10 */
2862 { 0x0bff025fu
, 0xffffffffu
, trans_pause
}, /* or r31,r31,r31 */
2864 { 0x08000000u
, 0xfc000fe0u
, trans_log
, .f
.ttt
= tcg_gen_andc_reg
},
2865 { 0x08000200u
, 0xfc000fe0u
, trans_log
, .f
.ttt
= tcg_gen_and_reg
},
2866 { 0x08000240u
, 0xfc000fe0u
, trans_log
, .f
.ttt
= tcg_gen_or_reg
},
2867 { 0x08000280u
, 0xfc000fe0u
, trans_log
, .f
.ttt
= tcg_gen_xor_reg
},
2868 { 0x08000880u
, 0xfc000fe0u
, trans_cmpclr
},
2869 { 0x08000380u
, 0xfc000fe0u
, trans_uxor
},
2870 { 0x08000980u
, 0xfc000fa0u
, trans_uaddcm
},
2871 { 0x08000b80u
, 0xfc1f0fa0u
, trans_dcor
},
2872 { 0x08000440u
, 0xfc000fe0u
, trans_ds
},
2873 { 0x08000700u
, 0xfc0007e0u
, trans_add
}, /* add */
2874 { 0x08000400u
, 0xfc0006e0u
, trans_sub
}, /* sub; sub,b; sub,tsv */
2875 { 0x080004c0u
, 0xfc0007e0u
, trans_sub
}, /* sub,tc; sub,tsv,tc */
2876 { 0x08000200u
, 0xfc000320u
, trans_add
}, /* shladd */
2879 static DisasJumpType
trans_addi(DisasContext
*ctx
, uint32_t insn
)
2881 target_sreg im
= low_sextract(insn
, 0, 11);
2882 unsigned e1
= extract32(insn
, 11, 1);
2883 unsigned cf
= extract32(insn
, 12, 4);
2884 unsigned rt
= extract32(insn
, 16, 5);
2885 unsigned r2
= extract32(insn
, 21, 5);
2886 unsigned o1
= extract32(insn
, 26, 1);
2887 TCGv_reg tcg_im
, tcg_r2
;
2894 tcg_im
= load_const(ctx
, im
);
2895 tcg_r2
= load_gpr(ctx
, r2
);
2896 ret
= do_add(ctx
, rt
, tcg_im
, tcg_r2
, 0, false, e1
, !o1
, false, cf
);
2898 return nullify_end(ctx
, ret
);
2901 static DisasJumpType
trans_subi(DisasContext
*ctx
, uint32_t insn
)
2903 target_sreg im
= low_sextract(insn
, 0, 11);
2904 unsigned e1
= extract32(insn
, 11, 1);
2905 unsigned cf
= extract32(insn
, 12, 4);
2906 unsigned rt
= extract32(insn
, 16, 5);
2907 unsigned r2
= extract32(insn
, 21, 5);
2908 TCGv_reg tcg_im
, tcg_r2
;
2915 tcg_im
= load_const(ctx
, im
);
2916 tcg_r2
= load_gpr(ctx
, r2
);
2917 ret
= do_sub(ctx
, rt
, tcg_im
, tcg_r2
, e1
, false, false, cf
);
2919 return nullify_end(ctx
, ret
);
2922 static DisasJumpType
trans_cmpiclr(DisasContext
*ctx
, uint32_t insn
)
2924 target_sreg im
= low_sextract(insn
, 0, 11);
2925 unsigned cf
= extract32(insn
, 12, 4);
2926 unsigned rt
= extract32(insn
, 16, 5);
2927 unsigned r2
= extract32(insn
, 21, 5);
2928 TCGv_reg tcg_im
, tcg_r2
;
2935 tcg_im
= load_const(ctx
, im
);
2936 tcg_r2
= load_gpr(ctx
, r2
);
2937 ret
= do_cmpclr(ctx
, rt
, tcg_im
, tcg_r2
, cf
);
2939 return nullify_end(ctx
, ret
);
2942 static DisasJumpType
trans_ld_idx_i(DisasContext
*ctx
, uint32_t insn
,
2943 const DisasInsn
*di
)
2945 unsigned rt
= extract32(insn
, 0, 5);
2946 unsigned m
= extract32(insn
, 5, 1);
2947 unsigned sz
= extract32(insn
, 6, 2);
2948 unsigned a
= extract32(insn
, 13, 1);
2949 unsigned sp
= extract32(insn
, 14, 2);
2950 int disp
= low_sextract(insn
, 16, 5);
2951 unsigned rb
= extract32(insn
, 21, 5);
2952 int modify
= (m
? (a
? -1 : 1) : 0);
2953 TCGMemOp mop
= MO_TE
| sz
;
2955 return do_load(ctx
, rt
, rb
, 0, 0, disp
, sp
, modify
, mop
);
2958 static DisasJumpType
trans_ld_idx_x(DisasContext
*ctx
, uint32_t insn
,
2959 const DisasInsn
*di
)
2961 unsigned rt
= extract32(insn
, 0, 5);
2962 unsigned m
= extract32(insn
, 5, 1);
2963 unsigned sz
= extract32(insn
, 6, 2);
2964 unsigned u
= extract32(insn
, 13, 1);
2965 unsigned sp
= extract32(insn
, 14, 2);
2966 unsigned rx
= extract32(insn
, 16, 5);
2967 unsigned rb
= extract32(insn
, 21, 5);
2968 TCGMemOp mop
= MO_TE
| sz
;
2970 return do_load(ctx
, rt
, rb
, rx
, u
? sz
: 0, 0, sp
, m
, mop
);
2973 static DisasJumpType
trans_st_idx_i(DisasContext
*ctx
, uint32_t insn
,
2974 const DisasInsn
*di
)
2976 int disp
= low_sextract(insn
, 0, 5);
2977 unsigned m
= extract32(insn
, 5, 1);
2978 unsigned sz
= extract32(insn
, 6, 2);
2979 unsigned a
= extract32(insn
, 13, 1);
2980 unsigned sp
= extract32(insn
, 14, 2);
2981 unsigned rr
= extract32(insn
, 16, 5);
2982 unsigned rb
= extract32(insn
, 21, 5);
2983 int modify
= (m
? (a
? -1 : 1) : 0);
2984 TCGMemOp mop
= MO_TE
| sz
;
2986 return do_store(ctx
, rr
, rb
, disp
, sp
, modify
, mop
);
2989 static DisasJumpType
trans_ldcw(DisasContext
*ctx
, uint32_t insn
,
2990 const DisasInsn
*di
)
2992 unsigned rt
= extract32(insn
, 0, 5);
2993 unsigned m
= extract32(insn
, 5, 1);
2994 unsigned i
= extract32(insn
, 12, 1);
2995 unsigned au
= extract32(insn
, 13, 1);
2996 unsigned sp
= extract32(insn
, 14, 2);
2997 unsigned rx
= extract32(insn
, 16, 5);
2998 unsigned rb
= extract32(insn
, 21, 5);
2999 TCGMemOp mop
= MO_TEUL
| MO_ALIGN_16
;
3000 TCGv_reg zero
, dest
, ofs
;
3002 int modify
, disp
= 0, scale
= 0;
3007 modify
= (m
? (au
? -1 : 1) : 0);
3008 disp
= low_sextract(rx
, 0, 5);
3013 scale
= mop
& MO_SIZE
;
3017 /* Base register modification. Make sure if RT == RB,
3018 we see the result of the load. */
3019 dest
= get_temp(ctx
);
3021 dest
= dest_gpr(ctx
, rt
);
3024 form_gva(ctx
, &addr
, &ofs
, rb
, rx
, scale
, disp
, sp
, modify
,
3025 ctx
->mmu_idx
== MMU_PHYS_IDX
);
3026 zero
= tcg_const_reg(0);
3027 tcg_gen_atomic_xchg_reg(dest
, addr
, zero
, ctx
->mmu_idx
, mop
);
3029 save_gpr(ctx
, rb
, ofs
);
3031 save_gpr(ctx
, rt
, dest
);
3033 return nullify_end(ctx
, DISAS_NEXT
);
3036 static DisasJumpType
trans_stby(DisasContext
*ctx
, uint32_t insn
,
3037 const DisasInsn
*di
)
3039 target_sreg disp
= low_sextract(insn
, 0, 5);
3040 unsigned m
= extract32(insn
, 5, 1);
3041 unsigned a
= extract32(insn
, 13, 1);
3042 unsigned sp
= extract32(insn
, 14, 2);
3043 unsigned rt
= extract32(insn
, 16, 5);
3044 unsigned rb
= extract32(insn
, 21, 5);
3050 form_gva(ctx
, &addr
, &ofs
, rb
, 0, 0, disp
, sp
, m
,
3051 ctx
->mmu_idx
== MMU_PHYS_IDX
);
3052 val
= load_gpr(ctx
, rt
);
3054 if (tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
) {
3055 gen_helper_stby_e_parallel(cpu_env
, addr
, val
);
3057 gen_helper_stby_e(cpu_env
, addr
, val
);
3060 if (tb_cflags(ctx
->base
.tb
) & CF_PARALLEL
) {
3061 gen_helper_stby_b_parallel(cpu_env
, addr
, val
);
3063 gen_helper_stby_b(cpu_env
, addr
, val
);
3068 tcg_gen_andi_reg(ofs
, ofs
, ~3);
3069 save_gpr(ctx
, rb
, ofs
);
3072 return nullify_end(ctx
, DISAS_NEXT
);
3075 #ifndef CONFIG_USER_ONLY
3076 static DisasJumpType
trans_ldwa_idx_i(DisasContext
*ctx
, uint32_t insn
,
3077 const DisasInsn
*di
)
3079 int hold_mmu_idx
= ctx
->mmu_idx
;
3082 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
3084 /* ??? needs fixing for hppa64 -- ldda does not follow the same
3085 format wrt the sub-opcode in bits 6:9. */
3086 ctx
->mmu_idx
= MMU_PHYS_IDX
;
3087 ret
= trans_ld_idx_i(ctx
, insn
, di
);
3088 ctx
->mmu_idx
= hold_mmu_idx
;
3092 static DisasJumpType
trans_ldwa_idx_x(DisasContext
*ctx
, uint32_t insn
,
3093 const DisasInsn
*di
)
3095 int hold_mmu_idx
= ctx
->mmu_idx
;
3098 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
3100 /* ??? needs fixing for hppa64 -- ldda does not follow the same
3101 format wrt the sub-opcode in bits 6:9. */
3102 ctx
->mmu_idx
= MMU_PHYS_IDX
;
3103 ret
= trans_ld_idx_x(ctx
, insn
, di
);
3104 ctx
->mmu_idx
= hold_mmu_idx
;
3108 static DisasJumpType
trans_stwa_idx_i(DisasContext
*ctx
, uint32_t insn
,
3109 const DisasInsn
*di
)
3111 int hold_mmu_idx
= ctx
->mmu_idx
;
3114 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR
);
3116 /* ??? needs fixing for hppa64 -- ldda does not follow the same
3117 format wrt the sub-opcode in bits 6:9. */
3118 ctx
->mmu_idx
= MMU_PHYS_IDX
;
3119 ret
= trans_st_idx_i(ctx
, insn
, di
);
3120 ctx
->mmu_idx
= hold_mmu_idx
;
3125 static const DisasInsn table_index_mem
[] = {
3126 { 0x0c001000u
, 0xfc001300, trans_ld_idx_i
}, /* LD[BHWD], im */
3127 { 0x0c000000u
, 0xfc001300, trans_ld_idx_x
}, /* LD[BHWD], rx */
3128 { 0x0c001200u
, 0xfc001300, trans_st_idx_i
}, /* ST[BHWD] */
3129 { 0x0c0001c0u
, 0xfc0003c0, trans_ldcw
},
3130 { 0x0c001300u
, 0xfc0013c0, trans_stby
},
3131 #ifndef CONFIG_USER_ONLY
3132 { 0x0c000180u
, 0xfc00d3c0, trans_ldwa_idx_x
}, /* LDWA, rx */
3133 { 0x0c001180u
, 0xfc00d3c0, trans_ldwa_idx_i
}, /* LDWA, im */
3134 { 0x0c001380u
, 0xfc00d3c0, trans_stwa_idx_i
}, /* STWA, im */
3138 static DisasJumpType
trans_ldil(DisasContext
*ctx
, uint32_t insn
)
3140 unsigned rt
= extract32(insn
, 21, 5);
3141 target_sreg i
= assemble_21(insn
);
3142 TCGv_reg tcg_rt
= dest_gpr(ctx
, rt
);
3144 tcg_gen_movi_reg(tcg_rt
, i
);
3145 save_gpr(ctx
, rt
, tcg_rt
);
3146 cond_free(&ctx
->null_cond
);
3151 static DisasJumpType
trans_addil(DisasContext
*ctx
, uint32_t insn
)
3153 unsigned rt
= extract32(insn
, 21, 5);
3154 target_sreg i
= assemble_21(insn
);
3155 TCGv_reg tcg_rt
= load_gpr(ctx
, rt
);
3156 TCGv_reg tcg_r1
= dest_gpr(ctx
, 1);
3158 tcg_gen_addi_reg(tcg_r1
, tcg_rt
, i
);
3159 save_gpr(ctx
, 1, tcg_r1
);
3160 cond_free(&ctx
->null_cond
);
3165 static DisasJumpType
trans_ldo(DisasContext
*ctx
, uint32_t insn
)
3167 unsigned rb
= extract32(insn
, 21, 5);
3168 unsigned rt
= extract32(insn
, 16, 5);
3169 target_sreg i
= assemble_16(insn
);
3170 TCGv_reg tcg_rt
= dest_gpr(ctx
, rt
);
3172 /* Special case rb == 0, for the LDI pseudo-op.
3173 The COPY pseudo-op is handled for free within tcg_gen_addi_tl. */
3175 tcg_gen_movi_reg(tcg_rt
, i
);
3177 tcg_gen_addi_reg(tcg_rt
, cpu_gr
[rb
], i
);
3179 save_gpr(ctx
, rt
, tcg_rt
);
3180 cond_free(&ctx
->null_cond
);
3185 static DisasJumpType
trans_load(DisasContext
*ctx
, uint32_t insn
,
3186 bool is_mod
, TCGMemOp mop
)
3188 unsigned rb
= extract32(insn
, 21, 5);
3189 unsigned rt
= extract32(insn
, 16, 5);
3190 unsigned sp
= extract32(insn
, 14, 2);
3191 target_sreg i
= assemble_16(insn
);
3193 return do_load(ctx
, rt
, rb
, 0, 0, i
, sp
,
3194 is_mod
? (i
< 0 ? -1 : 1) : 0, mop
);
3197 static DisasJumpType
trans_load_w(DisasContext
*ctx
, uint32_t insn
)
3199 unsigned rb
= extract32(insn
, 21, 5);
3200 unsigned rt
= extract32(insn
, 16, 5);
3201 unsigned sp
= extract32(insn
, 14, 2);
3202 target_sreg i
= assemble_16a(insn
);
3203 unsigned ext2
= extract32(insn
, 1, 2);
3208 /* FLDW without modification. */
3209 return do_floadw(ctx
, ext2
* 32 + rt
, rb
, 0, 0, i
, sp
, 0);
3211 /* LDW with modification. Note that the sign of I selects
3212 post-dec vs pre-inc. */
3213 return do_load(ctx
, rt
, rb
, 0, 0, i
, sp
, (i
< 0 ? 1 : -1), MO_TEUL
);
3215 return gen_illegal(ctx
);
3219 static DisasJumpType
trans_fload_mod(DisasContext
*ctx
, uint32_t insn
)
3221 target_sreg i
= assemble_16a(insn
);
3222 unsigned t1
= extract32(insn
, 1, 1);
3223 unsigned a
= extract32(insn
, 2, 1);
3224 unsigned sp
= extract32(insn
, 14, 2);
3225 unsigned t0
= extract32(insn
, 16, 5);
3226 unsigned rb
= extract32(insn
, 21, 5);
3228 /* FLDW with modification. */
3229 return do_floadw(ctx
, t1
* 32 + t0
, rb
, 0, 0, i
, sp
, (a
? -1 : 1));
3232 static DisasJumpType
trans_store(DisasContext
*ctx
, uint32_t insn
,
3233 bool is_mod
, TCGMemOp mop
)
3235 unsigned rb
= extract32(insn
, 21, 5);
3236 unsigned rt
= extract32(insn
, 16, 5);
3237 unsigned sp
= extract32(insn
, 14, 2);
3238 target_sreg i
= assemble_16(insn
);
3240 return do_store(ctx
, rt
, rb
, i
, sp
, is_mod
? (i
< 0 ? -1 : 1) : 0, mop
);
3243 static DisasJumpType
trans_store_w(DisasContext
*ctx
, uint32_t insn
)
3245 unsigned rb
= extract32(insn
, 21, 5);
3246 unsigned rt
= extract32(insn
, 16, 5);
3247 unsigned sp
= extract32(insn
, 14, 2);
3248 target_sreg i
= assemble_16a(insn
);
3249 unsigned ext2
= extract32(insn
, 1, 2);
3254 /* FSTW without modification. */
3255 return do_fstorew(ctx
, ext2
* 32 + rt
, rb
, 0, 0, i
, sp
, 0);
3257 /* STW with modification. */
3258 return do_store(ctx
, rt
, rb
, i
, sp
, (i
< 0 ? 1 : -1), MO_TEUL
);
3260 return gen_illegal(ctx
);
3264 static DisasJumpType
trans_fstore_mod(DisasContext
*ctx
, uint32_t insn
)
3266 target_sreg i
= assemble_16a(insn
);
3267 unsigned t1
= extract32(insn
, 1, 1);
3268 unsigned a
= extract32(insn
, 2, 1);
3269 unsigned sp
= extract32(insn
, 14, 2);
3270 unsigned t0
= extract32(insn
, 16, 5);
3271 unsigned rb
= extract32(insn
, 21, 5);
3273 /* FSTW with modification. */
3274 return do_fstorew(ctx
, t1
* 32 + t0
, rb
, 0, 0, i
, sp
, (a
? -1 : 1));
3277 static DisasJumpType
trans_copr_w(DisasContext
*ctx
, uint32_t insn
)
3279 unsigned t0
= extract32(insn
, 0, 5);
3280 unsigned m
= extract32(insn
, 5, 1);
3281 unsigned t1
= extract32(insn
, 6, 1);
3282 unsigned ext3
= extract32(insn
, 7, 3);
3283 /* unsigned cc = extract32(insn, 10, 2); */
3284 unsigned i
= extract32(insn
, 12, 1);
3285 unsigned ua
= extract32(insn
, 13, 1);
3286 unsigned sp
= extract32(insn
, 14, 2);
3287 unsigned rx
= extract32(insn
, 16, 5);
3288 unsigned rb
= extract32(insn
, 21, 5);
3289 unsigned rt
= t1
* 32 + t0
;
3290 int modify
= (m
? (ua
? -1 : 1) : 0);
3294 scale
= (ua
? 2 : 0);
3298 disp
= low_sextract(rx
, 0, 5);
3301 modify
= (m
? (ua
? -1 : 1) : 0);
3306 return do_floadw(ctx
, rt
, rb
, rx
, scale
, disp
, sp
, modify
);
3308 return do_fstorew(ctx
, rt
, rb
, rx
, scale
, disp
, sp
, modify
);
3310 return gen_illegal(ctx
);
3313 static DisasJumpType
trans_copr_dw(DisasContext
*ctx
, uint32_t insn
)
3315 unsigned rt
= extract32(insn
, 0, 5);
3316 unsigned m
= extract32(insn
, 5, 1);
3317 unsigned ext4
= extract32(insn
, 6, 4);
3318 /* unsigned cc = extract32(insn, 10, 2); */
3319 unsigned i
= extract32(insn
, 12, 1);
3320 unsigned ua
= extract32(insn
, 13, 1);
3321 unsigned sp
= extract32(insn
, 14, 2);
3322 unsigned rx
= extract32(insn
, 16, 5);
3323 unsigned rb
= extract32(insn
, 21, 5);
3324 int modify
= (m
? (ua
? -1 : 1) : 0);
3328 scale
= (ua
? 3 : 0);
3332 disp
= low_sextract(rx
, 0, 5);
3335 modify
= (m
? (ua
? -1 : 1) : 0);
3340 return do_floadd(ctx
, rt
, rb
, rx
, scale
, disp
, sp
, modify
);
3342 return do_fstored(ctx
, rt
, rb
, rx
, scale
, disp
, sp
, modify
);
3344 return gen_illegal(ctx
);
3348 static DisasJumpType
trans_cmpb(DisasContext
*ctx
, uint32_t insn
,
3349 bool is_true
, bool is_imm
, bool is_dw
)
3351 target_sreg disp
= assemble_12(insn
) * 4;
3352 unsigned n
= extract32(insn
, 1, 1);
3353 unsigned c
= extract32(insn
, 13, 3);
3354 unsigned r
= extract32(insn
, 21, 5);
3355 unsigned cf
= c
* 2 + !is_true
;
3356 TCGv_reg dest
, in1
, in2
, sv
;
3362 in1
= load_const(ctx
, low_sextract(insn
, 16, 5));
3364 in1
= load_gpr(ctx
, extract32(insn
, 16, 5));
3366 in2
= load_gpr(ctx
, r
);
3367 dest
= get_temp(ctx
);
3369 tcg_gen_sub_reg(dest
, in1
, in2
);
3373 sv
= do_sub_sv(ctx
, dest
, in1
, in2
);
3376 cond
= do_sub_cond(cf
, dest
, in1
, in2
, sv
);
3377 return do_cbranch(ctx
, disp
, n
, &cond
);
3380 static DisasJumpType
trans_addb(DisasContext
*ctx
, uint32_t insn
,
3381 bool is_true
, bool is_imm
)
3383 target_sreg disp
= assemble_12(insn
) * 4;
3384 unsigned n
= extract32(insn
, 1, 1);
3385 unsigned c
= extract32(insn
, 13, 3);
3386 unsigned r
= extract32(insn
, 21, 5);
3387 unsigned cf
= c
* 2 + !is_true
;
3388 TCGv_reg dest
, in1
, in2
, sv
, cb_msb
;
3394 in1
= load_const(ctx
, low_sextract(insn
, 16, 5));
3396 in1
= load_gpr(ctx
, extract32(insn
, 16, 5));
3398 in2
= load_gpr(ctx
, r
);
3399 dest
= dest_gpr(ctx
, r
);
3405 tcg_gen_add_reg(dest
, in1
, in2
);
3408 cb_msb
= get_temp(ctx
);
3409 tcg_gen_movi_reg(cb_msb
, 0);
3410 tcg_gen_add2_reg(dest
, cb_msb
, in1
, cb_msb
, in2
, cb_msb
);
3413 tcg_gen_add_reg(dest
, in1
, in2
);
3414 sv
= do_add_sv(ctx
, dest
, in1
, in2
);
3418 cond
= do_cond(cf
, dest
, cb_msb
, sv
);
3419 return do_cbranch(ctx
, disp
, n
, &cond
);
3422 static DisasJumpType
trans_bb(DisasContext
*ctx
, uint32_t insn
)
3424 target_sreg disp
= assemble_12(insn
) * 4;
3425 unsigned n
= extract32(insn
, 1, 1);
3426 unsigned c
= extract32(insn
, 15, 1);
3427 unsigned r
= extract32(insn
, 16, 5);
3428 unsigned p
= extract32(insn
, 21, 5);
3429 unsigned i
= extract32(insn
, 26, 1);
3430 TCGv_reg tmp
, tcg_r
;
3435 tmp
= tcg_temp_new();
3436 tcg_r
= load_gpr(ctx
, r
);
3438 tcg_gen_shli_reg(tmp
, tcg_r
, p
);
3440 tcg_gen_shl_reg(tmp
, tcg_r
, cpu_sar
);
3443 cond
= cond_make_0(c
? TCG_COND_GE
: TCG_COND_LT
, tmp
);
3445 return do_cbranch(ctx
, disp
, n
, &cond
);
3448 static DisasJumpType
trans_movb(DisasContext
*ctx
, uint32_t insn
, bool is_imm
)
3450 target_sreg disp
= assemble_12(insn
) * 4;
3451 unsigned n
= extract32(insn
, 1, 1);
3452 unsigned c
= extract32(insn
, 13, 3);
3453 unsigned t
= extract32(insn
, 16, 5);
3454 unsigned r
= extract32(insn
, 21, 5);
3460 dest
= dest_gpr(ctx
, r
);
3462 tcg_gen_movi_reg(dest
, low_sextract(t
, 0, 5));
3463 } else if (t
== 0) {
3464 tcg_gen_movi_reg(dest
, 0);
3466 tcg_gen_mov_reg(dest
, cpu_gr
[t
]);
3469 cond
= do_sed_cond(c
, dest
);
3470 return do_cbranch(ctx
, disp
, n
, &cond
);
3473 static DisasJumpType
trans_shrpw_sar(DisasContext
*ctx
, uint32_t insn
,
3474 const DisasInsn
*di
)
3476 unsigned rt
= extract32(insn
, 0, 5);
3477 unsigned c
= extract32(insn
, 13, 3);
3478 unsigned r1
= extract32(insn
, 16, 5);
3479 unsigned r2
= extract32(insn
, 21, 5);
3486 dest
= dest_gpr(ctx
, rt
);
3488 tcg_gen_ext32u_reg(dest
, load_gpr(ctx
, r2
));
3489 tcg_gen_shr_reg(dest
, dest
, cpu_sar
);
3490 } else if (r1
== r2
) {
3491 TCGv_i32 t32
= tcg_temp_new_i32();
3492 tcg_gen_trunc_reg_i32(t32
, load_gpr(ctx
, r2
));
3493 tcg_gen_rotr_i32(t32
, t32
, cpu_sar
);
3494 tcg_gen_extu_i32_reg(dest
, t32
);
3495 tcg_temp_free_i32(t32
);
3497 TCGv_i64 t
= tcg_temp_new_i64();
3498 TCGv_i64 s
= tcg_temp_new_i64();
3500 tcg_gen_concat_reg_i64(t
, load_gpr(ctx
, r2
), load_gpr(ctx
, r1
));
3501 tcg_gen_extu_reg_i64(s
, cpu_sar
);
3502 tcg_gen_shr_i64(t
, t
, s
);
3503 tcg_gen_trunc_i64_reg(dest
, t
);
3505 tcg_temp_free_i64(t
);
3506 tcg_temp_free_i64(s
);
3508 save_gpr(ctx
, rt
, dest
);
3510 /* Install the new nullification. */
3511 cond_free(&ctx
->null_cond
);
3513 ctx
->null_cond
= do_sed_cond(c
, dest
);
3515 return nullify_end(ctx
, DISAS_NEXT
);
3518 static DisasJumpType
trans_shrpw_imm(DisasContext
*ctx
, uint32_t insn
,
3519 const DisasInsn
*di
)
3521 unsigned rt
= extract32(insn
, 0, 5);
3522 unsigned cpos
= extract32(insn
, 5, 5);
3523 unsigned c
= extract32(insn
, 13, 3);
3524 unsigned r1
= extract32(insn
, 16, 5);
3525 unsigned r2
= extract32(insn
, 21, 5);
3526 unsigned sa
= 31 - cpos
;
3533 dest
= dest_gpr(ctx
, rt
);
3534 t2
= load_gpr(ctx
, r2
);
3536 TCGv_i32 t32
= tcg_temp_new_i32();
3537 tcg_gen_trunc_reg_i32(t32
, t2
);
3538 tcg_gen_rotri_i32(t32
, t32
, sa
);
3539 tcg_gen_extu_i32_reg(dest
, t32
);
3540 tcg_temp_free_i32(t32
);
3541 } else if (r1
== 0) {
3542 tcg_gen_extract_reg(dest
, t2
, sa
, 32 - sa
);
3544 TCGv_reg t0
= tcg_temp_new();
3545 tcg_gen_extract_reg(t0
, t2
, sa
, 32 - sa
);
3546 tcg_gen_deposit_reg(dest
, t0
, cpu_gr
[r1
], 32 - sa
, sa
);
3549 save_gpr(ctx
, rt
, dest
);
3551 /* Install the new nullification. */
3552 cond_free(&ctx
->null_cond
);
3554 ctx
->null_cond
= do_sed_cond(c
, dest
);
3556 return nullify_end(ctx
, DISAS_NEXT
);
3559 static DisasJumpType
trans_extrw_sar(DisasContext
*ctx
, uint32_t insn
,
3560 const DisasInsn
*di
)
3562 unsigned clen
= extract32(insn
, 0, 5);
3563 unsigned is_se
= extract32(insn
, 10, 1);
3564 unsigned c
= extract32(insn
, 13, 3);
3565 unsigned rt
= extract32(insn
, 16, 5);
3566 unsigned rr
= extract32(insn
, 21, 5);
3567 unsigned len
= 32 - clen
;
3568 TCGv_reg dest
, src
, tmp
;
3574 dest
= dest_gpr(ctx
, rt
);
3575 src
= load_gpr(ctx
, rr
);
3576 tmp
= tcg_temp_new();
3578 /* Recall that SAR is using big-endian bit numbering. */
3579 tcg_gen_xori_reg(tmp
, cpu_sar
, TARGET_REGISTER_BITS
- 1);
3581 tcg_gen_sar_reg(dest
, src
, tmp
);
3582 tcg_gen_sextract_reg(dest
, dest
, 0, len
);
3584 tcg_gen_shr_reg(dest
, src
, tmp
);
3585 tcg_gen_extract_reg(dest
, dest
, 0, len
);
3588 save_gpr(ctx
, rt
, dest
);
3590 /* Install the new nullification. */
3591 cond_free(&ctx
->null_cond
);
3593 ctx
->null_cond
= do_sed_cond(c
, dest
);
3595 return nullify_end(ctx
, DISAS_NEXT
);
3598 static DisasJumpType
trans_extrw_imm(DisasContext
*ctx
, uint32_t insn
,
3599 const DisasInsn
*di
)
3601 unsigned clen
= extract32(insn
, 0, 5);
3602 unsigned pos
= extract32(insn
, 5, 5);
3603 unsigned is_se
= extract32(insn
, 10, 1);
3604 unsigned c
= extract32(insn
, 13, 3);
3605 unsigned rt
= extract32(insn
, 16, 5);
3606 unsigned rr
= extract32(insn
, 21, 5);
3607 unsigned len
= 32 - clen
;
3608 unsigned cpos
= 31 - pos
;
3615 dest
= dest_gpr(ctx
, rt
);
3616 src
= load_gpr(ctx
, rr
);
3618 tcg_gen_sextract_reg(dest
, src
, cpos
, len
);
3620 tcg_gen_extract_reg(dest
, src
, cpos
, len
);
3622 save_gpr(ctx
, rt
, dest
);
3624 /* Install the new nullification. */
3625 cond_free(&ctx
->null_cond
);
3627 ctx
->null_cond
= do_sed_cond(c
, dest
);
3629 return nullify_end(ctx
, DISAS_NEXT
);
3632 static const DisasInsn table_sh_ex
[] = {
3633 { 0xd0000000u
, 0xfc001fe0u
, trans_shrpw_sar
},
3634 { 0xd0000800u
, 0xfc001c00u
, trans_shrpw_imm
},
3635 { 0xd0001000u
, 0xfc001be0u
, trans_extrw_sar
},
3636 { 0xd0001800u
, 0xfc001800u
, trans_extrw_imm
},
3639 static DisasJumpType
trans_depw_imm_c(DisasContext
*ctx
, uint32_t insn
,
3640 const DisasInsn
*di
)
3642 unsigned clen
= extract32(insn
, 0, 5);
3643 unsigned cpos
= extract32(insn
, 5, 5);
3644 unsigned nz
= extract32(insn
, 10, 1);
3645 unsigned c
= extract32(insn
, 13, 3);
3646 target_sreg val
= low_sextract(insn
, 16, 5);
3647 unsigned rt
= extract32(insn
, 21, 5);
3648 unsigned len
= 32 - clen
;
3649 target_sreg mask0
, mask1
;
3655 if (cpos
+ len
> 32) {
3659 dest
= dest_gpr(ctx
, rt
);
3660 mask0
= deposit64(0, cpos
, len
, val
);
3661 mask1
= deposit64(-1, cpos
, len
, val
);
3664 TCGv_reg src
= load_gpr(ctx
, rt
);
3666 tcg_gen_andi_reg(dest
, src
, mask1
);
3669 tcg_gen_ori_reg(dest
, src
, mask0
);
3671 tcg_gen_movi_reg(dest
, mask0
);
3673 save_gpr(ctx
, rt
, dest
);
3675 /* Install the new nullification. */
3676 cond_free(&ctx
->null_cond
);
3678 ctx
->null_cond
= do_sed_cond(c
, dest
);
3680 return nullify_end(ctx
, DISAS_NEXT
);
3683 static DisasJumpType
trans_depw_imm(DisasContext
*ctx
, uint32_t insn
,
3684 const DisasInsn
*di
)
3686 unsigned clen
= extract32(insn
, 0, 5);
3687 unsigned cpos
= extract32(insn
, 5, 5);
3688 unsigned nz
= extract32(insn
, 10, 1);
3689 unsigned c
= extract32(insn
, 13, 3);
3690 unsigned rr
= extract32(insn
, 16, 5);
3691 unsigned rt
= extract32(insn
, 21, 5);
3692 unsigned rs
= nz
? rt
: 0;
3693 unsigned len
= 32 - clen
;
3699 if (cpos
+ len
> 32) {
3703 dest
= dest_gpr(ctx
, rt
);
3704 val
= load_gpr(ctx
, rr
);
3706 tcg_gen_deposit_z_reg(dest
, val
, cpos
, len
);
3708 tcg_gen_deposit_reg(dest
, cpu_gr
[rs
], val
, cpos
, len
);
3710 save_gpr(ctx
, rt
, dest
);
3712 /* Install the new nullification. */
3713 cond_free(&ctx
->null_cond
);
3715 ctx
->null_cond
= do_sed_cond(c
, dest
);
3717 return nullify_end(ctx
, DISAS_NEXT
);
3720 static DisasJumpType
trans_depw_sar(DisasContext
*ctx
, uint32_t insn
,
3721 const DisasInsn
*di
)
3723 unsigned clen
= extract32(insn
, 0, 5);
3724 unsigned nz
= extract32(insn
, 10, 1);
3725 unsigned i
= extract32(insn
, 12, 1);
3726 unsigned c
= extract32(insn
, 13, 3);
3727 unsigned rt
= extract32(insn
, 21, 5);
3728 unsigned rs
= nz
? rt
: 0;
3729 unsigned len
= 32 - clen
;
3730 TCGv_reg val
, mask
, tmp
, shift
, dest
;
3731 unsigned msb
= 1U << (len
- 1);
3738 val
= load_const(ctx
, low_sextract(insn
, 16, 5));
3740 val
= load_gpr(ctx
, extract32(insn
, 16, 5));
3742 dest
= dest_gpr(ctx
, rt
);
3743 shift
= tcg_temp_new();
3744 tmp
= tcg_temp_new();
3746 /* Convert big-endian bit numbering in SAR to left-shift. */
3747 tcg_gen_xori_reg(shift
, cpu_sar
, TARGET_REGISTER_BITS
- 1);
3749 mask
= tcg_const_reg(msb
+ (msb
- 1));
3750 tcg_gen_and_reg(tmp
, val
, mask
);
3752 tcg_gen_shl_reg(mask
, mask
, shift
);
3753 tcg_gen_shl_reg(tmp
, tmp
, shift
);
3754 tcg_gen_andc_reg(dest
, cpu_gr
[rs
], mask
);
3755 tcg_gen_or_reg(dest
, dest
, tmp
);
3757 tcg_gen_shl_reg(dest
, tmp
, shift
);
3759 tcg_temp_free(shift
);
3760 tcg_temp_free(mask
);
3762 save_gpr(ctx
, rt
, dest
);
3764 /* Install the new nullification. */
3765 cond_free(&ctx
->null_cond
);
3767 ctx
->null_cond
= do_sed_cond(c
, dest
);
3769 return nullify_end(ctx
, DISAS_NEXT
);
3772 static const DisasInsn table_depw
[] = {
3773 { 0xd4000000u
, 0xfc000be0u
, trans_depw_sar
},
3774 { 0xd4000800u
, 0xfc001800u
, trans_depw_imm
},
3775 { 0xd4001800u
, 0xfc001800u
, trans_depw_imm_c
},
3778 static DisasJumpType
trans_be(DisasContext
*ctx
, uint32_t insn
, bool is_l
)
3780 unsigned n
= extract32(insn
, 1, 1);
3781 unsigned b
= extract32(insn
, 21, 5);
3782 target_sreg disp
= assemble_17(insn
);
3785 #ifdef CONFIG_USER_ONLY
3786 /* ??? It seems like there should be a good way of using
3787 "be disp(sr2, r0)", the canonical gateway entry mechanism
3788 to our advantage. But that appears to be inconvenient to
3789 manage along side branch delay slots. Therefore we handle
3790 entry into the gateway page via absolute address. */
3791 /* Since we don't implement spaces, just branch. Do notice the special
3792 case of "be disp(*,r0)" using a direct branch to disp, so that we can
3793 goto_tb to the TB containing the syscall. */
3795 return do_dbranch(ctx
, disp
, is_l
? 31 : 0, n
);
3798 int sp
= assemble_sr3(insn
);
3802 tmp
= get_temp(ctx
);
3803 tcg_gen_addi_reg(tmp
, load_gpr(ctx
, b
), disp
);
3804 tmp
= do_ibranch_priv(ctx
, tmp
);
3806 #ifdef CONFIG_USER_ONLY
3807 return do_ibranch(ctx
, tmp
, is_l
? 31 : 0, n
);
3809 TCGv_i64 new_spc
= tcg_temp_new_i64();
3811 load_spr(ctx
, new_spc
, sp
);
3813 copy_iaoq_entry(cpu_gr
[31], ctx
->iaoq_n
, ctx
->iaoq_n_var
);
3814 tcg_gen_mov_i64(cpu_sr
[0], cpu_iasq_f
);
3816 if (n
&& use_nullify_skip(ctx
)) {
3817 tcg_gen_mov_reg(cpu_iaoq_f
, tmp
);
3818 tcg_gen_addi_reg(cpu_iaoq_b
, cpu_iaoq_f
, 4);
3819 tcg_gen_mov_i64(cpu_iasq_f
, new_spc
);
3820 tcg_gen_mov_i64(cpu_iasq_b
, cpu_iasq_f
);
3822 copy_iaoq_entry(cpu_iaoq_f
, ctx
->iaoq_b
, cpu_iaoq_b
);
3823 if (ctx
->iaoq_b
== -1) {
3824 tcg_gen_mov_i64(cpu_iasq_f
, cpu_iasq_b
);
3826 tcg_gen_mov_reg(cpu_iaoq_b
, tmp
);
3827 tcg_gen_mov_i64(cpu_iasq_b
, new_spc
);
3828 nullify_set(ctx
, n
);
3830 tcg_temp_free_i64(new_spc
);
3831 tcg_gen_lookup_and_goto_ptr();
3832 return nullify_end(ctx
, DISAS_NORETURN
);
3836 static DisasJumpType
trans_bl(DisasContext
*ctx
, uint32_t insn
,
3837 const DisasInsn
*di
)
3839 unsigned n
= extract32(insn
, 1, 1);
3840 unsigned link
= extract32(insn
, 21, 5);
3841 target_sreg disp
= assemble_17(insn
);
3843 return do_dbranch(ctx
, iaoq_dest(ctx
, disp
), link
, n
);
3846 static DisasJumpType
trans_b_gate(DisasContext
*ctx
, uint32_t insn
,
3847 const DisasInsn
*di
)
3849 unsigned n
= extract32(insn
, 1, 1);
3850 unsigned link
= extract32(insn
, 21, 5);
3851 target_sreg disp
= assemble_17(insn
);
3852 target_ureg dest
= iaoq_dest(ctx
, disp
);
3854 /* Make sure the caller hasn't done something weird with the queue.
3855 * ??? This is not quite the same as the PSW[B] bit, which would be
3856 * expensive to track. Real hardware will trap for
3858 * b gateway+4 (in delay slot of first branch)
3859 * However, checking for a non-sequential instruction queue *will*
3860 * diagnose the security hole
3863 * in which instructions at evil would run with increased privs.
3865 if (ctx
->iaoq_b
== -1 || ctx
->iaoq_b
!= ctx
->iaoq_f
+ 4) {
3866 return gen_illegal(ctx
);
3869 #ifndef CONFIG_USER_ONLY
3870 if (ctx
->tb_flags
& PSW_C
) {
3871 CPUHPPAState
*env
= ctx
->cs
->env_ptr
;
3872 int type
= hppa_artype_for_page(env
, ctx
->base
.pc_next
);
3873 /* If we could not find a TLB entry, then we need to generate an
3874 ITLB miss exception so the kernel will provide it.
3875 The resulting TLB fill operation will invalidate this TB and
3876 we will re-translate, at which point we *will* be able to find
3877 the TLB entry and determine if this is in fact a gateway page. */
3879 return gen_excp(ctx
, EXCP_ITLB_MISS
);
3881 /* No change for non-gateway pages or for priv decrease. */
3882 if (type
>= 4 && type
- 4 < ctx
->privilege
) {
3883 dest
= deposit32(dest
, 0, 2, type
- 4);
3886 dest
&= -4; /* priv = 0 */
3890 return do_dbranch(ctx
, dest
, link
, n
);
3893 static DisasJumpType
trans_bl_long(DisasContext
*ctx
, uint32_t insn
,
3894 const DisasInsn
*di
)
3896 unsigned n
= extract32(insn
, 1, 1);
3897 target_sreg disp
= assemble_22(insn
);
3899 return do_dbranch(ctx
, iaoq_dest(ctx
, disp
), 2, n
);
3902 static DisasJumpType
trans_blr(DisasContext
*ctx
, uint32_t insn
,
3903 const DisasInsn
*di
)
3905 unsigned n
= extract32(insn
, 1, 1);
3906 unsigned rx
= extract32(insn
, 16, 5);
3907 unsigned link
= extract32(insn
, 21, 5);
3908 TCGv_reg tmp
= get_temp(ctx
);
3910 tcg_gen_shli_reg(tmp
, load_gpr(ctx
, rx
), 3);
3911 tcg_gen_addi_reg(tmp
, tmp
, ctx
->iaoq_f
+ 8);
3912 /* The computation here never changes privilege level. */
3913 return do_ibranch(ctx
, tmp
, link
, n
);
3916 static DisasJumpType
trans_bv(DisasContext
*ctx
, uint32_t insn
,
3917 const DisasInsn
*di
)
3919 unsigned n
= extract32(insn
, 1, 1);
3920 unsigned rx
= extract32(insn
, 16, 5);
3921 unsigned rb
= extract32(insn
, 21, 5);
3925 dest
= load_gpr(ctx
, rb
);
3927 dest
= get_temp(ctx
);
3928 tcg_gen_shli_reg(dest
, load_gpr(ctx
, rx
), 3);
3929 tcg_gen_add_reg(dest
, dest
, load_gpr(ctx
, rb
));
3931 dest
= do_ibranch_priv(ctx
, dest
);
3932 return do_ibranch(ctx
, dest
, 0, n
);
3935 static DisasJumpType
trans_bve(DisasContext
*ctx
, uint32_t insn
,
3936 const DisasInsn
*di
)
3938 unsigned n
= extract32(insn
, 1, 1);
3939 unsigned rb
= extract32(insn
, 21, 5);
3940 unsigned link
= extract32(insn
, 13, 1) ? 2 : 0;
3943 #ifdef CONFIG_USER_ONLY
3944 dest
= do_ibranch_priv(ctx
, load_gpr(ctx
, rb
));
3945 return do_ibranch(ctx
, dest
, link
, n
);
3948 dest
= do_ibranch_priv(ctx
, load_gpr(ctx
, rb
));
3950 copy_iaoq_entry(cpu_iaoq_f
, ctx
->iaoq_b
, cpu_iaoq_b
);
3951 if (ctx
->iaoq_b
== -1) {
3952 tcg_gen_mov_i64(cpu_iasq_f
, cpu_iasq_b
);
3954 copy_iaoq_entry(cpu_iaoq_b
, -1, dest
);
3955 tcg_gen_mov_i64(cpu_iasq_b
, space_select(ctx
, 0, dest
));
3957 copy_iaoq_entry(cpu_gr
[link
], ctx
->iaoq_n
, ctx
->iaoq_n_var
);
3959 nullify_set(ctx
, n
);
3960 tcg_gen_lookup_and_goto_ptr();
3961 return nullify_end(ctx
, DISAS_NORETURN
);
3965 static const DisasInsn table_branch
[] = {
3966 { 0xe8000000u
, 0xfc006000u
, trans_bl
}, /* B,L and B,L,PUSH */
3967 { 0xe800a000u
, 0xfc00e000u
, trans_bl_long
},
3968 { 0xe8004000u
, 0xfc00fffdu
, trans_blr
},
3969 { 0xe800c000u
, 0xfc00fffdu
, trans_bv
},
3970 { 0xe800d000u
, 0xfc00dffcu
, trans_bve
},
3971 { 0xe8002000u
, 0xfc00e000u
, trans_b_gate
},
3974 static DisasJumpType
trans_fop_wew_0c(DisasContext
*ctx
, uint32_t insn
,
3975 const DisasInsn
*di
)
3977 unsigned rt
= extract32(insn
, 0, 5);
3978 unsigned ra
= extract32(insn
, 21, 5);
3979 return do_fop_wew(ctx
, rt
, ra
, di
->f
.wew
);
3982 static DisasJumpType
trans_fop_wew_0e(DisasContext
*ctx
, uint32_t insn
,
3983 const DisasInsn
*di
)
3985 unsigned rt
= assemble_rt64(insn
);
3986 unsigned ra
= assemble_ra64(insn
);
3987 return do_fop_wew(ctx
, rt
, ra
, di
->f
.wew
);
3990 static DisasJumpType
trans_fop_ded(DisasContext
*ctx
, uint32_t insn
,
3991 const DisasInsn
*di
)
3993 unsigned rt
= extract32(insn
, 0, 5);
3994 unsigned ra
= extract32(insn
, 21, 5);
3995 return do_fop_ded(ctx
, rt
, ra
, di
->f
.ded
);
3998 static DisasJumpType
trans_fop_wed_0c(DisasContext
*ctx
, uint32_t insn
,
3999 const DisasInsn
*di
)
4001 unsigned rt
= extract32(insn
, 0, 5);
4002 unsigned ra
= extract32(insn
, 21, 5);
4003 return do_fop_wed(ctx
, rt
, ra
, di
->f
.wed
);
4006 static DisasJumpType
trans_fop_wed_0e(DisasContext
*ctx
, uint32_t insn
,
4007 const DisasInsn
*di
)
4009 unsigned rt
= assemble_rt64(insn
);
4010 unsigned ra
= extract32(insn
, 21, 5);
4011 return do_fop_wed(ctx
, rt
, ra
, di
->f
.wed
);
4014 static DisasJumpType
trans_fop_dew_0c(DisasContext
*ctx
, uint32_t insn
,
4015 const DisasInsn
*di
)
4017 unsigned rt
= extract32(insn
, 0, 5);
4018 unsigned ra
= extract32(insn
, 21, 5);
4019 return do_fop_dew(ctx
, rt
, ra
, di
->f
.dew
);
4022 static DisasJumpType
trans_fop_dew_0e(DisasContext
*ctx
, uint32_t insn
,
4023 const DisasInsn
*di
)
4025 unsigned rt
= extract32(insn
, 0, 5);
4026 unsigned ra
= assemble_ra64(insn
);
4027 return do_fop_dew(ctx
, rt
, ra
, di
->f
.dew
);
4030 static DisasJumpType
trans_fop_weww_0c(DisasContext
*ctx
, uint32_t insn
,
4031 const DisasInsn
*di
)
4033 unsigned rt
= extract32(insn
, 0, 5);
4034 unsigned rb
= extract32(insn
, 16, 5);
4035 unsigned ra
= extract32(insn
, 21, 5);
4036 return do_fop_weww(ctx
, rt
, ra
, rb
, di
->f
.weww
);
4039 static DisasJumpType
trans_fop_weww_0e(DisasContext
*ctx
, uint32_t insn
,
4040 const DisasInsn
*di
)
4042 unsigned rt
= assemble_rt64(insn
);
4043 unsigned rb
= assemble_rb64(insn
);
4044 unsigned ra
= assemble_ra64(insn
);
4045 return do_fop_weww(ctx
, rt
, ra
, rb
, di
->f
.weww
);
4048 static DisasJumpType
trans_fop_dedd(DisasContext
*ctx
, uint32_t insn
,
4049 const DisasInsn
*di
)
4051 unsigned rt
= extract32(insn
, 0, 5);
4052 unsigned rb
= extract32(insn
, 16, 5);
4053 unsigned ra
= extract32(insn
, 21, 5);
4054 return do_fop_dedd(ctx
, rt
, ra
, rb
, di
->f
.dedd
);
4057 static void gen_fcpy_s(TCGv_i32 dst
, TCGv_env unused
, TCGv_i32 src
)
4059 tcg_gen_mov_i32(dst
, src
);
4062 static void gen_fcpy_d(TCGv_i64 dst
, TCGv_env unused
, TCGv_i64 src
)
4064 tcg_gen_mov_i64(dst
, src
);
4067 static void gen_fabs_s(TCGv_i32 dst
, TCGv_env unused
, TCGv_i32 src
)
4069 tcg_gen_andi_i32(dst
, src
, INT32_MAX
);
4072 static void gen_fabs_d(TCGv_i64 dst
, TCGv_env unused
, TCGv_i64 src
)
4074 tcg_gen_andi_i64(dst
, src
, INT64_MAX
);
4077 static void gen_fneg_s(TCGv_i32 dst
, TCGv_env unused
, TCGv_i32 src
)
4079 tcg_gen_xori_i32(dst
, src
, INT32_MIN
);
4082 static void gen_fneg_d(TCGv_i64 dst
, TCGv_env unused
, TCGv_i64 src
)
4084 tcg_gen_xori_i64(dst
, src
, INT64_MIN
);
4087 static void gen_fnegabs_s(TCGv_i32 dst
, TCGv_env unused
, TCGv_i32 src
)
4089 tcg_gen_ori_i32(dst
, src
, INT32_MIN
);
4092 static void gen_fnegabs_d(TCGv_i64 dst
, TCGv_env unused
, TCGv_i64 src
)
4094 tcg_gen_ori_i64(dst
, src
, INT64_MIN
);
4097 static DisasJumpType
do_fcmp_s(DisasContext
*ctx
, unsigned ra
, unsigned rb
,
4098 unsigned y
, unsigned c
)
4100 TCGv_i32 ta
, tb
, tc
, ty
;
4104 ta
= load_frw0_i32(ra
);
4105 tb
= load_frw0_i32(rb
);
4106 ty
= tcg_const_i32(y
);
4107 tc
= tcg_const_i32(c
);
4109 gen_helper_fcmp_s(cpu_env
, ta
, tb
, ty
, tc
);
4111 tcg_temp_free_i32(ta
);
4112 tcg_temp_free_i32(tb
);
4113 tcg_temp_free_i32(ty
);
4114 tcg_temp_free_i32(tc
);
4116 return nullify_end(ctx
, DISAS_NEXT
);
4119 static DisasJumpType
trans_fcmp_s_0c(DisasContext
*ctx
, uint32_t insn
,
4120 const DisasInsn
*di
)
4122 unsigned c
= extract32(insn
, 0, 5);
4123 unsigned y
= extract32(insn
, 13, 3);
4124 unsigned rb
= extract32(insn
, 16, 5);
4125 unsigned ra
= extract32(insn
, 21, 5);
4126 return do_fcmp_s(ctx
, ra
, rb
, y
, c
);
4129 static DisasJumpType
trans_fcmp_s_0e(DisasContext
*ctx
, uint32_t insn
,
4130 const DisasInsn
*di
)
4132 unsigned c
= extract32(insn
, 0, 5);
4133 unsigned y
= extract32(insn
, 13, 3);
4134 unsigned rb
= assemble_rb64(insn
);
4135 unsigned ra
= assemble_ra64(insn
);
4136 return do_fcmp_s(ctx
, ra
, rb
, y
, c
);
4139 static DisasJumpType
trans_fcmp_d(DisasContext
*ctx
, uint32_t insn
,
4140 const DisasInsn
*di
)
4142 unsigned c
= extract32(insn
, 0, 5);
4143 unsigned y
= extract32(insn
, 13, 3);
4144 unsigned rb
= extract32(insn
, 16, 5);
4145 unsigned ra
= extract32(insn
, 21, 5);
4153 ty
= tcg_const_i32(y
);
4154 tc
= tcg_const_i32(c
);
4156 gen_helper_fcmp_d(cpu_env
, ta
, tb
, ty
, tc
);
4158 tcg_temp_free_i64(ta
);
4159 tcg_temp_free_i64(tb
);
4160 tcg_temp_free_i32(ty
);
4161 tcg_temp_free_i32(tc
);
4163 return nullify_end(ctx
, DISAS_NEXT
);
4166 static DisasJumpType
trans_ftest_t(DisasContext
*ctx
, uint32_t insn
,
4167 const DisasInsn
*di
)
4169 unsigned y
= extract32(insn
, 13, 3);
4170 unsigned cbit
= (y
^ 1) - 1;
4176 tcg_gen_ld32u_reg(t
, cpu_env
, offsetof(CPUHPPAState
, fr0_shadow
));
4177 tcg_gen_extract_reg(t
, t
, 21 - cbit
, 1);
4178 ctx
->null_cond
= cond_make_0(TCG_COND_NE
, t
);
4181 return nullify_end(ctx
, DISAS_NEXT
);
4184 static DisasJumpType
trans_ftest_q(DisasContext
*ctx
, uint32_t insn
,
4185 const DisasInsn
*di
)
4187 unsigned c
= extract32(insn
, 0, 5);
4195 tcg_gen_ld32u_reg(t
, cpu_env
, offsetof(CPUHPPAState
, fr0_shadow
));
4198 case 0: /* simple */
4199 tcg_gen_andi_reg(t
, t
, 0x4000000);
4200 ctx
->null_cond
= cond_make_0(TCG_COND_NE
, t
);
4224 return gen_illegal(ctx
);
4227 TCGv_reg c
= load_const(ctx
, mask
);
4228 tcg_gen_or_reg(t
, t
, c
);
4229 ctx
->null_cond
= cond_make(TCG_COND_EQ
, t
, c
);
4231 tcg_gen_andi_reg(t
, t
, mask
);
4232 ctx
->null_cond
= cond_make_0(TCG_COND_EQ
, t
);
4235 return nullify_end(ctx
, DISAS_NEXT
);
4238 static DisasJumpType
trans_xmpyu(DisasContext
*ctx
, uint32_t insn
,
4239 const DisasInsn
*di
)
4241 unsigned rt
= extract32(insn
, 0, 5);
4242 unsigned rb
= assemble_rb64(insn
);
4243 unsigned ra
= assemble_ra64(insn
);
4248 a
= load_frw0_i64(ra
);
4249 b
= load_frw0_i64(rb
);
4250 tcg_gen_mul_i64(a
, a
, b
);
4252 tcg_temp_free_i64(a
);
4253 tcg_temp_free_i64(b
);
4255 return nullify_end(ctx
, DISAS_NEXT
);
4258 #define FOP_DED trans_fop_ded, .f.ded
4259 #define FOP_DEDD trans_fop_dedd, .f.dedd
4261 #define FOP_WEW trans_fop_wew_0c, .f.wew
4262 #define FOP_DEW trans_fop_dew_0c, .f.dew
4263 #define FOP_WED trans_fop_wed_0c, .f.wed
4264 #define FOP_WEWW trans_fop_weww_0c, .f.weww
4266 static const DisasInsn table_float_0c
[] = {
4267 /* floating point class zero */
4268 { 0x30004000, 0xfc1fffe0, FOP_WEW
= gen_fcpy_s
},
4269 { 0x30006000, 0xfc1fffe0, FOP_WEW
= gen_fabs_s
},
4270 { 0x30008000, 0xfc1fffe0, FOP_WEW
= gen_helper_fsqrt_s
},
4271 { 0x3000a000, 0xfc1fffe0, FOP_WEW
= gen_helper_frnd_s
},
4272 { 0x3000c000, 0xfc1fffe0, FOP_WEW
= gen_fneg_s
},
4273 { 0x3000e000, 0xfc1fffe0, FOP_WEW
= gen_fnegabs_s
},
4275 { 0x30004800, 0xfc1fffe0, FOP_DED
= gen_fcpy_d
},
4276 { 0x30006800, 0xfc1fffe0, FOP_DED
= gen_fabs_d
},
4277 { 0x30008800, 0xfc1fffe0, FOP_DED
= gen_helper_fsqrt_d
},
4278 { 0x3000a800, 0xfc1fffe0, FOP_DED
= gen_helper_frnd_d
},
4279 { 0x3000c800, 0xfc1fffe0, FOP_DED
= gen_fneg_d
},
4280 { 0x3000e800, 0xfc1fffe0, FOP_DED
= gen_fnegabs_d
},
4282 /* floating point class three */
4283 { 0x30000600, 0xfc00ffe0, FOP_WEWW
= gen_helper_fadd_s
},
4284 { 0x30002600, 0xfc00ffe0, FOP_WEWW
= gen_helper_fsub_s
},
4285 { 0x30004600, 0xfc00ffe0, FOP_WEWW
= gen_helper_fmpy_s
},
4286 { 0x30006600, 0xfc00ffe0, FOP_WEWW
= gen_helper_fdiv_s
},
4288 { 0x30000e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fadd_d
},
4289 { 0x30002e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fsub_d
},
4290 { 0x30004e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fmpy_d
},
4291 { 0x30006e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fdiv_d
},
4293 /* floating point class one */
4295 { 0x30000a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_d_s
},
4296 { 0x30002200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_s_d
},
4298 { 0x30008200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_w_s
},
4299 { 0x30008a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_dw_s
},
4300 { 0x3000a200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_w_d
},
4301 { 0x3000aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_dw_d
},
4303 { 0x30010200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_s_w
},
4304 { 0x30010a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_d_w
},
4305 { 0x30012200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_s_dw
},
4306 { 0x30012a00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_d_dw
},
4307 /* float/int truncate */
4308 { 0x30018200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_t_s_w
},
4309 { 0x30018a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_t_d_w
},
4310 { 0x3001a200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_t_s_dw
},
4311 { 0x3001aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_t_d_dw
},
4313 { 0x30028200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_uw_s
},
4314 { 0x30028a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_udw_s
},
4315 { 0x3002a200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_uw_d
},
4316 { 0x3002aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_udw_d
},
4318 { 0x30030200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_s_uw
},
4319 { 0x30030a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_d_uw
},
4320 { 0x30032200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_s_udw
},
4321 { 0x30032a00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_d_udw
},
4322 /* float/uint truncate */
4323 { 0x30038200, 0xfc1fffe0, FOP_WEW
= gen_helper_fcnv_t_s_uw
},
4324 { 0x30038a00, 0xfc1fffe0, FOP_WED
= gen_helper_fcnv_t_d_uw
},
4325 { 0x3003a200, 0xfc1fffe0, FOP_DEW
= gen_helper_fcnv_t_s_udw
},
4326 { 0x3003aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_t_d_udw
},
4328 /* floating point class two */
4329 { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c
},
4330 { 0x30000c00, 0xfc001fe0, trans_fcmp_d
},
4331 { 0x30002420, 0xffffffe0, trans_ftest_q
},
4332 { 0x30000420, 0xffff1fff, trans_ftest_t
},
4334 /* FID. Note that ra == rt == 0, which via fcpy puts 0 into fr0.
4335 This is machine/revision == 0, which is reserved for simulator. */
4336 { 0x30000000, 0xffffffff, FOP_WEW
= gen_fcpy_s
},
4343 #define FOP_WEW trans_fop_wew_0e, .f.wew
4344 #define FOP_DEW trans_fop_dew_0e, .f.dew
4345 #define FOP_WED trans_fop_wed_0e, .f.wed
4346 #define FOP_WEWW trans_fop_weww_0e, .f.weww
4348 static const DisasInsn table_float_0e
[] = {
4349 /* floating point class zero */
4350 { 0x38004000, 0xfc1fff20, FOP_WEW
= gen_fcpy_s
},
4351 { 0x38006000, 0xfc1fff20, FOP_WEW
= gen_fabs_s
},
4352 { 0x38008000, 0xfc1fff20, FOP_WEW
= gen_helper_fsqrt_s
},
4353 { 0x3800a000, 0xfc1fff20, FOP_WEW
= gen_helper_frnd_s
},
4354 { 0x3800c000, 0xfc1fff20, FOP_WEW
= gen_fneg_s
},
4355 { 0x3800e000, 0xfc1fff20, FOP_WEW
= gen_fnegabs_s
},
4357 { 0x38004800, 0xfc1fffe0, FOP_DED
= gen_fcpy_d
},
4358 { 0x38006800, 0xfc1fffe0, FOP_DED
= gen_fabs_d
},
4359 { 0x38008800, 0xfc1fffe0, FOP_DED
= gen_helper_fsqrt_d
},
4360 { 0x3800a800, 0xfc1fffe0, FOP_DED
= gen_helper_frnd_d
},
4361 { 0x3800c800, 0xfc1fffe0, FOP_DED
= gen_fneg_d
},
4362 { 0x3800e800, 0xfc1fffe0, FOP_DED
= gen_fnegabs_d
},
4364 /* floating point class three */
4365 { 0x38000600, 0xfc00ef20, FOP_WEWW
= gen_helper_fadd_s
},
4366 { 0x38002600, 0xfc00ef20, FOP_WEWW
= gen_helper_fsub_s
},
4367 { 0x38004600, 0xfc00ef20, FOP_WEWW
= gen_helper_fmpy_s
},
4368 { 0x38006600, 0xfc00ef20, FOP_WEWW
= gen_helper_fdiv_s
},
4370 { 0x38000e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fadd_d
},
4371 { 0x38002e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fsub_d
},
4372 { 0x38004e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fmpy_d
},
4373 { 0x38006e00, 0xfc00ffe0, FOP_DEDD
= gen_helper_fdiv_d
},
4375 { 0x38004700, 0xfc00ef60, trans_xmpyu
},
4377 /* floating point class one */
4379 { 0x38000a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_d_s
},
4380 { 0x38002200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_s_d
},
4382 { 0x38008200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_w_s
},
4383 { 0x38008a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_dw_s
},
4384 { 0x3800a200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_w_d
},
4385 { 0x3800aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_dw_d
},
4387 { 0x38010200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_s_w
},
4388 { 0x38010a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_d_w
},
4389 { 0x38012200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_s_dw
},
4390 { 0x38012a00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_d_dw
},
4391 /* float/int truncate */
4392 { 0x38018200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_t_s_w
},
4393 { 0x38018a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_t_d_w
},
4394 { 0x3801a200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_t_s_dw
},
4395 { 0x3801aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_t_d_dw
},
4397 { 0x38028200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_uw_s
},
4398 { 0x38028a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_udw_s
},
4399 { 0x3802a200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_uw_d
},
4400 { 0x3802aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_udw_d
},
4402 { 0x38030200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_s_uw
},
4403 { 0x38030a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_d_uw
},
4404 { 0x38032200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_s_udw
},
4405 { 0x38032a00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_d_udw
},
4406 /* float/uint truncate */
4407 { 0x38038200, 0xfc1ffe20, FOP_WEW
= gen_helper_fcnv_t_s_uw
},
4408 { 0x38038a00, 0xfc1fffa0, FOP_WED
= gen_helper_fcnv_t_d_uw
},
4409 { 0x3803a200, 0xfc1fff60, FOP_DEW
= gen_helper_fcnv_t_s_udw
},
4410 { 0x3803aa00, 0xfc1fffe0, FOP_DED
= gen_helper_fcnv_t_d_udw
},
4412 /* floating point class two */
4413 { 0x38000400, 0xfc000f60, trans_fcmp_s_0e
},
4414 { 0x38000c00, 0xfc001fe0, trans_fcmp_d
},
4424 /* Convert the fmpyadd single-precision register encodings to standard. */
4425 static inline int fmpyadd_s_reg(unsigned r
)
4427 return (r
& 16) * 2 + 16 + (r
& 15);
4430 static DisasJumpType
trans_fmpyadd(DisasContext
*ctx
,
4431 uint32_t insn
, bool is_sub
)
4433 unsigned tm
= extract32(insn
, 0, 5);
4434 unsigned f
= extract32(insn
, 5, 1);
4435 unsigned ra
= extract32(insn
, 6, 5);
4436 unsigned ta
= extract32(insn
, 11, 5);
4437 unsigned rm2
= extract32(insn
, 16, 5);
4438 unsigned rm1
= extract32(insn
, 21, 5);
4442 /* Independent multiply & add/sub, with undefined behaviour
4443 if outputs overlap inputs. */
4445 tm
= fmpyadd_s_reg(tm
);
4446 ra
= fmpyadd_s_reg(ra
);
4447 ta
= fmpyadd_s_reg(ta
);
4448 rm2
= fmpyadd_s_reg(rm2
);
4449 rm1
= fmpyadd_s_reg(rm1
);
4450 do_fop_weww(ctx
, tm
, rm1
, rm2
, gen_helper_fmpy_s
);
4451 do_fop_weww(ctx
, ta
, ta
, ra
,
4452 is_sub
? gen_helper_fsub_s
: gen_helper_fadd_s
);
4454 do_fop_dedd(ctx
, tm
, rm1
, rm2
, gen_helper_fmpy_d
);
4455 do_fop_dedd(ctx
, ta
, ta
, ra
,
4456 is_sub
? gen_helper_fsub_d
: gen_helper_fadd_d
);
4459 return nullify_end(ctx
, DISAS_NEXT
);
4462 static DisasJumpType
trans_fmpyfadd_s(DisasContext
*ctx
, uint32_t insn
,
4463 const DisasInsn
*di
)
4465 unsigned rt
= assemble_rt64(insn
);
4466 unsigned neg
= extract32(insn
, 5, 1);
4467 unsigned rm1
= assemble_ra64(insn
);
4468 unsigned rm2
= assemble_rb64(insn
);
4469 unsigned ra3
= assemble_rc64(insn
);
4473 a
= load_frw0_i32(rm1
);
4474 b
= load_frw0_i32(rm2
);
4475 c
= load_frw0_i32(ra3
);
4478 gen_helper_fmpynfadd_s(a
, cpu_env
, a
, b
, c
);
4480 gen_helper_fmpyfadd_s(a
, cpu_env
, a
, b
, c
);
4483 tcg_temp_free_i32(b
);
4484 tcg_temp_free_i32(c
);
4485 save_frw_i32(rt
, a
);
4486 tcg_temp_free_i32(a
);
4487 return nullify_end(ctx
, DISAS_NEXT
);
4490 static DisasJumpType
trans_fmpyfadd_d(DisasContext
*ctx
, uint32_t insn
,
4491 const DisasInsn
*di
)
4493 unsigned rt
= extract32(insn
, 0, 5);
4494 unsigned neg
= extract32(insn
, 5, 1);
4495 unsigned rm1
= extract32(insn
, 21, 5);
4496 unsigned rm2
= extract32(insn
, 16, 5);
4497 unsigned ra3
= assemble_rc64(insn
);
4506 gen_helper_fmpynfadd_d(a
, cpu_env
, a
, b
, c
);
4508 gen_helper_fmpyfadd_d(a
, cpu_env
, a
, b
, c
);
4511 tcg_temp_free_i64(b
);
4512 tcg_temp_free_i64(c
);
4514 tcg_temp_free_i64(a
);
4515 return nullify_end(ctx
, DISAS_NEXT
);
4518 static const DisasInsn table_fp_fused
[] = {
4519 { 0xb8000000u
, 0xfc000800u
, trans_fmpyfadd_s
},
4520 { 0xb8000800u
, 0xfc0019c0u
, trans_fmpyfadd_d
}
4523 static DisasJumpType
translate_table_int(DisasContext
*ctx
, uint32_t insn
,
4524 const DisasInsn table
[], size_t n
)
4527 for (i
= 0; i
< n
; ++i
) {
4528 if ((insn
& table
[i
].mask
) == table
[i
].insn
) {
4529 return table
[i
].trans(ctx
, insn
, &table
[i
]);
4532 qemu_log_mask(LOG_UNIMP
, "UNIMP insn %08x @ " TARGET_FMT_lx
"\n",
4533 insn
, ctx
->base
.pc_next
);
4534 return gen_illegal(ctx
);
4537 #define translate_table(ctx, insn, table) \
4538 translate_table_int(ctx, insn, table, ARRAY_SIZE(table))
4540 static DisasJumpType
translate_one(DisasContext
*ctx
, uint32_t insn
)
4542 uint32_t opc
= extract32(insn
, 26, 6);
4545 case 0x00: /* system op */
4546 return translate_table(ctx
, insn
, table_system
);
4548 return translate_table(ctx
, insn
, table_mem_mgmt
);
4550 return translate_table(ctx
, insn
, table_arith_log
);
4552 return translate_table(ctx
, insn
, table_index_mem
);
4554 return trans_fmpyadd(ctx
, insn
, false);
4556 return trans_ldil(ctx
, insn
);
4558 return trans_copr_w(ctx
, insn
);
4560 return trans_addil(ctx
, insn
);
4562 return trans_copr_dw(ctx
, insn
);
4564 return translate_table(ctx
, insn
, table_float_0c
);
4566 return trans_ldo(ctx
, insn
);
4568 return translate_table(ctx
, insn
, table_float_0e
);
4571 return trans_load(ctx
, insn
, false, MO_UB
);
4573 return trans_load(ctx
, insn
, false, MO_TEUW
);
4575 return trans_load(ctx
, insn
, false, MO_TEUL
);
4577 return trans_load(ctx
, insn
, true, MO_TEUL
);
4579 return trans_fload_mod(ctx
, insn
);
4581 return trans_load_w(ctx
, insn
);
4583 return trans_store(ctx
, insn
, false, MO_UB
);
4585 return trans_store(ctx
, insn
, false, MO_TEUW
);
4587 return trans_store(ctx
, insn
, false, MO_TEUL
);
4589 return trans_store(ctx
, insn
, true, MO_TEUL
);
4591 return trans_fstore_mod(ctx
, insn
);
4593 return trans_store_w(ctx
, insn
);
4596 return trans_cmpb(ctx
, insn
, true, false, false);
4598 return trans_cmpb(ctx
, insn
, true, true, false);
4600 return trans_cmpb(ctx
, insn
, false, false, false);
4602 return trans_cmpb(ctx
, insn
, false, true, false);
4604 return trans_cmpiclr(ctx
, insn
);
4606 return trans_subi(ctx
, insn
);
4608 return trans_fmpyadd(ctx
, insn
, true);
4610 return trans_cmpb(ctx
, insn
, true, false, true);
4612 return trans_addb(ctx
, insn
, true, false);
4614 return trans_addb(ctx
, insn
, true, true);
4616 return trans_addb(ctx
, insn
, false, false);
4618 return trans_addb(ctx
, insn
, false, true);
4621 return trans_addi(ctx
, insn
);
4623 return translate_table(ctx
, insn
, table_fp_fused
);
4625 return trans_cmpb(ctx
, insn
, false, false, true);
4629 return trans_bb(ctx
, insn
);
4631 return trans_movb(ctx
, insn
, false);
4633 return trans_movb(ctx
, insn
, true);
4635 return translate_table(ctx
, insn
, table_sh_ex
);
4637 return translate_table(ctx
, insn
, table_depw
);
4639 return trans_be(ctx
, insn
, false);
4641 return trans_be(ctx
, insn
, true);
4643 return translate_table(ctx
, insn
, table_branch
);
4645 case 0x04: /* spopn */
4646 case 0x05: /* diag */
4647 case 0x0F: /* product specific */
4650 case 0x07: /* unassigned */
4651 case 0x15: /* unassigned */
4652 case 0x1D: /* unassigned */
4653 case 0x37: /* unassigned */
4656 #ifndef CONFIG_USER_ONLY
4657 /* Unassigned, but use as system-halt. */
4658 if (insn
== 0xfffdead0) {
4659 return gen_hlt(ctx
, 0); /* halt system */
4661 if (insn
== 0xfffdead1) {
4662 return gen_hlt(ctx
, 1); /* reset system */
4669 return gen_illegal(ctx
);
4672 static void hppa_tr_init_disas_context(DisasContextBase
*dcbase
, CPUState
*cs
)
4674 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4678 ctx
->tb_flags
= ctx
->base
.tb
->flags
;
4680 #ifdef CONFIG_USER_ONLY
4681 ctx
->privilege
= MMU_USER_IDX
;
4682 ctx
->mmu_idx
= MMU_USER_IDX
;
4683 ctx
->iaoq_f
= ctx
->base
.pc_first
| MMU_USER_IDX
;
4684 ctx
->iaoq_b
= ctx
->base
.tb
->cs_base
| MMU_USER_IDX
;
4686 ctx
->privilege
= (ctx
->tb_flags
>> TB_FLAG_PRIV_SHIFT
) & 3;
4687 ctx
->mmu_idx
= (ctx
->tb_flags
& PSW_D
? ctx
->privilege
: MMU_PHYS_IDX
);
4689 /* Recover the IAOQ values from the GVA + PRIV. */
4690 uint64_t cs_base
= ctx
->base
.tb
->cs_base
;
4691 uint64_t iasq_f
= cs_base
& ~0xffffffffull
;
4692 int32_t diff
= cs_base
;
4694 ctx
->iaoq_f
= (ctx
->base
.pc_first
& ~iasq_f
) + ctx
->privilege
;
4695 ctx
->iaoq_b
= (diff
? ctx
->iaoq_f
+ diff
: -1);
4698 ctx
->iaoq_n_var
= NULL
;
4700 /* Bound the number of instructions by those left on the page. */
4701 bound
= -(ctx
->base
.pc_first
| TARGET_PAGE_MASK
) / 4;
4702 ctx
->base
.max_insns
= MIN(ctx
->base
.max_insns
, bound
);
4706 memset(ctx
->tempr
, 0, sizeof(ctx
->tempr
));
4707 memset(ctx
->templ
, 0, sizeof(ctx
->templ
));
4710 static void hppa_tr_tb_start(DisasContextBase
*dcbase
, CPUState
*cs
)
4712 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4714 /* Seed the nullification status from PSW[N], as saved in TB->FLAGS. */
4715 ctx
->null_cond
= cond_make_f();
4716 ctx
->psw_n_nonzero
= false;
4717 if (ctx
->tb_flags
& PSW_N
) {
4718 ctx
->null_cond
.c
= TCG_COND_ALWAYS
;
4719 ctx
->psw_n_nonzero
= true;
4721 ctx
->null_lab
= NULL
;
4724 static void hppa_tr_insn_start(DisasContextBase
*dcbase
, CPUState
*cs
)
4726 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4728 tcg_gen_insn_start(ctx
->iaoq_f
, ctx
->iaoq_b
);
4731 static bool hppa_tr_breakpoint_check(DisasContextBase
*dcbase
, CPUState
*cs
,
4732 const CPUBreakpoint
*bp
)
4734 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4736 ctx
->base
.is_jmp
= gen_excp(ctx
, EXCP_DEBUG
);
4737 ctx
->base
.pc_next
+= 4;
4741 static void hppa_tr_translate_insn(DisasContextBase
*dcbase
, CPUState
*cs
)
4743 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4744 CPUHPPAState
*env
= cs
->env_ptr
;
4748 /* Execute one insn. */
4749 #ifdef CONFIG_USER_ONLY
4750 if (ctx
->base
.pc_next
< TARGET_PAGE_SIZE
) {
4751 ret
= do_page_zero(ctx
);
4752 assert(ret
!= DISAS_NEXT
);
4756 /* Always fetch the insn, even if nullified, so that we check
4757 the page permissions for execute. */
4758 uint32_t insn
= cpu_ldl_code(env
, ctx
->base
.pc_next
);
4760 /* Set up the IA queue for the next insn.
4761 This will be overwritten by a branch. */
4762 if (ctx
->iaoq_b
== -1) {
4764 ctx
->iaoq_n_var
= get_temp(ctx
);
4765 tcg_gen_addi_reg(ctx
->iaoq_n_var
, cpu_iaoq_b
, 4);
4767 ctx
->iaoq_n
= ctx
->iaoq_b
+ 4;
4768 ctx
->iaoq_n_var
= NULL
;
4771 if (unlikely(ctx
->null_cond
.c
== TCG_COND_ALWAYS
)) {
4772 ctx
->null_cond
.c
= TCG_COND_NEVER
;
4776 ret
= translate_one(ctx
, insn
);
4777 assert(ctx
->null_lab
== NULL
);
4781 /* Free any temporaries allocated. */
4782 for (i
= 0, n
= ctx
->ntempr
; i
< n
; ++i
) {
4783 tcg_temp_free(ctx
->tempr
[i
]);
4784 ctx
->tempr
[i
] = NULL
;
4786 for (i
= 0, n
= ctx
->ntempl
; i
< n
; ++i
) {
4787 tcg_temp_free_tl(ctx
->templ
[i
]);
4788 ctx
->templ
[i
] = NULL
;
4793 /* Advance the insn queue. Note that this check also detects
4794 a priority change within the instruction queue. */
4795 if (ret
== DISAS_NEXT
&& ctx
->iaoq_b
!= ctx
->iaoq_f
+ 4) {
4796 if (ctx
->iaoq_b
!= -1 && ctx
->iaoq_n
!= -1
4797 && use_goto_tb(ctx
, ctx
->iaoq_b
)
4798 && (ctx
->null_cond
.c
== TCG_COND_NEVER
4799 || ctx
->null_cond
.c
== TCG_COND_ALWAYS
)) {
4800 nullify_set(ctx
, ctx
->null_cond
.c
== TCG_COND_ALWAYS
);
4801 gen_goto_tb(ctx
, 0, ctx
->iaoq_b
, ctx
->iaoq_n
);
4802 ret
= DISAS_NORETURN
;
4804 ret
= DISAS_IAQ_N_STALE
;
4807 ctx
->iaoq_f
= ctx
->iaoq_b
;
4808 ctx
->iaoq_b
= ctx
->iaoq_n
;
4809 ctx
->base
.is_jmp
= ret
;
4810 ctx
->base
.pc_next
+= 4;
4812 if (ret
== DISAS_NORETURN
|| ret
== DISAS_IAQ_N_UPDATED
) {
4815 if (ctx
->iaoq_f
== -1) {
4816 tcg_gen_mov_reg(cpu_iaoq_f
, cpu_iaoq_b
);
4817 copy_iaoq_entry(cpu_iaoq_b
, ctx
->iaoq_n
, ctx
->iaoq_n_var
);
4818 #ifndef CONFIG_USER_ONLY
4819 tcg_gen_mov_i64(cpu_iasq_f
, cpu_iasq_b
);
4822 ctx
->base
.is_jmp
= DISAS_IAQ_N_UPDATED
;
4823 } else if (ctx
->iaoq_b
== -1) {
4824 tcg_gen_mov_reg(cpu_iaoq_b
, ctx
->iaoq_n_var
);
4828 static void hppa_tr_tb_stop(DisasContextBase
*dcbase
, CPUState
*cs
)
4830 DisasContext
*ctx
= container_of(dcbase
, DisasContext
, base
);
4831 DisasJumpType is_jmp
= ctx
->base
.is_jmp
;
4834 case DISAS_NORETURN
:
4836 case DISAS_TOO_MANY
:
4837 case DISAS_IAQ_N_STALE
:
4838 case DISAS_IAQ_N_STALE_EXIT
:
4839 copy_iaoq_entry(cpu_iaoq_f
, ctx
->iaoq_f
, cpu_iaoq_f
);
4840 copy_iaoq_entry(cpu_iaoq_b
, ctx
->iaoq_b
, cpu_iaoq_b
);
4843 case DISAS_IAQ_N_UPDATED
:
4844 if (ctx
->base
.singlestep_enabled
) {
4845 gen_excp_1(EXCP_DEBUG
);
4846 } else if (is_jmp
== DISAS_IAQ_N_STALE_EXIT
) {
4849 tcg_gen_lookup_and_goto_ptr();
4853 g_assert_not_reached();
4857 static void hppa_tr_disas_log(const DisasContextBase
*dcbase
, CPUState
*cs
)
4859 target_ulong pc
= dcbase
->pc_first
;
4861 #ifdef CONFIG_USER_ONLY
4864 qemu_log("IN:\n0x00000000: (null)\n");
4867 qemu_log("IN:\n0x000000b0: light-weight-syscall\n");
4870 qemu_log("IN:\n0x000000e0: set-thread-pointer-syscall\n");
4873 qemu_log("IN:\n0x00000100: syscall\n");
4878 qemu_log("IN: %s\n", lookup_symbol(pc
));
4879 log_target_disas(cs
, pc
, dcbase
->tb
->size
);
4882 static const TranslatorOps hppa_tr_ops
= {
4883 .init_disas_context
= hppa_tr_init_disas_context
,
4884 .tb_start
= hppa_tr_tb_start
,
4885 .insn_start
= hppa_tr_insn_start
,
4886 .breakpoint_check
= hppa_tr_breakpoint_check
,
4887 .translate_insn
= hppa_tr_translate_insn
,
4888 .tb_stop
= hppa_tr_tb_stop
,
4889 .disas_log
= hppa_tr_disas_log
,
4892 void gen_intermediate_code(CPUState
*cs
, struct TranslationBlock
*tb
)
4896 translator_loop(&hppa_tr_ops
, &ctx
.base
, cs
, tb
);
4899 void restore_state_to_opc(CPUHPPAState
*env
, TranslationBlock
*tb
,
4902 env
->iaoq_f
= data
[0];
4903 if (data
[1] != (target_ureg
)-1) {
4904 env
->iaoq_b
= data
[1];
4906 /* Since we were executing the instruction at IAOQ_F, and took some
4907 sort of action that provoked the cpu_restore_state, we can infer
4908 that the instruction was not nullified. */