xen_disk: remove use of grant map/unmap
[qemu.git] / target / hppa / translate.c
blob5320b217deb0df6eb46131c3076a8a1de445fefa
1 /*
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"
21 #include "cpu.h"
22 #include "disas/disas.h"
23 #include "qemu/host-utils.h"
24 #include "exec/exec-all.h"
25 #include "tcg-op.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"
31 #include "exec/log.h"
33 /* Since we have a distinction between register size and address size,
34 we need to redefine all of these. */
36 #undef TCGv
37 #undef tcg_temp_new
38 #undef tcg_global_reg_new
39 #undef tcg_global_mem_new
40 #undef tcg_temp_local_new
41 #undef tcg_temp_free
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
49 #else
50 #define tcg_gen_extu_reg_tl tcg_gen_extu_i32_i64
51 #endif
52 #else
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
57 #endif
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
155 #else
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 {
252 TCGCond c;
253 TCGv_reg a0, a1;
254 bool a0_is_n;
255 bool a1_is_0;
256 } DisasCond;
258 typedef struct DisasContext {
259 DisasContextBase base;
260 CPUState *cs;
262 target_ureg iaoq_f;
263 target_ureg iaoq_b;
264 target_ureg iaoq_n;
265 TCGv_reg iaoq_n_var;
267 int ntempr, ntempl;
268 TCGv_reg tempr[8];
269 TCGv_tl templ[4];
271 DisasCond null_cond;
272 TCGLabel *null_lab;
274 uint32_t insn;
275 uint32_t tb_flags;
276 int mmu_idx;
277 int privilege;
278 bool psw_n_nonzero;
279 } DisasContext;
281 /* Target-specific return values from translate_one, indicating the
282 state of the TB. Note that DISAS_NEXT indicates that we are not
283 exiting the TB. */
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 {
298 uint32_t insn, mask;
299 DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
300 const struct DisasInsn *f);
301 union {
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);
309 } f;
310 } DisasInsn;
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]) },
335 DEF_VAR(psw_n),
336 DEF_VAR(psw_v),
337 DEF_VAR(psw_cb),
338 DEF_VAR(psw_cb_msb),
339 DEF_VAR(iaoq_f),
340 DEF_VAR(iaoq_b),
343 #undef DEF_VAR
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"
357 int i;
359 cpu_gr[0] = NULL;
360 for (i = 1; i < 32; i++) {
361 cpu_gr[i] = tcg_global_mem_new(cpu_env,
362 offsetof(CPUHPPAState, gr[i]),
363 gr_names[i]);
365 for (i = 0; i < 4; i++) {
366 cpu_sr[i] = tcg_global_mem_new_i64(cpu_env,
367 offsetof(CPUHPPAState, sr[i]),
368 sr_names[i]);
370 cpu_srH = tcg_global_mem_new_i64(cpu_env,
371 offsetof(CPUHPPAState, sr[4]),
372 sr_names[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),
381 "iasq_f");
382 cpu_iasq_b = tcg_global_mem_new_i64(cpu_env,
383 offsetof(CPUHPPAState, iasq_b),
384 "iasq_b");
387 static DisasCond cond_make_f(void)
389 return (DisasCond){
390 .c = TCG_COND_NEVER,
391 .a0 = NULL,
392 .a1 = NULL,
396 static DisasCond cond_make_n(void)
398 return (DisasCond){
399 .c = TCG_COND_NE,
400 .a0 = cpu_psw_n,
401 .a0_is_n = true,
402 .a1 = NULL,
403 .a1_is_0 = true
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);
415 return r;
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);
428 return r;
431 static void cond_prep(DisasCond *cond)
433 if (cond->a1_is_0) {
434 cond->a1_is_0 = false;
435 cond->a1 = tcg_const_reg(0);
439 static void cond_free(DisasCond *cond)
441 switch (cond->c) {
442 default:
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;
451 cond->a0 = NULL;
452 cond->a1 = NULL;
453 /* fallthru */
454 case TCG_COND_ALWAYS:
455 cond->c = TCG_COND_NEVER;
456 break;
457 case TCG_COND_NEVER:
458 break;
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();
476 #endif
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);
482 return t;
485 static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg)
487 if (reg == 0) {
488 TCGv_reg t = get_temp(ctx);
489 tcg_gen_movi_reg(t, 0);
490 return t;
491 } else {
492 return cpu_gr[reg];
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);
500 } else {
501 return cpu_gr[reg];
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);
511 } else {
512 tcg_gen_mov_reg(dest, t);
516 static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t)
518 if (reg != 0) {
519 save_or_nullify(ctx, cpu_gr[reg], t);
523 #ifdef HOST_WORDS_BIGENDIAN
524 # define HI_OFS 0
525 # define LO_OFS 4
526 #else
527 # define HI_OFS 4
528 # define LO_OFS 0
529 #endif
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));
537 return ret;
540 static TCGv_i32 load_frw0_i32(unsigned rt)
542 if (rt == 0) {
543 return tcg_const_i32(0);
544 } else {
545 return load_frw_i32(rt);
549 static TCGv_i64 load_frw0_i64(unsigned rt)
551 if (rt == 0) {
552 return tcg_const_i64(0);
553 } else {
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));
558 return ret;
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));
569 #undef HI_OFS
570 #undef LO_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]));
576 return ret;
579 static TCGv_i64 load_frd0(unsigned rt)
581 if (rt == 0) {
582 return tcg_const_i64(0);
583 } else {
584 return load_frd(rt);
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);
597 #else
598 if (reg < 4) {
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);
602 } else {
603 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
605 #endif
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);
646 return;
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. */
681 return status;
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);
689 } else {
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. */
694 nullify_save(ctx);
695 gen_set_label(null_lab);
696 ctx->null_cond = cond_make_n();
698 if (status == DISAS_NORETURN) {
699 status = DISAS_NEXT;
701 return status;
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);
708 } else {
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);
729 nullify_save(ctx);
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]));
738 tcg_temp_free(tmp);
739 return gen_excp(ctx, exc);
742 static DisasJumpType gen_illegal(DisasContext *ctx)
744 nullify_over(ctx);
745 return nullify_end(ctx, gen_excp_iir(ctx, EXCP_ILL));
748 #define CHECK_MOST_PRIVILEGED(EXCP) \
749 do { \
750 if (ctx->privilege != 0) { \
751 nullify_over(ctx); \
752 return nullify_end(ctx, gen_excp_iir(ctx, EXCP)); \
754 } while (0)
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) {
760 return false;
762 return true;
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);
783 } else {
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);
788 } else {
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);
800 return x;
803 static unsigned assemble_rt64(uint32_t insn)
805 unsigned r1 = extract32(insn, 6, 1);
806 unsigned r0 = extract32(insn, 0, 5);
807 return r1 * 32 + r0;
810 static unsigned assemble_ra64(uint32_t insn)
812 unsigned r1 = extract32(insn, 7, 1);
813 unsigned r0 = extract32(insn, 21, 5);
814 return r1 * 32 + r0;
817 static unsigned assemble_rb64(uint32_t insn)
819 unsigned r1 = extract32(insn, 12, 1);
820 unsigned r0 = extract32(insn, 16, 5);
821 return r1 * 32 + r0;
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);
836 return s2 * 4 + s0;
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);
844 return x;
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);
862 return x << 2;
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);
871 return x << 2;
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);
881 return x << 11;
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);
890 return x << 2;
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)
903 DisasCond cond;
904 TCGv_reg tmp;
906 switch (cf >> 1) {
907 case 0: /* Never / TR */
908 cond = cond_make_f();
909 break;
910 case 1: /* = / <> (Z / !Z) */
911 cond = cond_make_0(TCG_COND_EQ, res);
912 break;
913 case 2: /* < / >= (N / !N) */
914 cond = cond_make_0(TCG_COND_LT, res);
915 break;
916 case 3: /* <= / > (N | Z / !N & !Z) */
917 cond = cond_make_0(TCG_COND_LE, res);
918 break;
919 case 4: /* NUV / UV (!C / C) */
920 cond = cond_make_0(TCG_COND_EQ, cb_msb);
921 break;
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);
927 tcg_temp_free(tmp);
928 break;
929 case 6: /* SV / NSV (V / !V) */
930 cond = cond_make_0(TCG_COND_LT, sv);
931 break;
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);
936 tcg_temp_free(tmp);
937 break;
938 default:
939 g_assert_not_reached();
941 if (cf & 1) {
942 cond.c = tcg_invert_cond(cond.c);
945 return cond;
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)
955 DisasCond cond;
957 switch (cf >> 1) {
958 case 1: /* = / <> */
959 cond = cond_make(TCG_COND_EQ, in1, in2);
960 break;
961 case 2: /* < / >= */
962 cond = cond_make(TCG_COND_LT, in1, in2);
963 break;
964 case 3: /* <= / > */
965 cond = cond_make(TCG_COND_LE, in1, in2);
966 break;
967 case 4: /* << / >>= */
968 cond = cond_make(TCG_COND_LTU, in1, in2);
969 break;
970 case 5: /* <<= / >> */
971 cond = cond_make(TCG_COND_LEU, in1, in2);
972 break;
973 default:
974 return do_cond(cf, res, sv, sv);
976 if (cf & 1) {
977 cond.c = tcg_invert_cond(cond.c);
980 return cond;
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)
988 switch (cf >> 1) {
989 case 4: case 5: case 6:
990 cf &= 1;
991 break;
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)
1000 unsigned c, f;
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. */
1005 c = orig & 3;
1006 if (c == 3) {
1007 c = 7;
1009 f = (orig & 4) / 4;
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)
1019 DisasCond cond;
1020 TCGv_reg tmp, cb = NULL;
1022 if (cf & 8) {
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);
1033 tcg_temp_free(tmp);
1036 switch (cf >> 1) {
1037 case 0: /* never / TR */
1038 case 1: /* undefined */
1039 case 5: /* undefined */
1040 cond = cond_make_f();
1041 break;
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);
1052 tcg_temp_free(tmp);
1053 break;
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);
1061 tcg_temp_free(tmp);
1062 break;
1064 case 4: /* SDC / NDC */
1065 tcg_gen_andi_reg(cb, cb, 0x88888888u);
1066 cond = cond_make_0(TCG_COND_NE, cb);
1067 break;
1069 case 6: /* SBC / NBC */
1070 tcg_gen_andi_reg(cb, cb, 0x80808080u);
1071 cond = cond_make_0(TCG_COND_NE, cb);
1072 break;
1074 case 7: /* SHC / NHC */
1075 tcg_gen_andi_reg(cb, cb, 0x80008000u);
1076 cond = cond_make_0(TCG_COND_NE, cb);
1077 break;
1079 default:
1080 g_assert_not_reached();
1082 if (cf & 8) {
1083 tcg_temp_free(cb);
1085 if (cf & 1) {
1086 cond.c = tcg_invert_cond(cond.c);
1089 return cond;
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);
1102 tcg_temp_free(tmp);
1104 return sv;
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);
1117 tcg_temp_free(tmp);
1119 return sv;
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;
1128 DisasCond cond;
1130 dest = tcg_temp_new();
1131 cb = NULL;
1132 cb_msb = NULL;
1134 if (shift) {
1135 tmp = get_temp(ctx);
1136 tcg_gen_shli_reg(tmp, in1, shift);
1137 in1 = tmp;
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);
1144 if (is_c) {
1145 tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
1147 tcg_temp_free(zero);
1148 if (!is_l) {
1149 cb = get_temp(ctx);
1150 tcg_gen_xor_reg(cb, in1, in2);
1151 tcg_gen_xor_reg(cb, cb, dest);
1153 } else {
1154 tcg_gen_add_reg(dest, in1, in2);
1155 if (is_c) {
1156 tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
1160 /* Compute signed overflow if required. */
1161 sv = NULL;
1162 if (is_tsv || c == 6) {
1163 sv = do_add_sv(ctx, dest, in1, in2);
1164 if (is_tsv) {
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);
1172 if (is_tc) {
1173 cond_prep(&cond);
1174 tmp = tcg_temp_new();
1175 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1176 gen_helper_tcond(cpu_env, tmp);
1177 tcg_temp_free(tmp);
1180 /* Write back the result. */
1181 if (!is_l) {
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;
1191 return DISAS_NEXT;
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;
1200 DisasCond cond;
1202 dest = tcg_temp_new();
1203 cb = tcg_temp_new();
1204 cb_msb = tcg_temp_new();
1206 zero = tcg_const_reg(0);
1207 if (is_b) {
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);
1214 } else {
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. */
1225 sv = NULL;
1226 if (is_tsv || c == 6) {
1227 sv = do_sub_sv(ctx, dest, in1, in2);
1228 if (is_tsv) {
1229 gen_helper_tsv(cpu_env, sv);
1233 /* Compute the condition. We cannot use the special case for borrow. */
1234 if (!is_b) {
1235 cond = do_sub_cond(cf, dest, in1, in2, sv);
1236 } else {
1237 cond = do_cond(cf, dest, cb_msb, sv);
1240 /* Emit any conditional trap before any writeback. */
1241 if (is_tc) {
1242 cond_prep(&cond);
1243 tmp = tcg_temp_new();
1244 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1245 gen_helper_tcond(cpu_env, tmp);
1246 tcg_temp_free(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;
1258 return DISAS_NEXT;
1261 static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1262 TCGv_reg in2, unsigned cf)
1264 TCGv_reg dest, sv;
1265 DisasCond cond;
1267 dest = tcg_temp_new();
1268 tcg_gen_sub_reg(dest, in1, in2);
1270 /* Compute signed overflow if required. */
1271 sv = NULL;
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);
1279 /* Clear. */
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;
1287 return DISAS_NEXT;
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. */
1297 fn(dest, in1, in2);
1298 save_gpr(ctx, rt, dest);
1300 /* Install the new nullification. */
1301 cond_free(&ctx->null_cond);
1302 if (cf) {
1303 ctx->null_cond = do_log_cond(cf, dest);
1305 return DISAS_NEXT;
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))
1312 TCGv_reg dest;
1313 DisasCond cond;
1315 if (cf == 0) {
1316 dest = dest_gpr(ctx, rt);
1317 fn(dest, in1, in2);
1318 save_gpr(ctx, rt, dest);
1319 cond_free(&ctx->null_cond);
1320 } else {
1321 dest = tcg_temp_new();
1322 fn(dest, in1, in2);
1324 cond = do_unit_cond(cf, dest, in1, in2);
1326 if (is_tc) {
1327 TCGv_reg tmp = tcg_temp_new();
1328 cond_prep(&cond);
1329 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1330 gen_helper_tcond(cpu_env, tmp);
1331 tcg_temp_free(tmp);
1333 save_gpr(ctx, rt, dest);
1335 cond_free(&ctx->null_cond);
1336 ctx->null_cond = cond;
1338 return DISAS_NEXT;
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)
1348 TCGv_ptr ptr;
1349 TCGv_reg tmp;
1350 TCGv_i64 spc;
1352 if (sp != 0) {
1353 if (sp < 0) {
1354 sp = ~sp;
1356 spc = get_temp_tl(ctx);
1357 load_spr(ctx, spc, sp);
1358 return spc;
1360 if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1361 return cpu_srH;
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);
1371 tcg_temp_free(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);
1377 return spc;
1379 #endif
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);
1386 TCGv_reg ofs;
1388 /* Note that RX is mutually exclusive with DISP. */
1389 if (rx) {
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);
1396 } else {
1397 ofs = base;
1400 *pofs = ofs;
1401 #ifdef CONFIG_USER_ONLY
1402 *pgva = (modify <= 0 ? ofs : base);
1403 #else
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);
1409 if (!is_phys) {
1410 tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base));
1412 *pgva = addr;
1413 #endif
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)
1425 TCGv_reg ofs;
1426 TCGv_tl addr;
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);
1434 if (modify) {
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)
1443 TCGv_reg ofs;
1444 TCGv_tl addr;
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);
1452 if (modify) {
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)
1461 TCGv_reg ofs;
1462 TCGv_tl addr;
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);
1470 if (modify) {
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)
1479 TCGv_reg ofs;
1480 TCGv_tl addr;
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);
1488 if (modify) {
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
1496 #else
1497 #define do_load_reg do_load_32
1498 #define do_store_reg do_store_32
1499 #endif
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)
1505 TCGv_reg dest;
1507 nullify_over(ctx);
1509 if (modify == 0) {
1510 /* No base register update. */
1511 dest = dest_gpr(ctx, rt);
1512 } else {
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)
1526 TCGv_i32 tmp;
1528 nullify_over(ctx);
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);
1535 if (rt == 0) {
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)
1546 TCGv_i64 tmp;
1548 nullify_over(ctx);
1550 tmp = tcg_temp_new_i64();
1551 do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1552 save_frd(rt, tmp);
1553 tcg_temp_free_i64(tmp);
1555 if (rt == 0) {
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)
1566 nullify_over(ctx);
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)
1575 TCGv_i32 tmp;
1577 nullify_over(ctx);
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)
1590 TCGv_i64 tmp;
1592 nullify_over(ctx);
1594 tmp = load_frd(rt);
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))
1604 TCGv_i32 tmp;
1606 nullify_over(ctx);
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))
1619 TCGv_i32 dst;
1620 TCGv_i64 src;
1622 nullify_over(ctx);
1623 src = load_frd(ra);
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))
1637 TCGv_i64 tmp;
1639 nullify_over(ctx);
1640 tmp = load_frd0(ra);
1642 func(tmp, cpu_env, tmp);
1644 save_frd(rt, 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))
1652 TCGv_i32 src;
1653 TCGv_i64 dst;
1655 nullify_over(ctx);
1656 src = load_frw0_i32(ra);
1657 dst = tcg_temp_new_i64();
1659 func(dst, cpu_env, src);
1661 tcg_temp_free_i32(src);
1662 save_frd(rt, dst);
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))
1672 TCGv_i32 a, b;
1674 nullify_over(ctx);
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))
1691 TCGv_i64 a, b;
1693 nullify_over(ctx);
1694 a = load_frd0(ra);
1695 b = load_frd0(rb);
1697 func(a, cpu_env, a, b);
1699 tcg_temp_free_i64(b);
1700 save_frd(rt, a);
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) {
1711 if (link != 0) {
1712 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1714 ctx->iaoq_n = dest;
1715 if (is_n) {
1716 ctx->null_cond.c = TCG_COND_ALWAYS;
1718 return DISAS_NEXT;
1719 } else {
1720 nullify_over(ctx);
1722 if (link != 0) {
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);
1729 } else {
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,
1745 DisasCond *cond)
1747 target_ureg dest = iaoq_dest(ctx, disp);
1748 TCGLabel *taken = NULL;
1749 TCGCond c = cond->c;
1750 bool n;
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();
1763 cond_prep(cond);
1764 tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
1765 cond_free(cond);
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);
1772 } else {
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);
1793 } else {
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;
1803 } else {
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;
1814 TCGCond c;
1816 assert(ctx->null_lab == NULL);
1818 if (ctx->null_cond.c == TCG_COND_NEVER) {
1819 if (link != 0) {
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);
1824 if (is_n) {
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;
1833 ctx->iaoq_n = -1;
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);
1851 nullify_over(ctx);
1852 if (link != 0) {
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);
1857 } else {
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);
1868 ctx->iaoq_n = -1;
1869 ctx->iaoq_n_var = next;
1871 if (link != 0) {
1872 tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1875 if (is_n) {
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
1878 to the branch. */
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;
1883 } else {
1884 cond_free(&ctx->null_cond);
1888 return DISAS_NEXT;
1891 /* Implement
1892 * if (IAOQ_Front{30..31} < GR[b]{30..31})
1893 * IAOQ_Next{30..31} ← GR[b]{30..31};
1894 * else
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)
1900 TCGv_reg dest;
1901 switch (ctx->privilege) {
1902 case 0:
1903 /* Privilege 0 is maximum and is allowed to decrease. */
1904 return offset;
1905 case 3:
1906 /* Privilege 3 is minimum and is never allowed increase. */
1907 dest = get_temp(ctx);
1908 tcg_gen_ori_reg(dest, offset, 3);
1909 break;
1910 default:
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);
1916 break;
1918 return 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:
1936 break;
1937 case TCG_COND_ALWAYS:
1938 tcg_gen_movi_reg(cpu_psw_n, 0);
1939 goto do_sigill;
1940 default:
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) {
1951 goto do_sigill;
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;
1973 default:
1974 do_sigill:
1975 gen_excp_1(EXCP_ILL);
1976 return DISAS_NORETURN;
1979 #endif
1981 static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
1982 const DisasInsn *di)
1984 cond_free(&ctx->null_cond);
1985 return DISAS_NEXT;
1988 static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
1989 const DisasInsn *di)
1991 nullify_over(ctx);
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);
2002 return DISAS_NEXT;
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);
2014 return DISAS_NEXT;
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);
2030 tcg_temp_free(t1);
2031 tcg_temp_free_i64(t0);
2033 cond_free(&ctx->null_cond);
2034 return DISAS_NEXT;
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);
2042 TCGv_reg tmp;
2043 DisasJumpType ret;
2045 switch (ctl) {
2046 case CR_SAR:
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);
2053 goto done;
2055 #endif
2056 save_gpr(ctx, rt, cpu_sar);
2057 goto done;
2058 case CR_IT: /* Interval Timer */
2059 /* FIXME: Respect PSW_S bit. */
2060 nullify_over(ctx);
2061 tmp = dest_gpr(ctx, rt);
2062 if (ctx->base.tb->cflags & CF_USE_ICOUNT) {
2063 gen_io_start();
2064 gen_helper_read_interval_timer(tmp);
2065 gen_io_end();
2066 ret = DISAS_IAQ_N_STALE;
2067 } else {
2068 gen_helper_read_interval_timer(tmp);
2069 ret = DISAS_NEXT;
2071 save_gpr(ctx, rt, tmp);
2072 return nullify_end(ctx, ret);
2073 case 26:
2074 case 27:
2075 break;
2076 default:
2077 /* All other control registers are privileged. */
2078 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2079 break;
2082 tmp = get_temp(ctx);
2083 tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2084 save_gpr(ctx, rt, tmp);
2086 done:
2087 cond_free(&ctx->null_cond);
2088 return DISAS_NEXT;
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);
2096 TCGv_i64 t64;
2098 if (rs >= 5) {
2099 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2101 nullify_over(ctx);
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);
2107 if (rs >= 4) {
2108 tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs]));
2109 ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2110 } else {
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);
2124 TCGv_reg tmp;
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);
2130 tcg_temp_free(tmp);
2132 cond_free(&ctx->null_cond);
2133 return DISAS_NEXT;
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();
2141 #else
2142 DisasJumpType ret = DISAS_NEXT;
2144 nullify_over(ctx);
2145 switch (ctl) {
2146 case CR_IT:
2147 gen_helper_write_interval_timer(cpu_env, reg);
2148 break;
2149 case CR_EIRR:
2150 gen_helper_write_eirr(cpu_env, reg);
2151 break;
2152 case CR_EIEM:
2153 gen_helper_write_eiem(cpu_env, reg);
2154 ret = DISAS_IAQ_N_STALE_EXIT;
2155 break;
2157 case CR_IIASQ:
2158 case CR_IIAOQ:
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]));
2167 break;
2169 default:
2170 tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2171 break;
2173 return nullify_end(ctx, ret);
2174 #endif
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);
2186 tcg_temp_free(tmp);
2188 cond_free(&ctx->null_cond);
2189 return DISAS_NEXT;
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);
2201 #else
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);
2211 #endif
2212 save_gpr(ctx, rt, dest);
2214 cond_free(&ctx->null_cond);
2215 return DISAS_NEXT;
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;
2230 return val;
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);
2238 TCGv_reg tmp;
2240 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2241 nullify_over(ctx);
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);
2258 TCGv_reg tmp;
2260 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2261 nullify_over(ctx);
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);
2277 TCGv_reg tmp, reg;
2279 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2280 nullify_over(ctx);
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);
2296 nullify_over(ctx);
2298 if (comp == 5) {
2299 gen_helper_rfi_r(cpu_env);
2300 } else {
2301 gen_helper_rfi(cpu_env);
2303 if (ctx->base.singlestep_enabled) {
2304 gen_excp_1(EXCP_DEBUG);
2305 } else {
2306 tcg_gen_exit_tb(0);
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);
2316 nullify_over(ctx);
2317 if (reset) {
2318 gen_helper_reset(cpu_env);
2319 } else {
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 },
2342 #endif
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);
2359 return DISAS_NEXT;
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);
2371 TCGv_reg dest, ofs;
2372 TCGv_i32 level, want;
2373 TCGv_tl addr;
2375 nullify_over(ctx);
2377 dest = dest_gpr(ctx, rt);
2378 form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
2380 if (is_imm) {
2381 level = tcg_const_i32(extract32(insn, 16, 2));
2382 } else {
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)
2402 unsigned sp;
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;
2407 TCGv_tl addr;
2408 TCGv_reg ofs, reg;
2410 if (is_data) {
2411 sp = extract32(insn, 14, 2);
2412 } else {
2413 sp = ~assemble_sr3(insn);
2416 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2417 nullify_over(ctx);
2419 form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
2420 reg = load_gpr(ctx, rr);
2421 if (is_addr) {
2422 gen_helper_itlba(cpu_env, addr, reg);
2423 } else {
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);
2437 unsigned sp;
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;
2442 TCGv_tl addr;
2443 TCGv_reg ofs;
2445 if (is_data) {
2446 sp = extract32(insn, 14, 2);
2447 } else {
2448 sp = ~assemble_sr3(insn);
2451 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2452 nullify_over(ctx);
2454 form_gva(ctx, &addr, &ofs, rb, rx, 0, 0, sp, m, false);
2455 if (m) {
2456 save_gpr(ctx, rb, ofs);
2458 if (is_local) {
2459 gen_helper_ptlbe(cpu_env);
2460 } else {
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);
2477 TCGv_tl vaddr;
2478 TCGv_reg ofs, paddr;
2480 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2481 nullify_over(ctx);
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. */
2489 if (m) {
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);
2502 TCGv_reg ci;
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);
2512 tcg_temp_free(ci);
2514 return DISAS_NEXT;
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 },
2545 #endif
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;
2558 bool is_c = false;
2559 bool is_l = false;
2560 bool is_tc = false;
2561 bool is_tsv = false;
2562 DisasJumpType ret;
2564 switch (ext) {
2565 case 0x6: /* ADD, SHLADD */
2566 break;
2567 case 0xa: /* ADD,L, SHLADD,L */
2568 is_l = true;
2569 break;
2570 case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
2571 is_tsv = true;
2572 break;
2573 case 0x7: /* ADD,C */
2574 is_c = true;
2575 break;
2576 case 0xf: /* ADD,C,TSV */
2577 is_c = is_tsv = true;
2578 break;
2579 default:
2580 return gen_illegal(ctx);
2583 if (cf) {
2584 nullify_over(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;
2601 bool is_b = false;
2602 bool is_tc = false;
2603 bool is_tsv = false;
2604 DisasJumpType ret;
2606 switch (ext) {
2607 case 0x10: /* SUB */
2608 break;
2609 case 0x30: /* SUB,TSV */
2610 is_tsv = true;
2611 break;
2612 case 0x14: /* SUB,B */
2613 is_b = true;
2614 break;
2615 case 0x34: /* SUB,B,TSV */
2616 is_b = is_tsv = true;
2617 break;
2618 case 0x13: /* SUB,TC */
2619 is_tc = true;
2620 break;
2621 case 0x33: /* SUB,TSV,TC */
2622 is_tc = is_tsv = true;
2623 break;
2624 default:
2625 return gen_illegal(ctx);
2628 if (cf) {
2629 nullify_over(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;
2645 DisasJumpType ret;
2647 if (cf) {
2648 nullify_over(ctx);
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);
2663 if (r1 == 0) {
2664 TCGv_reg dest = dest_gpr(ctx, rt);
2665 tcg_gen_movi_reg(dest, 0);
2666 save_gpr(ctx, rt, dest);
2667 } else {
2668 save_gpr(ctx, rt, cpu_gr[r1]);
2670 cond_free(&ctx->null_cond);
2671 return DISAS_NEXT;
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;
2682 DisasJumpType ret;
2684 if (cf) {
2685 nullify_over(ctx);
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;
2701 DisasJumpType ret;
2703 if (cf) {
2704 nullify_over(ctx);
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;
2721 DisasJumpType ret;
2723 if (cf) {
2724 nullify_over(ctx);
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);
2741 TCGv_reg tmp;
2742 DisasJumpType ret;
2744 nullify_over(ctx);
2746 tmp = get_temp(ctx);
2747 tcg_gen_shri_reg(tmp, cpu_psw_cb, 3);
2748 if (!is_i) {
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;
2768 nullify_over(ctx);
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. */
2809 if (cf) {
2810 TCGv_reg sv = NULL;
2811 if (cf >> 1 == 6) {
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)
2835 TCGv_i32 tmp;
2837 /* No need to check for supervisor, as userland can only pause
2838 until the next timer interrupt. */
2839 nullify_over(ctx);
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);
2855 #endif
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 */
2863 #endif
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;
2888 DisasJumpType ret;
2890 if (cf) {
2891 nullify_over(ctx);
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;
2909 DisasJumpType ret;
2911 if (cf) {
2912 nullify_over(ctx);
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;
2929 DisasJumpType ret;
2931 if (cf) {
2932 nullify_over(ctx);
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;
3001 TCGv_tl addr;
3002 int modify, disp = 0, scale = 0;
3004 nullify_over(ctx);
3006 if (i) {
3007 modify = (m ? (au ? -1 : 1) : 0);
3008 disp = low_sextract(rx, 0, 5);
3009 rx = 0;
3010 } else {
3011 modify = m;
3012 if (au) {
3013 scale = mop & MO_SIZE;
3016 if (modify) {
3017 /* Base register modification. Make sure if RT == RB,
3018 we see the result of the load. */
3019 dest = get_temp(ctx);
3020 } else {
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);
3028 if (modify) {
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);
3045 TCGv_reg ofs, val;
3046 TCGv_tl addr;
3048 nullify_over(ctx);
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);
3053 if (a) {
3054 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3055 gen_helper_stby_e_parallel(cpu_env, addr, val);
3056 } else {
3057 gen_helper_stby_e(cpu_env, addr, val);
3059 } else {
3060 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3061 gen_helper_stby_b_parallel(cpu_env, addr, val);
3062 } else {
3063 gen_helper_stby_b(cpu_env, addr, val);
3067 if (m) {
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;
3080 DisasJumpType ret;
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;
3089 return ret;
3092 static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn,
3093 const DisasInsn *di)
3095 int hold_mmu_idx = ctx->mmu_idx;
3096 DisasJumpType ret;
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;
3105 return ret;
3108 static DisasJumpType trans_stwa_idx_i(DisasContext *ctx, uint32_t insn,
3109 const DisasInsn *di)
3111 int hold_mmu_idx = ctx->mmu_idx;
3112 DisasJumpType ret;
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;
3121 return ret;
3123 #endif
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 */
3135 #endif
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);
3148 return DISAS_NEXT;
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);
3162 return DISAS_NEXT;
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. */
3174 if (rb == 0) {
3175 tcg_gen_movi_reg(tcg_rt, i);
3176 } else {
3177 tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i);
3179 save_gpr(ctx, rt, tcg_rt);
3180 cond_free(&ctx->null_cond);
3182 return DISAS_NEXT;
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);
3205 switch (ext2) {
3206 case 0:
3207 case 1:
3208 /* FLDW without modification. */
3209 return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
3210 case 2:
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);
3214 default:
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);
3251 switch (ext2) {
3252 case 0:
3253 case 1:
3254 /* FSTW without modification. */
3255 return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
3256 case 2:
3257 /* STW with modification. */
3258 return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
3259 default:
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);
3291 int disp, scale;
3293 if (i == 0) {
3294 scale = (ua ? 2 : 0);
3295 disp = 0;
3296 modify = m;
3297 } else {
3298 disp = low_sextract(rx, 0, 5);
3299 scale = 0;
3300 rx = 0;
3301 modify = (m ? (ua ? -1 : 1) : 0);
3304 switch (ext3) {
3305 case 0: /* FLDW */
3306 return do_floadw(ctx, rt, rb, rx, scale, disp, sp, modify);
3307 case 4: /* FSTW */
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);
3325 int disp, scale;
3327 if (i == 0) {
3328 scale = (ua ? 3 : 0);
3329 disp = 0;
3330 modify = m;
3331 } else {
3332 disp = low_sextract(rx, 0, 5);
3333 scale = 0;
3334 rx = 0;
3335 modify = (m ? (ua ? -1 : 1) : 0);
3338 switch (ext4) {
3339 case 0: /* FLDD */
3340 return do_floadd(ctx, rt, rb, rx, scale, disp, sp, modify);
3341 case 8: /* FSTD */
3342 return do_fstored(ctx, rt, rb, rx, scale, disp, sp, modify);
3343 default:
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;
3357 DisasCond cond;
3359 nullify_over(ctx);
3361 if (is_imm) {
3362 in1 = load_const(ctx, low_sextract(insn, 16, 5));
3363 } else {
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);
3371 sv = NULL;
3372 if (c == 6) {
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;
3389 DisasCond cond;
3391 nullify_over(ctx);
3393 if (is_imm) {
3394 in1 = load_const(ctx, low_sextract(insn, 16, 5));
3395 } else {
3396 in1 = load_gpr(ctx, extract32(insn, 16, 5));
3398 in2 = load_gpr(ctx, r);
3399 dest = dest_gpr(ctx, r);
3400 sv = NULL;
3401 cb_msb = NULL;
3403 switch (c) {
3404 default:
3405 tcg_gen_add_reg(dest, in1, in2);
3406 break;
3407 case 4: case 5:
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);
3411 break;
3412 case 6:
3413 tcg_gen_add_reg(dest, in1, in2);
3414 sv = do_add_sv(ctx, dest, in1, in2);
3415 break;
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;
3431 DisasCond cond;
3433 nullify_over(ctx);
3435 tmp = tcg_temp_new();
3436 tcg_r = load_gpr(ctx, r);
3437 if (i) {
3438 tcg_gen_shli_reg(tmp, tcg_r, p);
3439 } else {
3440 tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
3443 cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp);
3444 tcg_temp_free(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);
3455 TCGv_reg dest;
3456 DisasCond cond;
3458 nullify_over(ctx);
3460 dest = dest_gpr(ctx, r);
3461 if (is_imm) {
3462 tcg_gen_movi_reg(dest, low_sextract(t, 0, 5));
3463 } else if (t == 0) {
3464 tcg_gen_movi_reg(dest, 0);
3465 } else {
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);
3480 TCGv_reg dest;
3482 if (c) {
3483 nullify_over(ctx);
3486 dest = dest_gpr(ctx, rt);
3487 if (r1 == 0) {
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);
3496 } else {
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);
3512 if (c) {
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;
3527 TCGv_reg dest, t2;
3529 if (c) {
3530 nullify_over(ctx);
3533 dest = dest_gpr(ctx, rt);
3534 t2 = load_gpr(ctx, r2);
3535 if (r1 == 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);
3543 } else {
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);
3547 tcg_temp_free(t0);
3549 save_gpr(ctx, rt, dest);
3551 /* Install the new nullification. */
3552 cond_free(&ctx->null_cond);
3553 if (c) {
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;
3570 if (c) {
3571 nullify_over(ctx);
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);
3580 if (is_se) {
3581 tcg_gen_sar_reg(dest, src, tmp);
3582 tcg_gen_sextract_reg(dest, dest, 0, len);
3583 } else {
3584 tcg_gen_shr_reg(dest, src, tmp);
3585 tcg_gen_extract_reg(dest, dest, 0, len);
3587 tcg_temp_free(tmp);
3588 save_gpr(ctx, rt, dest);
3590 /* Install the new nullification. */
3591 cond_free(&ctx->null_cond);
3592 if (c) {
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;
3609 TCGv_reg dest, src;
3611 if (c) {
3612 nullify_over(ctx);
3615 dest = dest_gpr(ctx, rt);
3616 src = load_gpr(ctx, rr);
3617 if (is_se) {
3618 tcg_gen_sextract_reg(dest, src, cpos, len);
3619 } else {
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);
3626 if (c) {
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;
3650 TCGv_reg dest;
3652 if (c) {
3653 nullify_over(ctx);
3655 if (cpos + len > 32) {
3656 len = 32 - cpos;
3659 dest = dest_gpr(ctx, rt);
3660 mask0 = deposit64(0, cpos, len, val);
3661 mask1 = deposit64(-1, cpos, len, val);
3663 if (nz) {
3664 TCGv_reg src = load_gpr(ctx, rt);
3665 if (mask1 != -1) {
3666 tcg_gen_andi_reg(dest, src, mask1);
3667 src = dest;
3669 tcg_gen_ori_reg(dest, src, mask0);
3670 } else {
3671 tcg_gen_movi_reg(dest, mask0);
3673 save_gpr(ctx, rt, dest);
3675 /* Install the new nullification. */
3676 cond_free(&ctx->null_cond);
3677 if (c) {
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;
3694 TCGv_reg dest, val;
3696 if (c) {
3697 nullify_over(ctx);
3699 if (cpos + len > 32) {
3700 len = 32 - cpos;
3703 dest = dest_gpr(ctx, rt);
3704 val = load_gpr(ctx, rr);
3705 if (rs == 0) {
3706 tcg_gen_deposit_z_reg(dest, val, cpos, len);
3707 } else {
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);
3714 if (c) {
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);
3733 if (c) {
3734 nullify_over(ctx);
3737 if (i) {
3738 val = load_const(ctx, low_sextract(insn, 16, 5));
3739 } else {
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);
3751 if (rs) {
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);
3756 } else {
3757 tcg_gen_shl_reg(dest, tmp, shift);
3759 tcg_temp_free(shift);
3760 tcg_temp_free(mask);
3761 tcg_temp_free(tmp);
3762 save_gpr(ctx, rt, dest);
3764 /* Install the new nullification. */
3765 cond_free(&ctx->null_cond);
3766 if (c) {
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);
3783 TCGv_reg tmp;
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. */
3794 if (b == 0) {
3795 return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
3797 #else
3798 int sp = assemble_sr3(insn);
3799 nullify_over(ctx);
3800 #endif
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);
3808 #else
3809 TCGv_i64 new_spc = tcg_temp_new_i64();
3811 load_spr(ctx, new_spc, sp);
3812 if (is_l) {
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);
3821 } else {
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);
3833 #endif
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
3857 * b gateway
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
3861 * b gateway
3862 * b evil
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. */
3878 if (type < 0) {
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);
3885 } else {
3886 dest &= -4; /* priv = 0 */
3888 #endif
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);
3922 TCGv_reg dest;
3924 if (rx == 0) {
3925 dest = load_gpr(ctx, rb);
3926 } else {
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;
3941 TCGv_reg dest;
3943 #ifdef CONFIG_USER_ONLY
3944 dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
3945 return do_ibranch(ctx, dest, link, n);
3946 #else
3947 nullify_over(ctx);
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));
3956 if (link) {
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);
3962 #endif
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;
4102 nullify_over(ctx);
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);
4146 TCGv_i64 ta, tb;
4147 TCGv_i32 tc, ty;
4149 nullify_over(ctx);
4151 ta = load_frd0(ra);
4152 tb = load_frd0(rb);
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;
4171 TCGv_reg t;
4173 nullify_over(ctx);
4175 t = tcg_temp_new();
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);
4179 tcg_temp_free(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);
4188 int mask;
4189 bool inv = false;
4190 TCGv_reg t;
4192 nullify_over(ctx);
4194 t = tcg_temp_new();
4195 tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
4197 switch (c) {
4198 case 0: /* simple */
4199 tcg_gen_andi_reg(t, t, 0x4000000);
4200 ctx->null_cond = cond_make_0(TCG_COND_NE, t);
4201 goto done;
4202 case 2: /* rej */
4203 inv = true;
4204 /* fallthru */
4205 case 1: /* acc */
4206 mask = 0x43ff800;
4207 break;
4208 case 6: /* rej8 */
4209 inv = true;
4210 /* fallthru */
4211 case 5: /* acc8 */
4212 mask = 0x43f8000;
4213 break;
4214 case 9: /* acc6 */
4215 mask = 0x43e0000;
4216 break;
4217 case 13: /* acc4 */
4218 mask = 0x4380000;
4219 break;
4220 case 17: /* acc2 */
4221 mask = 0x4200000;
4222 break;
4223 default:
4224 return gen_illegal(ctx);
4226 if (inv) {
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);
4230 } else {
4231 tcg_gen_andi_reg(t, t, mask);
4232 ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
4234 done:
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);
4244 TCGv_i64 a, b;
4246 nullify_over(ctx);
4248 a = load_frw0_i64(ra);
4249 b = load_frw0_i64(rb);
4250 tcg_gen_mul_i64(a, a, b);
4251 save_frd(rt, a);
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 */
4294 /* float/float */
4295 { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s },
4296 { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d },
4297 /* int/float */
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 },
4302 /* float/int */
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 },
4312 /* uint/float */
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 },
4317 /* float/uint */
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 },
4339 #undef FOP_WEW
4340 #undef FOP_DEW
4341 #undef FOP_WED
4342 #undef FOP_WEWW
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 */
4378 /* float/float */
4379 { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
4380 { 0x38002200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_d },
4381 /* int/float */
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 },
4386 /* float/int */
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 },
4396 /* uint/float */
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 },
4401 /* float/uint */
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 },
4417 #undef FOP_WEW
4418 #undef FOP_DEW
4419 #undef FOP_WED
4420 #undef FOP_WEWW
4421 #undef FOP_DED
4422 #undef FOP_DEDD
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);
4440 nullify_over(ctx);
4442 /* Independent multiply & add/sub, with undefined behaviour
4443 if outputs overlap inputs. */
4444 if (f == 0) {
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);
4453 } else {
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);
4470 TCGv_i32 a, b, c;
4472 nullify_over(ctx);
4473 a = load_frw0_i32(rm1);
4474 b = load_frw0_i32(rm2);
4475 c = load_frw0_i32(ra3);
4477 if (neg) {
4478 gen_helper_fmpynfadd_s(a, cpu_env, a, b, c);
4479 } else {
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);
4498 TCGv_i64 a, b, c;
4500 nullify_over(ctx);
4501 a = load_frd0(rm1);
4502 b = load_frd0(rm2);
4503 c = load_frd0(ra3);
4505 if (neg) {
4506 gen_helper_fmpynfadd_d(a, cpu_env, a, b, c);
4507 } else {
4508 gen_helper_fmpyfadd_d(a, cpu_env, a, b, c);
4511 tcg_temp_free_i64(b);
4512 tcg_temp_free_i64(c);
4513 save_frd(rt, a);
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)
4526 size_t i;
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);
4544 switch (opc) {
4545 case 0x00: /* system op */
4546 return translate_table(ctx, insn, table_system);
4547 case 0x01:
4548 return translate_table(ctx, insn, table_mem_mgmt);
4549 case 0x02:
4550 return translate_table(ctx, insn, table_arith_log);
4551 case 0x03:
4552 return translate_table(ctx, insn, table_index_mem);
4553 case 0x06:
4554 return trans_fmpyadd(ctx, insn, false);
4555 case 0x08:
4556 return trans_ldil(ctx, insn);
4557 case 0x09:
4558 return trans_copr_w(ctx, insn);
4559 case 0x0A:
4560 return trans_addil(ctx, insn);
4561 case 0x0B:
4562 return trans_copr_dw(ctx, insn);
4563 case 0x0C:
4564 return translate_table(ctx, insn, table_float_0c);
4565 case 0x0D:
4566 return trans_ldo(ctx, insn);
4567 case 0x0E:
4568 return translate_table(ctx, insn, table_float_0e);
4570 case 0x10:
4571 return trans_load(ctx, insn, false, MO_UB);
4572 case 0x11:
4573 return trans_load(ctx, insn, false, MO_TEUW);
4574 case 0x12:
4575 return trans_load(ctx, insn, false, MO_TEUL);
4576 case 0x13:
4577 return trans_load(ctx, insn, true, MO_TEUL);
4578 case 0x16:
4579 return trans_fload_mod(ctx, insn);
4580 case 0x17:
4581 return trans_load_w(ctx, insn);
4582 case 0x18:
4583 return trans_store(ctx, insn, false, MO_UB);
4584 case 0x19:
4585 return trans_store(ctx, insn, false, MO_TEUW);
4586 case 0x1A:
4587 return trans_store(ctx, insn, false, MO_TEUL);
4588 case 0x1B:
4589 return trans_store(ctx, insn, true, MO_TEUL);
4590 case 0x1E:
4591 return trans_fstore_mod(ctx, insn);
4592 case 0x1F:
4593 return trans_store_w(ctx, insn);
4595 case 0x20:
4596 return trans_cmpb(ctx, insn, true, false, false);
4597 case 0x21:
4598 return trans_cmpb(ctx, insn, true, true, false);
4599 case 0x22:
4600 return trans_cmpb(ctx, insn, false, false, false);
4601 case 0x23:
4602 return trans_cmpb(ctx, insn, false, true, false);
4603 case 0x24:
4604 return trans_cmpiclr(ctx, insn);
4605 case 0x25:
4606 return trans_subi(ctx, insn);
4607 case 0x26:
4608 return trans_fmpyadd(ctx, insn, true);
4609 case 0x27:
4610 return trans_cmpb(ctx, insn, true, false, true);
4611 case 0x28:
4612 return trans_addb(ctx, insn, true, false);
4613 case 0x29:
4614 return trans_addb(ctx, insn, true, true);
4615 case 0x2A:
4616 return trans_addb(ctx, insn, false, false);
4617 case 0x2B:
4618 return trans_addb(ctx, insn, false, true);
4619 case 0x2C:
4620 case 0x2D:
4621 return trans_addi(ctx, insn);
4622 case 0x2E:
4623 return translate_table(ctx, insn, table_fp_fused);
4624 case 0x2F:
4625 return trans_cmpb(ctx, insn, false, false, true);
4627 case 0x30:
4628 case 0x31:
4629 return trans_bb(ctx, insn);
4630 case 0x32:
4631 return trans_movb(ctx, insn, false);
4632 case 0x33:
4633 return trans_movb(ctx, insn, true);
4634 case 0x34:
4635 return translate_table(ctx, insn, table_sh_ex);
4636 case 0x35:
4637 return translate_table(ctx, insn, table_depw);
4638 case 0x38:
4639 return trans_be(ctx, insn, false);
4640 case 0x39:
4641 return trans_be(ctx, insn, true);
4642 case 0x3A:
4643 return translate_table(ctx, insn, table_branch);
4645 case 0x04: /* spopn */
4646 case 0x05: /* diag */
4647 case 0x0F: /* product specific */
4648 break;
4650 case 0x07: /* unassigned */
4651 case 0x15: /* unassigned */
4652 case 0x1D: /* unassigned */
4653 case 0x37: /* unassigned */
4654 break;
4655 case 0x3F:
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 */
4664 #endif
4665 break;
4666 default:
4667 break;
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);
4675 int bound;
4677 ctx->cs = cs;
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;
4685 #else
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);
4696 #endif
4697 ctx->iaoq_n = -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);
4704 ctx->ntempr = 0;
4705 ctx->ntempl = 0;
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;
4738 return true;
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;
4745 DisasJumpType ret;
4746 int i, n;
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);
4753 } else
4754 #endif
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) {
4763 ctx->iaoq_n = -1;
4764 ctx->iaoq_n_var = get_temp(ctx);
4765 tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
4766 } else {
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;
4773 ret = DISAS_NEXT;
4774 } else {
4775 ctx->insn = insn;
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;
4790 ctx->ntempr = 0;
4791 ctx->ntempl = 0;
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;
4803 } else {
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) {
4813 return;
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);
4820 #endif
4821 nullify_save(ctx);
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;
4833 switch (is_jmp) {
4834 case DISAS_NORETURN:
4835 break;
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);
4841 nullify_save(ctx);
4842 /* FALLTHRU */
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) {
4847 tcg_gen_exit_tb(0);
4848 } else {
4849 tcg_gen_lookup_and_goto_ptr();
4851 break;
4852 default:
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
4862 switch (pc) {
4863 case 0x00:
4864 qemu_log("IN:\n0x00000000: (null)\n");
4865 return;
4866 case 0xb0:
4867 qemu_log("IN:\n0x000000b0: light-weight-syscall\n");
4868 return;
4869 case 0xe0:
4870 qemu_log("IN:\n0x000000e0: set-thread-pointer-syscall\n");
4871 return;
4872 case 0x100:
4873 qemu_log("IN:\n0x00000100: syscall\n");
4874 return;
4876 #endif
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)
4895 DisasContext ctx;
4896 translator_loop(&hppa_tr_ops, &ctx.base, cs, tb);
4899 void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
4900 target_ulong *data)
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. */
4909 env->psw_n = 0;