1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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/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 "exec/log.h"
31
32
33
34
35#undef TCGv
36#undef tcg_temp_new
37#undef tcg_global_reg_new
38#undef tcg_global_mem_new
39#undef tcg_temp_local_new
40#undef tcg_temp_free
41
42#if TARGET_LONG_BITS == 64
43#define TCGv_tl TCGv_i64
44#define tcg_temp_new_tl tcg_temp_new_i64
45#define tcg_temp_free_tl tcg_temp_free_i64
46#if TARGET_REGISTER_BITS == 64
47#define tcg_gen_extu_reg_tl tcg_gen_mov_i64
48#else
49#define tcg_gen_extu_reg_tl tcg_gen_extu_i32_i64
50#endif
51#else
52#define TCGv_tl TCGv_i32
53#define tcg_temp_new_tl tcg_temp_new_i32
54#define tcg_temp_free_tl tcg_temp_free_i32
55#define tcg_gen_extu_reg_tl tcg_gen_mov_i32
56#endif
57
58#if TARGET_REGISTER_BITS == 64
59#define TCGv_reg TCGv_i64
60
61#define tcg_temp_new tcg_temp_new_i64
62#define tcg_global_reg_new tcg_global_reg_new_i64
63#define tcg_global_mem_new tcg_global_mem_new_i64
64#define tcg_temp_local_new tcg_temp_local_new_i64
65#define tcg_temp_free tcg_temp_free_i64
66
67#define tcg_gen_movi_reg tcg_gen_movi_i64
68#define tcg_gen_mov_reg tcg_gen_mov_i64
69#define tcg_gen_ld8u_reg tcg_gen_ld8u_i64
70#define tcg_gen_ld8s_reg tcg_gen_ld8s_i64
71#define tcg_gen_ld16u_reg tcg_gen_ld16u_i64
72#define tcg_gen_ld16s_reg tcg_gen_ld16s_i64
73#define tcg_gen_ld32u_reg tcg_gen_ld32u_i64
74#define tcg_gen_ld32s_reg tcg_gen_ld32s_i64
75#define tcg_gen_ld_reg tcg_gen_ld_i64
76#define tcg_gen_st8_reg tcg_gen_st8_i64
77#define tcg_gen_st16_reg tcg_gen_st16_i64
78#define tcg_gen_st32_reg tcg_gen_st32_i64
79#define tcg_gen_st_reg tcg_gen_st_i64
80#define tcg_gen_add_reg tcg_gen_add_i64
81#define tcg_gen_addi_reg tcg_gen_addi_i64
82#define tcg_gen_sub_reg tcg_gen_sub_i64
83#define tcg_gen_neg_reg tcg_gen_neg_i64
84#define tcg_gen_subfi_reg tcg_gen_subfi_i64
85#define tcg_gen_subi_reg tcg_gen_subi_i64
86#define tcg_gen_and_reg tcg_gen_and_i64
87#define tcg_gen_andi_reg tcg_gen_andi_i64
88#define tcg_gen_or_reg tcg_gen_or_i64
89#define tcg_gen_ori_reg tcg_gen_ori_i64
90#define tcg_gen_xor_reg tcg_gen_xor_i64
91#define tcg_gen_xori_reg tcg_gen_xori_i64
92#define tcg_gen_not_reg tcg_gen_not_i64
93#define tcg_gen_shl_reg tcg_gen_shl_i64
94#define tcg_gen_shli_reg tcg_gen_shli_i64
95#define tcg_gen_shr_reg tcg_gen_shr_i64
96#define tcg_gen_shri_reg tcg_gen_shri_i64
97#define tcg_gen_sar_reg tcg_gen_sar_i64
98#define tcg_gen_sari_reg tcg_gen_sari_i64
99#define tcg_gen_brcond_reg tcg_gen_brcond_i64
100#define tcg_gen_brcondi_reg tcg_gen_brcondi_i64
101#define tcg_gen_setcond_reg tcg_gen_setcond_i64
102#define tcg_gen_setcondi_reg tcg_gen_setcondi_i64
103#define tcg_gen_mul_reg tcg_gen_mul_i64
104#define tcg_gen_muli_reg tcg_gen_muli_i64
105#define tcg_gen_div_reg tcg_gen_div_i64
106#define tcg_gen_rem_reg tcg_gen_rem_i64
107#define tcg_gen_divu_reg tcg_gen_divu_i64
108#define tcg_gen_remu_reg tcg_gen_remu_i64
109#define tcg_gen_discard_reg tcg_gen_discard_i64
110#define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32
111#define tcg_gen_trunc_i64_reg tcg_gen_mov_i64
112#define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64
113#define tcg_gen_ext_i32_reg tcg_gen_ext_i32_i64
114#define tcg_gen_extu_reg_i64 tcg_gen_mov_i64
115#define tcg_gen_ext_reg_i64 tcg_gen_mov_i64
116#define tcg_gen_ext8u_reg tcg_gen_ext8u_i64
117#define tcg_gen_ext8s_reg tcg_gen_ext8s_i64
118#define tcg_gen_ext16u_reg tcg_gen_ext16u_i64
119#define tcg_gen_ext16s_reg tcg_gen_ext16s_i64
120#define tcg_gen_ext32u_reg tcg_gen_ext32u_i64
121#define tcg_gen_ext32s_reg tcg_gen_ext32s_i64
122#define tcg_gen_bswap16_reg tcg_gen_bswap16_i64
123#define tcg_gen_bswap32_reg tcg_gen_bswap32_i64
124#define tcg_gen_bswap64_reg tcg_gen_bswap64_i64
125#define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64
126#define tcg_gen_andc_reg tcg_gen_andc_i64
127#define tcg_gen_eqv_reg tcg_gen_eqv_i64
128#define tcg_gen_nand_reg tcg_gen_nand_i64
129#define tcg_gen_nor_reg tcg_gen_nor_i64
130#define tcg_gen_orc_reg tcg_gen_orc_i64
131#define tcg_gen_clz_reg tcg_gen_clz_i64
132#define tcg_gen_ctz_reg tcg_gen_ctz_i64
133#define tcg_gen_clzi_reg tcg_gen_clzi_i64
134#define tcg_gen_ctzi_reg tcg_gen_ctzi_i64
135#define tcg_gen_clrsb_reg tcg_gen_clrsb_i64
136#define tcg_gen_ctpop_reg tcg_gen_ctpop_i64
137#define tcg_gen_rotl_reg tcg_gen_rotl_i64
138#define tcg_gen_rotli_reg tcg_gen_rotli_i64
139#define tcg_gen_rotr_reg tcg_gen_rotr_i64
140#define tcg_gen_rotri_reg tcg_gen_rotri_i64
141#define tcg_gen_deposit_reg tcg_gen_deposit_i64
142#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64
143#define tcg_gen_extract_reg tcg_gen_extract_i64
144#define tcg_gen_sextract_reg tcg_gen_sextract_i64
145#define tcg_const_reg tcg_const_i64
146#define tcg_const_local_reg tcg_const_local_i64
147#define tcg_constant_reg tcg_constant_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
162
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_constant_reg tcg_constant_i32
243#define tcg_gen_movcond_reg tcg_gen_movcond_i32
244#define tcg_gen_add2_reg tcg_gen_add2_i32
245#define tcg_gen_sub2_reg tcg_gen_sub2_i32
246#define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i32
247#define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i32
248#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
249#define tcg_gen_trunc_reg_ptr tcg_gen_ext_i32_ptr
250#endif
251
252typedef struct DisasCond {
253 TCGCond c;
254 TCGv_reg a0, a1;
255} DisasCond;
256
257typedef struct DisasContext {
258 DisasContextBase base;
259 CPUState *cs;
260
261 target_ureg iaoq_f;
262 target_ureg iaoq_b;
263 target_ureg iaoq_n;
264 TCGv_reg iaoq_n_var;
265
266 int ntempr, ntempl;
267 TCGv_reg tempr[8];
268 TCGv_tl templ[4];
269
270 DisasCond null_cond;
271 TCGLabel *null_lab;
272
273 uint32_t insn;
274 uint32_t tb_flags;
275 int mmu_idx;
276 int privilege;
277 bool psw_n_nonzero;
278} DisasContext;
279
280
281static int expand_sm_imm(DisasContext *ctx, int val)
282{
283 if (val & PSW_SM_E) {
284 val = (val & ~PSW_SM_E) | PSW_E;
285 }
286 if (val & PSW_SM_W) {
287 val = (val & ~PSW_SM_W) | PSW_W;
288 }
289 return val;
290}
291
292
293static int expand_sr3x(DisasContext *ctx, int val)
294{
295 return ~val;
296}
297
298
299
300static int ma_to_m(DisasContext *ctx, int val)
301{
302 return val & 2 ? (val & 1 ? -1 : 1) : 0;
303}
304
305
306static int pos_to_m(DisasContext *ctx, int val)
307{
308 return val ? 1 : -1;
309}
310
311static int neg_to_m(DisasContext *ctx, int val)
312{
313 return val ? -1 : 1;
314}
315
316
317static int expand_shl2(DisasContext *ctx, int val)
318{
319 return val << 2;
320}
321
322
323static int expand_shl3(DisasContext *ctx, int val)
324{
325 return val << 3;
326}
327
328
329static int expand_shl11(DisasContext *ctx, int val)
330{
331 return val << 11;
332}
333
334
335
336#include "decode-insns.c.inc"
337
338
339
340#define DISAS_IAQ_N_UPDATED DISAS_TARGET_0
341
342
343
344#define DISAS_IAQ_N_STALE DISAS_TARGET_1
345
346
347
348#define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2
349#define DISAS_EXIT DISAS_TARGET_3
350
351
352static TCGv_reg cpu_gr[32];
353static TCGv_i64 cpu_sr[4];
354static TCGv_i64 cpu_srH;
355static TCGv_reg cpu_iaoq_f;
356static TCGv_reg cpu_iaoq_b;
357static TCGv_i64 cpu_iasq_f;
358static TCGv_i64 cpu_iasq_b;
359static TCGv_reg cpu_sar;
360static TCGv_reg cpu_psw_n;
361static TCGv_reg cpu_psw_v;
362static TCGv_reg cpu_psw_cb;
363static TCGv_reg cpu_psw_cb_msb;
364
365#include "exec/gen-icount.h"
366
367void hppa_translate_init(void)
368{
369#define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
370
371 typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar;
372 static const GlobalVar vars[] = {
373 { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) },
374 DEF_VAR(psw_n),
375 DEF_VAR(psw_v),
376 DEF_VAR(psw_cb),
377 DEF_VAR(psw_cb_msb),
378 DEF_VAR(iaoq_f),
379 DEF_VAR(iaoq_b),
380 };
381
382#undef DEF_VAR
383
384
385 static const char gr_names[32][4] = {
386 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
387 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
388 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
389 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
390 };
391
392 static const char sr_names[5][4] = {
393 "sr0", "sr1", "sr2", "sr3", "srH"
394 };
395
396 int i;
397
398 cpu_gr[0] = NULL;
399 for (i = 1; i < 32; i++) {
400 cpu_gr[i] = tcg_global_mem_new(cpu_env,
401 offsetof(CPUHPPAState, gr[i]),
402 gr_names[i]);
403 }
404 for (i = 0; i < 4; i++) {
405 cpu_sr[i] = tcg_global_mem_new_i64(cpu_env,
406 offsetof(CPUHPPAState, sr[i]),
407 sr_names[i]);
408 }
409 cpu_srH = tcg_global_mem_new_i64(cpu_env,
410 offsetof(CPUHPPAState, sr[4]),
411 sr_names[4]);
412
413 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
414 const GlobalVar *v = &vars[i];
415 *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name);
416 }
417
418 cpu_iasq_f = tcg_global_mem_new_i64(cpu_env,
419 offsetof(CPUHPPAState, iasq_f),
420 "iasq_f");
421 cpu_iasq_b = tcg_global_mem_new_i64(cpu_env,
422 offsetof(CPUHPPAState, iasq_b),
423 "iasq_b");
424}
425
426static DisasCond cond_make_f(void)
427{
428 return (DisasCond){
429 .c = TCG_COND_NEVER,
430 .a0 = NULL,
431 .a1 = NULL,
432 };
433}
434
435static DisasCond cond_make_t(void)
436{
437 return (DisasCond){
438 .c = TCG_COND_ALWAYS,
439 .a0 = NULL,
440 .a1 = NULL,
441 };
442}
443
444static DisasCond cond_make_n(void)
445{
446 return (DisasCond){
447 .c = TCG_COND_NE,
448 .a0 = cpu_psw_n,
449 .a1 = tcg_constant_reg(0)
450 };
451}
452
453static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0)
454{
455 assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
456 return (DisasCond){
457 .c = c, .a0 = a0, .a1 = tcg_constant_reg(0)
458 };
459}
460
461static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
462{
463 TCGv_reg tmp = tcg_temp_new();
464 tcg_gen_mov_reg(tmp, a0);
465 return cond_make_0_tmp(c, tmp);
466}
467
468static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
469{
470 DisasCond r = { .c = c };
471
472 assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
473 r.a0 = tcg_temp_new();
474 tcg_gen_mov_reg(r.a0, a0);
475 r.a1 = tcg_temp_new();
476 tcg_gen_mov_reg(r.a1, a1);
477
478 return r;
479}
480
481static void cond_free(DisasCond *cond)
482{
483 switch (cond->c) {
484 default:
485 if (cond->a0 != cpu_psw_n) {
486 tcg_temp_free(cond->a0);
487 }
488 tcg_temp_free(cond->a1);
489 cond->a0 = NULL;
490 cond->a1 = NULL;
491
492 case TCG_COND_ALWAYS:
493 cond->c = TCG_COND_NEVER;
494 break;
495 case TCG_COND_NEVER:
496 break;
497 }
498}
499
500static TCGv_reg get_temp(DisasContext *ctx)
501{
502 unsigned i = ctx->ntempr++;
503 g_assert(i < ARRAY_SIZE(ctx->tempr));
504 return ctx->tempr[i] = tcg_temp_new();
505}
506
507#ifndef CONFIG_USER_ONLY
508static TCGv_tl get_temp_tl(DisasContext *ctx)
509{
510 unsigned i = ctx->ntempl++;
511 g_assert(i < ARRAY_SIZE(ctx->templ));
512 return ctx->templ[i] = tcg_temp_new_tl();
513}
514#endif
515
516static TCGv_reg load_const(DisasContext *ctx, target_sreg v)
517{
518 TCGv_reg t = get_temp(ctx);
519 tcg_gen_movi_reg(t, v);
520 return t;
521}
522
523static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg)
524{
525 if (reg == 0) {
526 TCGv_reg t = get_temp(ctx);
527 tcg_gen_movi_reg(t, 0);
528 return t;
529 } else {
530 return cpu_gr[reg];
531 }
532}
533
534static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg)
535{
536 if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
537 return get_temp(ctx);
538 } else {
539 return cpu_gr[reg];
540 }
541}
542
543static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
544{
545 if (ctx->null_cond.c != TCG_COND_NEVER) {
546 tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0,
547 ctx->null_cond.a1, dest, t);
548 } else {
549 tcg_gen_mov_reg(dest, t);
550 }
551}
552
553static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t)
554{
555 if (reg != 0) {
556 save_or_nullify(ctx, cpu_gr[reg], t);
557 }
558}
559
560#ifdef HOST_WORDS_BIGENDIAN
561# define HI_OFS 0
562# define LO_OFS 4
563#else
564# define HI_OFS 4
565# define LO_OFS 0
566#endif
567
568static TCGv_i32 load_frw_i32(unsigned rt)
569{
570 TCGv_i32 ret = tcg_temp_new_i32();
571 tcg_gen_ld_i32(ret, cpu_env,
572 offsetof(CPUHPPAState, fr[rt & 31])
573 + (rt & 32 ? LO_OFS : HI_OFS));
574 return ret;
575}
576
577static TCGv_i32 load_frw0_i32(unsigned rt)
578{
579 if (rt == 0) {
580 return tcg_const_i32(0);
581 } else {
582 return load_frw_i32(rt);
583 }
584}
585
586static TCGv_i64 load_frw0_i64(unsigned rt)
587{
588 if (rt == 0) {
589 return tcg_const_i64(0);
590 } else {
591 TCGv_i64 ret = tcg_temp_new_i64();
592 tcg_gen_ld32u_i64(ret, cpu_env,
593 offsetof(CPUHPPAState, fr[rt & 31])
594 + (rt & 32 ? LO_OFS : HI_OFS));
595 return ret;
596 }
597}
598
599static void save_frw_i32(unsigned rt, TCGv_i32 val)
600{
601 tcg_gen_st_i32(val, cpu_env,
602 offsetof(CPUHPPAState, fr[rt & 31])
603 + (rt & 32 ? LO_OFS : HI_OFS));
604}
605
606#undef HI_OFS
607#undef LO_OFS
608
609static TCGv_i64 load_frd(unsigned rt)
610{
611 TCGv_i64 ret = tcg_temp_new_i64();
612 tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt]));
613 return ret;
614}
615
616static TCGv_i64 load_frd0(unsigned rt)
617{
618 if (rt == 0) {
619 return tcg_const_i64(0);
620 } else {
621 return load_frd(rt);
622 }
623}
624
625static void save_frd(unsigned rt, TCGv_i64 val)
626{
627 tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
628}
629
630static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
631{
632#ifdef CONFIG_USER_ONLY
633 tcg_gen_movi_i64(dest, 0);
634#else
635 if (reg < 4) {
636 tcg_gen_mov_i64(dest, cpu_sr[reg]);
637 } else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
638 tcg_gen_mov_i64(dest, cpu_srH);
639 } else {
640 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
641 }
642#endif
643}
644
645
646
647static void nullify_over(DisasContext *ctx)
648{
649 if (ctx->null_cond.c != TCG_COND_NEVER) {
650
651 assert(ctx->null_cond.c != TCG_COND_ALWAYS);
652
653 ctx->null_lab = gen_new_label();
654
655
656 if (ctx->null_cond.a0 == cpu_psw_n) {
657 ctx->null_cond.a0 = tcg_temp_new();
658 tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
659 }
660
661
662
663 if (ctx->psw_n_nonzero) {
664 ctx->psw_n_nonzero = false;
665 tcg_gen_movi_reg(cpu_psw_n, 0);
666 }
667
668 tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0,
669 ctx->null_cond.a1, ctx->null_lab);
670 cond_free(&ctx->null_cond);
671 }
672}
673
674
675static void nullify_save(DisasContext *ctx)
676{
677 if (ctx->null_cond.c == TCG_COND_NEVER) {
678 if (ctx->psw_n_nonzero) {
679 tcg_gen_movi_reg(cpu_psw_n, 0);
680 }
681 return;
682 }
683 if (ctx->null_cond.a0 != cpu_psw_n) {
684 tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n,
685 ctx->null_cond.a0, ctx->null_cond.a1);
686 ctx->psw_n_nonzero = true;
687 }
688 cond_free(&ctx->null_cond);
689}
690
691
692
693
694static void nullify_set(DisasContext *ctx, bool x)
695{
696 if (ctx->psw_n_nonzero || x) {
697 tcg_gen_movi_reg(cpu_psw_n, x);
698 }
699}
700
701
702
703
704static bool nullify_end(DisasContext *ctx)
705{
706 TCGLabel *null_lab = ctx->null_lab;
707 DisasJumpType status = ctx->base.is_jmp;
708
709
710
711 assert(status != DISAS_IAQ_N_UPDATED);
712
713 if (likely(null_lab == NULL)) {
714
715
716
717 return true;
718 }
719 ctx->null_lab = NULL;
720
721 if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
722
723
724 gen_set_label(null_lab);
725 } else {
726
727
728
729
730 nullify_save(ctx);
731 gen_set_label(null_lab);
732 ctx->null_cond = cond_make_n();
733 }
734 if (status == DISAS_NORETURN) {
735 ctx->base.is_jmp = DISAS_NEXT;
736 }
737 return true;
738}
739
740static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
741{
742 if (unlikely(ival == -1)) {
743 tcg_gen_mov_reg(dest, vval);
744 } else {
745 tcg_gen_movi_reg(dest, ival);
746 }
747}
748
749static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp)
750{
751 return ctx->iaoq_f + disp + 8;
752}
753
754static void gen_excp_1(int exception)
755{
756 gen_helper_excp(cpu_env, tcg_constant_i32(exception));
757}
758
759static void gen_excp(DisasContext *ctx, int exception)
760{
761 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
762 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
763 nullify_save(ctx);
764 gen_excp_1(exception);
765 ctx->base.is_jmp = DISAS_NORETURN;
766}
767
768static bool gen_excp_iir(DisasContext *ctx, int exc)
769{
770 nullify_over(ctx);
771 tcg_gen_st_reg(tcg_constant_reg(ctx->insn),
772 cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
773 gen_excp(ctx, exc);
774 return nullify_end(ctx);
775}
776
777static bool gen_illegal(DisasContext *ctx)
778{
779 return gen_excp_iir(ctx, EXCP_ILL);
780}
781
782#ifdef CONFIG_USER_ONLY
783#define CHECK_MOST_PRIVILEGED(EXCP) \
784 return gen_excp_iir(ctx, EXCP)
785#else
786#define CHECK_MOST_PRIVILEGED(EXCP) \
787 do { \
788 if (ctx->privilege != 0) { \
789 return gen_excp_iir(ctx, EXCP); \
790 } \
791 } while (0)
792#endif
793
794static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
795{
796 return translator_use_goto_tb(&ctx->base, dest);
797}
798
799
800
801
802
803static bool use_nullify_skip(DisasContext *ctx)
804{
805 return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
806 && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
807}
808
809static void gen_goto_tb(DisasContext *ctx, int which,
810 target_ureg f, target_ureg b)
811{
812 if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
813 tcg_gen_goto_tb(which);
814 tcg_gen_movi_reg(cpu_iaoq_f, f);
815 tcg_gen_movi_reg(cpu_iaoq_b, b);
816 tcg_gen_exit_tb(ctx->base.tb, which);
817 } else {
818 copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
819 copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
820 if (ctx->base.singlestep_enabled) {
821 gen_excp_1(EXCP_DEBUG);
822 } else {
823 tcg_gen_lookup_and_goto_ptr();
824 }
825 }
826}
827
828static bool cond_need_sv(int c)
829{
830 return c == 2 || c == 3 || c == 6;
831}
832
833static bool cond_need_cb(int c)
834{
835 return c == 4 || c == 5;
836}
837
838
839
840
841
842
843static DisasCond do_cond(unsigned cf, TCGv_reg res,
844 TCGv_reg cb_msb, TCGv_reg sv)
845{
846 DisasCond cond;
847 TCGv_reg tmp;
848
849 switch (cf >> 1) {
850 case 0:
851 cond = cond_make_f();
852 break;
853 case 1:
854 cond = cond_make_0(TCG_COND_EQ, res);
855 break;
856 case 2:
857 tmp = tcg_temp_new();
858 tcg_gen_xor_reg(tmp, res, sv);
859 cond = cond_make_0_tmp(TCG_COND_LT, tmp);
860 break;
861 case 3:
862
863
864
865
866
867
868
869
870
871 tmp = tcg_temp_new();
872 tcg_gen_eqv_reg(tmp, res, sv);
873 tcg_gen_sari_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
874 tcg_gen_and_reg(tmp, tmp, res);
875 cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
876 break;
877 case 4:
878 cond = cond_make_0(TCG_COND_EQ, cb_msb);
879 break;
880 case 5:
881 tmp = tcg_temp_new();
882 tcg_gen_neg_reg(tmp, cb_msb);
883 tcg_gen_and_reg(tmp, tmp, res);
884 cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
885 break;
886 case 6:
887 cond = cond_make_0(TCG_COND_LT, sv);
888 break;
889 case 7:
890 tmp = tcg_temp_new();
891 tcg_gen_andi_reg(tmp, res, 1);
892 cond = cond_make_0_tmp(TCG_COND_NE, tmp);
893 break;
894 default:
895 g_assert_not_reached();
896 }
897 if (cf & 1) {
898 cond.c = tcg_invert_cond(cond.c);
899 }
900
901 return cond;
902}
903
904
905
906
907
908static DisasCond do_sub_cond(unsigned cf, TCGv_reg res,
909 TCGv_reg in1, TCGv_reg in2, TCGv_reg sv)
910{
911 DisasCond cond;
912
913 switch (cf >> 1) {
914 case 1:
915 cond = cond_make(TCG_COND_EQ, in1, in2);
916 break;
917 case 2:
918 cond = cond_make(TCG_COND_LT, in1, in2);
919 break;
920 case 3:
921 cond = cond_make(TCG_COND_LE, in1, in2);
922 break;
923 case 4:
924 cond = cond_make(TCG_COND_LTU, in1, in2);
925 break;
926 case 5:
927 cond = cond_make(TCG_COND_LEU, in1, in2);
928 break;
929 default:
930 return do_cond(cf, res, NULL, sv);
931 }
932 if (cf & 1) {
933 cond.c = tcg_invert_cond(cond.c);
934 }
935
936 return cond;
937}
938
939
940
941
942
943
944
945
946
947
948static DisasCond do_log_cond(unsigned cf, TCGv_reg res)
949{
950 switch (cf) {
951 case 0:
952 case 9:
953 case 11:
954 case 12:
955 return cond_make_f();
956
957 case 1:
958 case 8:
959 case 10:
960 case 13:
961 return cond_make_t();
962
963 case 2:
964 return cond_make_0(TCG_COND_EQ, res);
965 case 3:
966 return cond_make_0(TCG_COND_NE, res);
967 case 4:
968 return cond_make_0(TCG_COND_LT, res);
969 case 5:
970 return cond_make_0(TCG_COND_GE, res);
971 case 6:
972 return cond_make_0(TCG_COND_LE, res);
973 case 7:
974 return cond_make_0(TCG_COND_GT, res);
975
976 case 14:
977 case 15:
978 return do_cond(cf, res, NULL, NULL);
979
980 default:
981 g_assert_not_reached();
982 }
983}
984
985
986
987static DisasCond do_sed_cond(unsigned orig, TCGv_reg res)
988{
989 unsigned c, f;
990
991
992
993
994 c = orig & 3;
995 if (c == 3) {
996 c = 7;
997 }
998 f = (orig & 4) / 4;
999
1000 return do_log_cond(c * 2 + f, res);
1001}
1002
1003
1004
1005static DisasCond do_unit_cond(unsigned cf, TCGv_reg res,
1006 TCGv_reg in1, TCGv_reg in2)
1007{
1008 DisasCond cond;
1009 TCGv_reg tmp, cb = NULL;
1010
1011 if (cf & 8) {
1012
1013
1014
1015
1016 cb = tcg_temp_new();
1017 tmp = tcg_temp_new();
1018 tcg_gen_or_reg(cb, in1, in2);
1019 tcg_gen_and_reg(tmp, in1, in2);
1020 tcg_gen_andc_reg(cb, cb, res);
1021 tcg_gen_or_reg(cb, cb, tmp);
1022 tcg_temp_free(tmp);
1023 }
1024
1025 switch (cf >> 1) {
1026 case 0:
1027 case 1:
1028 case 5:
1029 cond = cond_make_f();
1030 break;
1031
1032 case 2:
1033
1034
1035
1036 tmp = tcg_temp_new();
1037 tcg_gen_subi_reg(tmp, res, 0x01010101u);
1038 tcg_gen_andc_reg(tmp, tmp, res);
1039 tcg_gen_andi_reg(tmp, tmp, 0x80808080u);
1040 cond = cond_make_0(TCG_COND_NE, tmp);
1041 tcg_temp_free(tmp);
1042 break;
1043
1044 case 3:
1045 tmp = tcg_temp_new();
1046 tcg_gen_subi_reg(tmp, res, 0x00010001u);
1047 tcg_gen_andc_reg(tmp, tmp, res);
1048 tcg_gen_andi_reg(tmp, tmp, 0x80008000u);
1049 cond = cond_make_0(TCG_COND_NE, tmp);
1050 tcg_temp_free(tmp);
1051 break;
1052
1053 case 4:
1054 tcg_gen_andi_reg(cb, cb, 0x88888888u);
1055 cond = cond_make_0(TCG_COND_NE, cb);
1056 break;
1057
1058 case 6:
1059 tcg_gen_andi_reg(cb, cb, 0x80808080u);
1060 cond = cond_make_0(TCG_COND_NE, cb);
1061 break;
1062
1063 case 7:
1064 tcg_gen_andi_reg(cb, cb, 0x80008000u);
1065 cond = cond_make_0(TCG_COND_NE, cb);
1066 break;
1067
1068 default:
1069 g_assert_not_reached();
1070 }
1071 if (cf & 8) {
1072 tcg_temp_free(cb);
1073 }
1074 if (cf & 1) {
1075 cond.c = tcg_invert_cond(cond.c);
1076 }
1077
1078 return cond;
1079}
1080
1081
1082static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res,
1083 TCGv_reg in1, TCGv_reg in2)
1084{
1085 TCGv_reg sv = get_temp(ctx);
1086 TCGv_reg tmp = tcg_temp_new();
1087
1088 tcg_gen_xor_reg(sv, res, in1);
1089 tcg_gen_xor_reg(tmp, in1, in2);
1090 tcg_gen_andc_reg(sv, sv, tmp);
1091 tcg_temp_free(tmp);
1092
1093 return sv;
1094}
1095
1096
1097static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res,
1098 TCGv_reg in1, TCGv_reg in2)
1099{
1100 TCGv_reg sv = get_temp(ctx);
1101 TCGv_reg tmp = tcg_temp_new();
1102
1103 tcg_gen_xor_reg(sv, res, in1);
1104 tcg_gen_xor_reg(tmp, in1, in2);
1105 tcg_gen_and_reg(sv, sv, tmp);
1106 tcg_temp_free(tmp);
1107
1108 return sv;
1109}
1110
1111static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1112 TCGv_reg in2, unsigned shift, bool is_l,
1113 bool is_tsv, bool is_tc, bool is_c, unsigned cf)
1114{
1115 TCGv_reg dest, cb, cb_msb, sv, tmp;
1116 unsigned c = cf >> 1;
1117 DisasCond cond;
1118
1119 dest = tcg_temp_new();
1120 cb = NULL;
1121 cb_msb = NULL;
1122
1123 if (shift) {
1124 tmp = get_temp(ctx);
1125 tcg_gen_shli_reg(tmp, in1, shift);
1126 in1 = tmp;
1127 }
1128
1129 if (!is_l || cond_need_cb(c)) {
1130 TCGv_reg zero = tcg_constant_reg(0);
1131 cb_msb = get_temp(ctx);
1132 tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
1133 if (is_c) {
1134 tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
1135 }
1136 if (!is_l) {
1137 cb = get_temp(ctx);
1138 tcg_gen_xor_reg(cb, in1, in2);
1139 tcg_gen_xor_reg(cb, cb, dest);
1140 }
1141 } else {
1142 tcg_gen_add_reg(dest, in1, in2);
1143 if (is_c) {
1144 tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
1145 }
1146 }
1147
1148
1149 sv = NULL;
1150 if (is_tsv || cond_need_sv(c)) {
1151 sv = do_add_sv(ctx, dest, in1, in2);
1152 if (is_tsv) {
1153
1154 gen_helper_tsv(cpu_env, sv);
1155 }
1156 }
1157
1158
1159 cond = do_cond(cf, dest, cb_msb, sv);
1160 if (is_tc) {
1161 tmp = tcg_temp_new();
1162 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1163 gen_helper_tcond(cpu_env, tmp);
1164 tcg_temp_free(tmp);
1165 }
1166
1167
1168 if (!is_l) {
1169 save_or_nullify(ctx, cpu_psw_cb, cb);
1170 save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1171 }
1172 save_gpr(ctx, rt, dest);
1173 tcg_temp_free(dest);
1174
1175
1176 cond_free(&ctx->null_cond);
1177 ctx->null_cond = cond;
1178}
1179
1180static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_sh *a,
1181 bool is_l, bool is_tsv, bool is_tc, bool is_c)
1182{
1183 TCGv_reg tcg_r1, tcg_r2;
1184
1185 if (a->cf) {
1186 nullify_over(ctx);
1187 }
1188 tcg_r1 = load_gpr(ctx, a->r1);
1189 tcg_r2 = load_gpr(ctx, a->r2);
1190 do_add(ctx, a->t, tcg_r1, tcg_r2, a->sh, is_l, is_tsv, is_tc, is_c, a->cf);
1191 return nullify_end(ctx);
1192}
1193
1194static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
1195 bool is_tsv, bool is_tc)
1196{
1197 TCGv_reg tcg_im, tcg_r2;
1198
1199 if (a->cf) {
1200 nullify_over(ctx);
1201 }
1202 tcg_im = load_const(ctx, a->i);
1203 tcg_r2 = load_gpr(ctx, a->r);
1204 do_add(ctx, a->t, tcg_im, tcg_r2, 0, 0, is_tsv, is_tc, 0, a->cf);
1205 return nullify_end(ctx);
1206}
1207
1208static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1209 TCGv_reg in2, bool is_tsv, bool is_b,
1210 bool is_tc, unsigned cf)
1211{
1212 TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
1213 unsigned c = cf >> 1;
1214 DisasCond cond;
1215
1216 dest = tcg_temp_new();
1217 cb = tcg_temp_new();
1218 cb_msb = tcg_temp_new();
1219
1220 zero = tcg_constant_reg(0);
1221 if (is_b) {
1222
1223 tcg_gen_not_reg(cb, in2);
1224 tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
1225 tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
1226 tcg_gen_xor_reg(cb, cb, in1);
1227 tcg_gen_xor_reg(cb, cb, dest);
1228 } else {
1229
1230
1231 tcg_gen_movi_reg(cb_msb, 1);
1232 tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero);
1233 tcg_gen_eqv_reg(cb, in1, in2);
1234 tcg_gen_xor_reg(cb, cb, dest);
1235 }
1236
1237
1238 sv = NULL;
1239 if (is_tsv || cond_need_sv(c)) {
1240 sv = do_sub_sv(ctx, dest, in1, in2);
1241 if (is_tsv) {
1242 gen_helper_tsv(cpu_env, sv);
1243 }
1244 }
1245
1246
1247 if (!is_b) {
1248 cond = do_sub_cond(cf, dest, in1, in2, sv);
1249 } else {
1250 cond = do_cond(cf, dest, cb_msb, sv);
1251 }
1252
1253
1254 if (is_tc) {
1255 tmp = tcg_temp_new();
1256 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1257 gen_helper_tcond(cpu_env, tmp);
1258 tcg_temp_free(tmp);
1259 }
1260
1261
1262 save_or_nullify(ctx, cpu_psw_cb, cb);
1263 save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1264 save_gpr(ctx, rt, dest);
1265 tcg_temp_free(dest);
1266 tcg_temp_free(cb);
1267 tcg_temp_free(cb_msb);
1268
1269
1270 cond_free(&ctx->null_cond);
1271 ctx->null_cond = cond;
1272}
1273
1274static bool do_sub_reg(DisasContext *ctx, arg_rrr_cf *a,
1275 bool is_tsv, bool is_b, bool is_tc)
1276{
1277 TCGv_reg tcg_r1, tcg_r2;
1278
1279 if (a->cf) {
1280 nullify_over(ctx);
1281 }
1282 tcg_r1 = load_gpr(ctx, a->r1);
1283 tcg_r2 = load_gpr(ctx, a->r2);
1284 do_sub(ctx, a->t, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, a->cf);
1285 return nullify_end(ctx);
1286}
1287
1288static bool do_sub_imm(DisasContext *ctx, arg_rri_cf *a, bool is_tsv)
1289{
1290 TCGv_reg tcg_im, tcg_r2;
1291
1292 if (a->cf) {
1293 nullify_over(ctx);
1294 }
1295 tcg_im = load_const(ctx, a->i);
1296 tcg_r2 = load_gpr(ctx, a->r);
1297 do_sub(ctx, a->t, tcg_im, tcg_r2, is_tsv, 0, 0, a->cf);
1298 return nullify_end(ctx);
1299}
1300
1301static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1302 TCGv_reg in2, unsigned cf)
1303{
1304 TCGv_reg dest, sv;
1305 DisasCond cond;
1306
1307 dest = tcg_temp_new();
1308 tcg_gen_sub_reg(dest, in1, in2);
1309
1310
1311 sv = NULL;
1312 if (cond_need_sv(cf >> 1)) {
1313 sv = do_sub_sv(ctx, dest, in1, in2);
1314 }
1315
1316
1317 cond = do_sub_cond(cf, dest, in1, in2, sv);
1318
1319
1320 tcg_gen_movi_reg(dest, 0);
1321 save_gpr(ctx, rt, dest);
1322 tcg_temp_free(dest);
1323
1324
1325 cond_free(&ctx->null_cond);
1326 ctx->null_cond = cond;
1327}
1328
1329static void do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1330 TCGv_reg in2, unsigned cf,
1331 void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1332{
1333 TCGv_reg dest = dest_gpr(ctx, rt);
1334
1335
1336 fn(dest, in1, in2);
1337 save_gpr(ctx, rt, dest);
1338
1339
1340 cond_free(&ctx->null_cond);
1341 if (cf) {
1342 ctx->null_cond = do_log_cond(cf, dest);
1343 }
1344}
1345
1346static bool do_log_reg(DisasContext *ctx, arg_rrr_cf *a,
1347 void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1348{
1349 TCGv_reg tcg_r1, tcg_r2;
1350
1351 if (a->cf) {
1352 nullify_over(ctx);
1353 }
1354 tcg_r1 = load_gpr(ctx, a->r1);
1355 tcg_r2 = load_gpr(ctx, a->r2);
1356 do_log(ctx, a->t, tcg_r1, tcg_r2, a->cf, fn);
1357 return nullify_end(ctx);
1358}
1359
1360static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1361 TCGv_reg in2, unsigned cf, bool is_tc,
1362 void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1363{
1364 TCGv_reg dest;
1365 DisasCond cond;
1366
1367 if (cf == 0) {
1368 dest = dest_gpr(ctx, rt);
1369 fn(dest, in1, in2);
1370 save_gpr(ctx, rt, dest);
1371 cond_free(&ctx->null_cond);
1372 } else {
1373 dest = tcg_temp_new();
1374 fn(dest, in1, in2);
1375
1376 cond = do_unit_cond(cf, dest, in1, in2);
1377
1378 if (is_tc) {
1379 TCGv_reg tmp = tcg_temp_new();
1380 tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1381 gen_helper_tcond(cpu_env, tmp);
1382 tcg_temp_free(tmp);
1383 }
1384 save_gpr(ctx, rt, dest);
1385
1386 cond_free(&ctx->null_cond);
1387 ctx->null_cond = cond;
1388 }
1389}
1390
1391#ifndef CONFIG_USER_ONLY
1392
1393
1394
1395
1396static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base)
1397{
1398 TCGv_ptr ptr;
1399 TCGv_reg tmp;
1400 TCGv_i64 spc;
1401
1402 if (sp != 0) {
1403 if (sp < 0) {
1404 sp = ~sp;
1405 }
1406 spc = get_temp_tl(ctx);
1407 load_spr(ctx, spc, sp);
1408 return spc;
1409 }
1410 if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1411 return cpu_srH;
1412 }
1413
1414 ptr = tcg_temp_new_ptr();
1415 tmp = tcg_temp_new();
1416 spc = get_temp_tl(ctx);
1417
1418 tcg_gen_shri_reg(tmp, base, TARGET_REGISTER_BITS - 5);
1419 tcg_gen_andi_reg(tmp, tmp, 030);
1420 tcg_gen_trunc_reg_ptr(ptr, tmp);
1421 tcg_temp_free(tmp);
1422
1423 tcg_gen_add_ptr(ptr, ptr, cpu_env);
1424 tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
1425 tcg_temp_free_ptr(ptr);
1426
1427 return spc;
1428}
1429#endif
1430
1431static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs,
1432 unsigned rb, unsigned rx, int scale, target_sreg disp,
1433 unsigned sp, int modify, bool is_phys)
1434{
1435 TCGv_reg base = load_gpr(ctx, rb);
1436 TCGv_reg ofs;
1437
1438
1439 if (rx) {
1440 ofs = get_temp(ctx);
1441 tcg_gen_shli_reg(ofs, cpu_gr[rx], scale);
1442 tcg_gen_add_reg(ofs, ofs, base);
1443 } else if (disp || modify) {
1444 ofs = get_temp(ctx);
1445 tcg_gen_addi_reg(ofs, base, disp);
1446 } else {
1447 ofs = base;
1448 }
1449
1450 *pofs = ofs;
1451#ifdef CONFIG_USER_ONLY
1452 *pgva = (modify <= 0 ? ofs : base);
1453#else
1454 TCGv_tl addr = get_temp_tl(ctx);
1455 tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base);
1456 if (ctx->tb_flags & PSW_W) {
1457 tcg_gen_andi_tl(addr, addr, 0x3fffffffffffffffull);
1458 }
1459 if (!is_phys) {
1460 tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base));
1461 }
1462 *pgva = addr;
1463#endif
1464}
1465
1466
1467
1468
1469
1470
1471static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1472 unsigned rx, int scale, target_sreg disp,
1473 unsigned sp, int modify, MemOp mop)
1474{
1475 TCGv_reg ofs;
1476 TCGv_tl addr;
1477
1478
1479 assert(ctx->null_cond.c == TCG_COND_NEVER);
1480
1481 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1482 ctx->mmu_idx == MMU_PHYS_IDX);
1483 tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop);
1484 if (modify) {
1485 save_gpr(ctx, rb, ofs);
1486 }
1487}
1488
1489static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1490 unsigned rx, int scale, target_sreg disp,
1491 unsigned sp, int modify, MemOp mop)
1492{
1493 TCGv_reg ofs;
1494 TCGv_tl addr;
1495
1496
1497 assert(ctx->null_cond.c == TCG_COND_NEVER);
1498
1499 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1500 ctx->mmu_idx == MMU_PHYS_IDX);
1501 tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
1502 if (modify) {
1503 save_gpr(ctx, rb, ofs);
1504 }
1505}
1506
1507static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1508 unsigned rx, int scale, target_sreg disp,
1509 unsigned sp, int modify, MemOp mop)
1510{
1511 TCGv_reg ofs;
1512 TCGv_tl addr;
1513
1514
1515 assert(ctx->null_cond.c == TCG_COND_NEVER);
1516
1517 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1518 ctx->mmu_idx == MMU_PHYS_IDX);
1519 tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop);
1520 if (modify) {
1521 save_gpr(ctx, rb, ofs);
1522 }
1523}
1524
1525static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1526 unsigned rx, int scale, target_sreg disp,
1527 unsigned sp, int modify, MemOp mop)
1528{
1529 TCGv_reg ofs;
1530 TCGv_tl addr;
1531
1532
1533 assert(ctx->null_cond.c == TCG_COND_NEVER);
1534
1535 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1536 ctx->mmu_idx == MMU_PHYS_IDX);
1537 tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop);
1538 if (modify) {
1539 save_gpr(ctx, rb, ofs);
1540 }
1541}
1542
1543#if TARGET_REGISTER_BITS == 64
1544#define do_load_reg do_load_64
1545#define do_store_reg do_store_64
1546#else
1547#define do_load_reg do_load_32
1548#define do_store_reg do_store_32
1549#endif
1550
1551static bool do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1552 unsigned rx, int scale, target_sreg disp,
1553 unsigned sp, int modify, MemOp mop)
1554{
1555 TCGv_reg dest;
1556
1557 nullify_over(ctx);
1558
1559 if (modify == 0) {
1560
1561 dest = dest_gpr(ctx, rt);
1562 } else {
1563
1564 dest = get_temp(ctx);
1565 }
1566 do_load_reg(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
1567 save_gpr(ctx, rt, dest);
1568
1569 return nullify_end(ctx);
1570}
1571
1572static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1573 unsigned rx, int scale, target_sreg disp,
1574 unsigned sp, int modify)
1575{
1576 TCGv_i32 tmp;
1577
1578 nullify_over(ctx);
1579
1580 tmp = tcg_temp_new_i32();
1581 do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1582 save_frw_i32(rt, tmp);
1583 tcg_temp_free_i32(tmp);
1584
1585 if (rt == 0) {
1586 gen_helper_loaded_fr0(cpu_env);
1587 }
1588
1589 return nullify_end(ctx);
1590}
1591
1592static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
1593{
1594 return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1595 a->disp, a->sp, a->m);
1596}
1597
1598static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1599 unsigned rx, int scale, target_sreg disp,
1600 unsigned sp, int modify)
1601{
1602 TCGv_i64 tmp;
1603
1604 nullify_over(ctx);
1605
1606 tmp = tcg_temp_new_i64();
1607 do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1608 save_frd(rt, tmp);
1609 tcg_temp_free_i64(tmp);
1610
1611 if (rt == 0) {
1612 gen_helper_loaded_fr0(cpu_env);
1613 }
1614
1615 return nullify_end(ctx);
1616}
1617
1618static bool trans_fldd(DisasContext *ctx, arg_ldst *a)
1619{
1620 return do_floadd(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1621 a->disp, a->sp, a->m);
1622}
1623
1624static bool do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1625 target_sreg disp, unsigned sp,
1626 int modify, MemOp mop)
1627{
1628 nullify_over(ctx);
1629 do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
1630 return nullify_end(ctx);
1631}
1632
1633static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1634 unsigned rx, int scale, target_sreg disp,
1635 unsigned sp, int modify)
1636{
1637 TCGv_i32 tmp;
1638
1639 nullify_over(ctx);
1640
1641 tmp = load_frw_i32(rt);
1642 do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1643 tcg_temp_free_i32(tmp);
1644
1645 return nullify_end(ctx);
1646}
1647
1648static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
1649{
1650 return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1651 a->disp, a->sp, a->m);
1652}
1653
1654static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1655 unsigned rx, int scale, target_sreg disp,
1656 unsigned sp, int modify)
1657{
1658 TCGv_i64 tmp;
1659
1660 nullify_over(ctx);
1661
1662 tmp = load_frd(rt);
1663 do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1664 tcg_temp_free_i64(tmp);
1665
1666 return nullify_end(ctx);
1667}
1668
1669static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
1670{
1671 return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1672 a->disp, a->sp, a->m);
1673}
1674
1675static bool do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1676 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1677{
1678 TCGv_i32 tmp;
1679
1680 nullify_over(ctx);
1681 tmp = load_frw0_i32(ra);
1682
1683 func(tmp, cpu_env, tmp);
1684
1685 save_frw_i32(rt, tmp);
1686 tcg_temp_free_i32(tmp);
1687 return nullify_end(ctx);
1688}
1689
1690static bool do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1691 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1692{
1693 TCGv_i32 dst;
1694 TCGv_i64 src;
1695
1696 nullify_over(ctx);
1697 src = load_frd(ra);
1698 dst = tcg_temp_new_i32();
1699
1700 func(dst, cpu_env, src);
1701
1702 tcg_temp_free_i64(src);
1703 save_frw_i32(rt, dst);
1704 tcg_temp_free_i32(dst);
1705 return nullify_end(ctx);
1706}
1707
1708static bool do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1709 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1710{
1711 TCGv_i64 tmp;
1712
1713 nullify_over(ctx);
1714 tmp = load_frd0(ra);
1715
1716 func(tmp, cpu_env, tmp);
1717
1718 save_frd(rt, tmp);
1719 tcg_temp_free_i64(tmp);
1720 return nullify_end(ctx);
1721}
1722
1723static bool do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1724 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1725{
1726 TCGv_i32 src;
1727 TCGv_i64 dst;
1728
1729 nullify_over(ctx);
1730 src = load_frw0_i32(ra);
1731 dst = tcg_temp_new_i64();
1732
1733 func(dst, cpu_env, src);
1734
1735 tcg_temp_free_i32(src);
1736 save_frd(rt, dst);
1737 tcg_temp_free_i64(dst);
1738 return nullify_end(ctx);
1739}
1740
1741static bool do_fop_weww(DisasContext *ctx, unsigned rt,
1742 unsigned ra, unsigned rb,
1743 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
1744{
1745 TCGv_i32 a, b;
1746
1747 nullify_over(ctx);
1748 a = load_frw0_i32(ra);
1749 b = load_frw0_i32(rb);
1750
1751 func(a, cpu_env, a, b);
1752
1753 tcg_temp_free_i32(b);
1754 save_frw_i32(rt, a);
1755 tcg_temp_free_i32(a);
1756 return nullify_end(ctx);
1757}
1758
1759static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
1760 unsigned ra, unsigned rb,
1761 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1762{
1763 TCGv_i64 a, b;
1764
1765 nullify_over(ctx);
1766 a = load_frd0(ra);
1767 b = load_frd0(rb);
1768
1769 func(a, cpu_env, a, b);
1770
1771 tcg_temp_free_i64(b);
1772 save_frd(rt, a);
1773 tcg_temp_free_i64(a);
1774 return nullify_end(ctx);
1775}
1776
1777
1778
1779static bool do_dbranch(DisasContext *ctx, target_ureg dest,
1780 unsigned link, bool is_n)
1781{
1782 if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1783 if (link != 0) {
1784 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1785 }
1786 ctx->iaoq_n = dest;
1787 if (is_n) {
1788 ctx->null_cond.c = TCG_COND_ALWAYS;
1789 }
1790 } else {
1791 nullify_over(ctx);
1792
1793 if (link != 0) {
1794 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1795 }
1796
1797 if (is_n && use_nullify_skip(ctx)) {
1798 nullify_set(ctx, 0);
1799 gen_goto_tb(ctx, 0, dest, dest + 4);
1800 } else {
1801 nullify_set(ctx, is_n);
1802 gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
1803 }
1804
1805 nullify_end(ctx);
1806
1807 nullify_set(ctx, 0);
1808 gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1809 ctx->base.is_jmp = DISAS_NORETURN;
1810 }
1811 return true;
1812}
1813
1814
1815
1816static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
1817 DisasCond *cond)
1818{
1819 target_ureg dest = iaoq_dest(ctx, disp);
1820 TCGLabel *taken = NULL;
1821 TCGCond c = cond->c;
1822 bool n;
1823
1824 assert(ctx->null_cond.c == TCG_COND_NEVER);
1825
1826
1827 if (c == TCG_COND_ALWAYS) {
1828 return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
1829 }
1830 if (c == TCG_COND_NEVER) {
1831 return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
1832 }
1833
1834 taken = gen_new_label();
1835 tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
1836 cond_free(cond);
1837
1838
1839 n = is_n && disp < 0;
1840 if (n && use_nullify_skip(ctx)) {
1841 nullify_set(ctx, 0);
1842 gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
1843 } else {
1844 if (!n && ctx->null_lab) {
1845 gen_set_label(ctx->null_lab);
1846 ctx->null_lab = NULL;
1847 }
1848 nullify_set(ctx, n);
1849 if (ctx->iaoq_n == -1) {
1850
1851
1852 tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
1853 }
1854 gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
1855 }
1856
1857 gen_set_label(taken);
1858
1859
1860 n = is_n && disp >= 0;
1861 if (n && use_nullify_skip(ctx)) {
1862 nullify_set(ctx, 0);
1863 gen_goto_tb(ctx, 1, dest, dest + 4);
1864 } else {
1865 nullify_set(ctx, n);
1866 gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
1867 }
1868
1869
1870 if (ctx->null_lab) {
1871 gen_set_label(ctx->null_lab);
1872 ctx->null_lab = NULL;
1873 ctx->base.is_jmp = DISAS_IAQ_N_STALE;
1874 } else {
1875 ctx->base.is_jmp = DISAS_NORETURN;
1876 }
1877 return true;
1878}
1879
1880
1881
1882static bool do_ibranch(DisasContext *ctx, TCGv_reg dest,
1883 unsigned link, bool is_n)
1884{
1885 TCGv_reg a0, a1, next, tmp;
1886 TCGCond c;
1887
1888 assert(ctx->null_lab == NULL);
1889
1890 if (ctx->null_cond.c == TCG_COND_NEVER) {
1891 if (link != 0) {
1892 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1893 }
1894 next = get_temp(ctx);
1895 tcg_gen_mov_reg(next, dest);
1896 if (is_n) {
1897 if (use_nullify_skip(ctx)) {
1898 tcg_gen_mov_reg(cpu_iaoq_f, next);
1899 tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
1900 nullify_set(ctx, 0);
1901 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
1902 return true;
1903 }
1904 ctx->null_cond.c = TCG_COND_ALWAYS;
1905 }
1906 ctx->iaoq_n = -1;
1907 ctx->iaoq_n_var = next;
1908 } else if (is_n && use_nullify_skip(ctx)) {
1909
1910
1911
1912
1913
1914
1915 tcg_debug_assert(ctx->iaoq_b != -1);
1916 tcg_debug_assert(ctx->iaoq_n != -1);
1917
1918
1919
1920
1921 tcg_gen_mov_reg(cpu_iaoq_f, dest);
1922 tcg_gen_addi_reg(cpu_iaoq_b, dest, 4);
1923
1924 nullify_over(ctx);
1925 if (link != 0) {
1926 tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n);
1927 }
1928 tcg_gen_lookup_and_goto_ptr();
1929 return nullify_end(ctx);
1930 } else {
1931 c = ctx->null_cond.c;
1932 a0 = ctx->null_cond.a0;
1933 a1 = ctx->null_cond.a1;
1934
1935 tmp = tcg_temp_new();
1936 next = get_temp(ctx);
1937
1938 copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1939 tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
1940 ctx->iaoq_n = -1;
1941 ctx->iaoq_n_var = next;
1942
1943 if (link != 0) {
1944 tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1945 }
1946
1947 if (is_n) {
1948
1949
1950
1951 tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1);
1952 cond_free(&ctx->null_cond);
1953 ctx->null_cond = cond_make_n();
1954 ctx->psw_n_nonzero = true;
1955 } else {
1956 cond_free(&ctx->null_cond);
1957 }
1958 }
1959 return true;
1960}
1961
1962
1963
1964
1965
1966
1967
1968
1969static TCGv_reg do_ibranch_priv(DisasContext *ctx, TCGv_reg offset)
1970{
1971 TCGv_reg dest;
1972 switch (ctx->privilege) {
1973 case 0:
1974
1975 return offset;
1976 case 3:
1977
1978 dest = get_temp(ctx);
1979 tcg_gen_ori_reg(dest, offset, 3);
1980 break;
1981 default:
1982 dest = get_temp(ctx);
1983 tcg_gen_andi_reg(dest, offset, -4);
1984 tcg_gen_ori_reg(dest, dest, ctx->privilege);
1985 tcg_gen_movcond_reg(TCG_COND_GTU, dest, dest, offset, dest, offset);
1986 break;
1987 }
1988 return dest;
1989}
1990
1991#ifdef CONFIG_USER_ONLY
1992
1993
1994
1995
1996
1997
1998
1999static void do_page_zero(DisasContext *ctx)
2000{
2001
2002
2003
2004 switch (ctx->null_cond.c) {
2005 case TCG_COND_NEVER:
2006 break;
2007 case TCG_COND_ALWAYS:
2008 tcg_gen_movi_reg(cpu_psw_n, 0);
2009 goto do_sigill;
2010 default:
2011
2012
2013 g_assert_not_reached();
2014 }
2015
2016
2017
2018
2019
2020 if (ctx->iaoq_b != ctx->iaoq_f + 4) {
2021 goto do_sigill;
2022 }
2023
2024 switch (ctx->iaoq_f & -4) {
2025 case 0x00:
2026 gen_excp_1(EXCP_IMP);
2027 ctx->base.is_jmp = DISAS_NORETURN;
2028 break;
2029
2030 case 0xb0:
2031 gen_excp_1(EXCP_SYSCALL_LWS);
2032 ctx->base.is_jmp = DISAS_NORETURN;
2033 break;
2034
2035 case 0xe0:
2036 tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27]));
2037 tcg_gen_ori_reg(cpu_iaoq_f, cpu_gr[31], 3);
2038 tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
2039 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
2040 break;
2041
2042 case 0x100:
2043 gen_excp_1(EXCP_SYSCALL);
2044 ctx->base.is_jmp = DISAS_NORETURN;
2045 break;
2046
2047 default:
2048 do_sigill:
2049 gen_excp_1(EXCP_ILL);
2050 ctx->base.is_jmp = DISAS_NORETURN;
2051 break;
2052 }
2053}
2054#endif
2055
2056static bool trans_nop(DisasContext *ctx, arg_nop *a)
2057{
2058 cond_free(&ctx->null_cond);
2059 return true;
2060}
2061
2062static bool trans_break(DisasContext *ctx, arg_break *a)
2063{
2064 return gen_excp_iir(ctx, EXCP_BREAK);
2065}
2066
2067static bool trans_sync(DisasContext *ctx, arg_sync *a)
2068{
2069
2070 tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
2071
2072 cond_free(&ctx->null_cond);
2073 return true;
2074}
2075
2076static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
2077{
2078 unsigned rt = a->t;
2079 TCGv_reg tmp = dest_gpr(ctx, rt);
2080 tcg_gen_movi_reg(tmp, ctx->iaoq_f);
2081 save_gpr(ctx, rt, tmp);
2082
2083 cond_free(&ctx->null_cond);
2084 return true;
2085}
2086
2087static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
2088{
2089 unsigned rt = a->t;
2090 unsigned rs = a->sp;
2091 TCGv_i64 t0 = tcg_temp_new_i64();
2092 TCGv_reg t1 = tcg_temp_new();
2093
2094 load_spr(ctx, t0, rs);
2095 tcg_gen_shri_i64(t0, t0, 32);
2096 tcg_gen_trunc_i64_reg(t1, t0);
2097
2098 save_gpr(ctx, rt, t1);
2099 tcg_temp_free(t1);
2100 tcg_temp_free_i64(t0);
2101
2102 cond_free(&ctx->null_cond);
2103 return true;
2104}
2105
2106static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
2107{
2108 unsigned rt = a->t;
2109 unsigned ctl = a->r;
2110 TCGv_reg tmp;
2111
2112 switch (ctl) {
2113 case CR_SAR:
2114#ifdef TARGET_HPPA64
2115 if (a->e == 0) {
2116
2117 tmp = dest_gpr(ctx, rt);
2118 tcg_gen_andi_reg(tmp, cpu_sar, 31);
2119 save_gpr(ctx, rt, tmp);
2120 goto done;
2121 }
2122#endif
2123 save_gpr(ctx, rt, cpu_sar);
2124 goto done;
2125 case CR_IT:
2126
2127 nullify_over(ctx);
2128 tmp = dest_gpr(ctx, rt);
2129 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2130 gen_io_start();
2131 gen_helper_read_interval_timer(tmp);
2132 ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2133 } else {
2134 gen_helper_read_interval_timer(tmp);
2135 }
2136 save_gpr(ctx, rt, tmp);
2137 return nullify_end(ctx);
2138 case 26:
2139 case 27:
2140 break;
2141 default:
2142
2143 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2144 break;
2145 }
2146
2147 tmp = get_temp(ctx);
2148 tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2149 save_gpr(ctx, rt, tmp);
2150
2151 done:
2152 cond_free(&ctx->null_cond);
2153 return true;
2154}
2155
2156static bool trans_mtsp(DisasContext *ctx, arg_mtsp *a)
2157{
2158 unsigned rr = a->r;
2159 unsigned rs = a->sp;
2160 TCGv_i64 t64;
2161
2162 if (rs >= 5) {
2163 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2164 }
2165 nullify_over(ctx);
2166
2167 t64 = tcg_temp_new_i64();
2168 tcg_gen_extu_reg_i64(t64, load_gpr(ctx, rr));
2169 tcg_gen_shli_i64(t64, t64, 32);
2170
2171 if (rs >= 4) {
2172 tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs]));
2173 ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2174 } else {
2175 tcg_gen_mov_i64(cpu_sr[rs], t64);
2176 }
2177 tcg_temp_free_i64(t64);
2178
2179 return nullify_end(ctx);
2180}
2181
2182static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
2183{
2184 unsigned ctl = a->t;
2185 TCGv_reg reg;
2186 TCGv_reg tmp;
2187
2188 if (ctl == CR_SAR) {
2189 reg = load_gpr(ctx, a->r);
2190 tmp = tcg_temp_new();
2191 tcg_gen_andi_reg(tmp, reg, TARGET_REGISTER_BITS - 1);
2192 save_or_nullify(ctx, cpu_sar, tmp);
2193 tcg_temp_free(tmp);
2194
2195 cond_free(&ctx->null_cond);
2196 return true;
2197 }
2198
2199
2200 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2201
2202#ifndef CONFIG_USER_ONLY
2203 nullify_over(ctx);
2204 reg = load_gpr(ctx, a->r);
2205
2206 switch (ctl) {
2207 case CR_IT:
2208 gen_helper_write_interval_timer(cpu_env, reg);
2209 break;
2210 case CR_EIRR:
2211 gen_helper_write_eirr(cpu_env, reg);
2212 break;
2213 case CR_EIEM:
2214 gen_helper_write_eiem(cpu_env, reg);
2215 ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2216 break;
2217
2218 case CR_IIASQ:
2219 case CR_IIAOQ:
2220
2221
2222 tmp = get_temp(ctx);
2223 tcg_gen_ld_reg(tmp, cpu_env,
2224 offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2225 tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2226 tcg_gen_st_reg(reg, cpu_env,
2227 offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2228 break;
2229
2230 case CR_PID1:
2231 case CR_PID2:
2232 case CR_PID3:
2233 case CR_PID4:
2234 tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2235#ifndef CONFIG_USER_ONLY
2236 gen_helper_change_prot_id(cpu_env);
2237#endif
2238 break;
2239
2240 default:
2241 tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2242 break;
2243 }
2244 return nullify_end(ctx);
2245#endif
2246}
2247
2248static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
2249{
2250 TCGv_reg tmp = tcg_temp_new();
2251
2252 tcg_gen_not_reg(tmp, load_gpr(ctx, a->r));
2253 tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
2254 save_or_nullify(ctx, cpu_sar, tmp);
2255 tcg_temp_free(tmp);
2256
2257 cond_free(&ctx->null_cond);
2258 return true;
2259}
2260
2261static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
2262{
2263 TCGv_reg dest = dest_gpr(ctx, a->t);
2264
2265#ifdef CONFIG_USER_ONLY
2266
2267 tcg_gen_movi_reg(dest, 0);
2268#else
2269 TCGv_i64 t0 = tcg_temp_new_i64();
2270
2271 tcg_gen_mov_i64(t0, space_select(ctx, a->sp, load_gpr(ctx, a->b)));
2272 tcg_gen_shri_i64(t0, t0, 32);
2273 tcg_gen_trunc_i64_reg(dest, t0);
2274
2275 tcg_temp_free_i64(t0);
2276#endif
2277 save_gpr(ctx, a->t, dest);
2278
2279 cond_free(&ctx->null_cond);
2280 return true;
2281}
2282
2283static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
2284{
2285 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2286#ifndef CONFIG_USER_ONLY
2287 TCGv_reg tmp;
2288
2289 nullify_over(ctx);
2290
2291 tmp = get_temp(ctx);
2292 tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2293 tcg_gen_andi_reg(tmp, tmp, ~a->i);
2294 gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2295 save_gpr(ctx, a->t, tmp);
2296
2297
2298 ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2299 return nullify_end(ctx);
2300#endif
2301}
2302
2303static bool trans_ssm(DisasContext *ctx, arg_ssm *a)
2304{
2305 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2306#ifndef CONFIG_USER_ONLY
2307 TCGv_reg tmp;
2308
2309 nullify_over(ctx);
2310
2311 tmp = get_temp(ctx);
2312 tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2313 tcg_gen_ori_reg(tmp, tmp, a->i);
2314 gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2315 save_gpr(ctx, a->t, tmp);
2316
2317
2318 ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2319 return nullify_end(ctx);
2320#endif
2321}
2322
2323static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a)
2324{
2325 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2326#ifndef CONFIG_USER_ONLY
2327 TCGv_reg tmp, reg;
2328 nullify_over(ctx);
2329
2330 reg = load_gpr(ctx, a->r);
2331 tmp = get_temp(ctx);
2332 gen_helper_swap_system_mask(tmp, cpu_env, reg);
2333
2334
2335 ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2336 return nullify_end(ctx);
2337#endif
2338}
2339
2340static bool do_rfi(DisasContext *ctx, bool rfi_r)
2341{
2342 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2343#ifndef CONFIG_USER_ONLY
2344 nullify_over(ctx);
2345
2346 if (rfi_r) {
2347 gen_helper_rfi_r(cpu_env);
2348 } else {
2349 gen_helper_rfi(cpu_env);
2350 }
2351
2352 if (ctx->base.singlestep_enabled) {
2353 gen_excp_1(EXCP_DEBUG);
2354 } else {
2355 tcg_gen_exit_tb(NULL, 0);
2356 }
2357 ctx->base.is_jmp = DISAS_NORETURN;
2358
2359 return nullify_end(ctx);
2360#endif
2361}
2362
2363static bool trans_rfi(DisasContext *ctx, arg_rfi *a)
2364{
2365 return do_rfi(ctx, false);
2366}
2367
2368static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a)
2369{
2370 return do_rfi(ctx, true);
2371}
2372
2373static bool trans_halt(DisasContext *ctx, arg_halt *a)
2374{
2375 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2376#ifndef CONFIG_USER_ONLY
2377 nullify_over(ctx);
2378 gen_helper_halt(cpu_env);
2379 ctx->base.is_jmp = DISAS_NORETURN;
2380 return nullify_end(ctx);
2381#endif
2382}
2383
2384static bool trans_reset(DisasContext *ctx, arg_reset *a)
2385{
2386 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2387#ifndef CONFIG_USER_ONLY
2388 nullify_over(ctx);
2389 gen_helper_reset(cpu_env);
2390 ctx->base.is_jmp = DISAS_NORETURN;
2391 return nullify_end(ctx);
2392#endif
2393}
2394
2395static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
2396{
2397 if (a->m) {
2398 TCGv_reg dest = dest_gpr(ctx, a->b);
2399 TCGv_reg src1 = load_gpr(ctx, a->b);
2400 TCGv_reg src2 = load_gpr(ctx, a->x);
2401
2402
2403 tcg_gen_add_reg(dest, src1, src2);
2404 save_gpr(ctx, a->b, dest);
2405 }
2406 cond_free(&ctx->null_cond);
2407 return true;
2408}
2409
2410static bool trans_probe(DisasContext *ctx, arg_probe *a)
2411{
2412 TCGv_reg dest, ofs;
2413 TCGv_i32 level, want;
2414 TCGv_tl addr;
2415
2416 nullify_over(ctx);
2417
2418 dest = dest_gpr(ctx, a->t);
2419 form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2420
2421 if (a->imm) {
2422 level = tcg_constant_i32(a->ri);
2423 } else {
2424 level = tcg_temp_new_i32();
2425 tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
2426 tcg_gen_andi_i32(level, level, 3);
2427 }
2428 want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ);
2429
2430 gen_helper_probe(dest, cpu_env, addr, level, want);
2431
2432 tcg_temp_free_i32(level);
2433
2434 save_gpr(ctx, a->t, dest);
2435 return nullify_end(ctx);
2436}
2437
2438static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
2439{
2440 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2441#ifndef CONFIG_USER_ONLY
2442 TCGv_tl addr;
2443 TCGv_reg ofs, reg;
2444
2445 nullify_over(ctx);
2446
2447 form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2448 reg = load_gpr(ctx, a->r);
2449 if (a->addr) {
2450 gen_helper_itlba(cpu_env, addr, reg);
2451 } else {
2452 gen_helper_itlbp(cpu_env, addr, reg);
2453 }
2454
2455
2456 if (ctx->tb_flags & PSW_C) {
2457 ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2458 }
2459 return nullify_end(ctx);
2460#endif
2461}
2462
2463static bool trans_pxtlbx(DisasContext *ctx, arg_pxtlbx *a)
2464{
2465 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2466#ifndef CONFIG_USER_ONLY
2467 TCGv_tl addr;
2468 TCGv_reg ofs;
2469
2470 nullify_over(ctx);
2471
2472 form_gva(ctx, &addr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2473 if (a->m) {
2474 save_gpr(ctx, a->b, ofs);
2475 }
2476 if (a->local) {
2477 gen_helper_ptlbe(cpu_env);
2478 } else {
2479 gen_helper_ptlb(cpu_env, addr);
2480 }
2481
2482
2483 if (ctx->tb_flags & PSW_C) {
2484 ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2485 }
2486 return nullify_end(ctx);
2487#endif
2488}
2489
2490
2491
2492
2493
2494
2495
2496static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
2497{
2498 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2499#ifndef CONFIG_USER_ONLY
2500 TCGv_tl addr, atl, stl;
2501 TCGv_reg reg;
2502
2503 nullify_over(ctx);
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513 atl = tcg_temp_new_tl();
2514 stl = tcg_temp_new_tl();
2515 addr = tcg_temp_new_tl();
2516
2517 tcg_gen_ld32u_i64(stl, cpu_env,
2518 a->data ? offsetof(CPUHPPAState, cr[CR_ISR])
2519 : offsetof(CPUHPPAState, cr[CR_IIASQ]));
2520 tcg_gen_ld32u_i64(atl, cpu_env,
2521 a->data ? offsetof(CPUHPPAState, cr[CR_IOR])
2522 : offsetof(CPUHPPAState, cr[CR_IIAOQ]));
2523 tcg_gen_shli_i64(stl, stl, 32);
2524 tcg_gen_or_tl(addr, atl, stl);
2525 tcg_temp_free_tl(atl);
2526 tcg_temp_free_tl(stl);
2527
2528 reg = load_gpr(ctx, a->r);
2529 if (a->addr) {
2530 gen_helper_itlba(cpu_env, addr, reg);
2531 } else {
2532 gen_helper_itlbp(cpu_env, addr, reg);
2533 }
2534 tcg_temp_free_tl(addr);
2535
2536
2537 if (ctx->tb_flags & PSW_C) {
2538 ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2539 }
2540 return nullify_end(ctx);
2541#endif
2542}
2543
2544static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
2545{
2546 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2547#ifndef CONFIG_USER_ONLY
2548 TCGv_tl vaddr;
2549 TCGv_reg ofs, paddr;
2550
2551 nullify_over(ctx);
2552
2553 form_gva(ctx, &vaddr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2554
2555 paddr = tcg_temp_new();
2556 gen_helper_lpa(paddr, cpu_env, vaddr);
2557
2558
2559 if (a->m) {
2560 save_gpr(ctx, a->b, ofs);
2561 }
2562 save_gpr(ctx, a->t, paddr);
2563 tcg_temp_free(paddr);
2564
2565 return nullify_end(ctx);
2566#endif
2567}
2568
2569static bool trans_lci(DisasContext *ctx, arg_lci *a)
2570{
2571 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2572
2573
2574
2575
2576
2577 save_gpr(ctx, a->t, tcg_constant_reg(0));
2578
2579 cond_free(&ctx->null_cond);
2580 return true;
2581}
2582
2583static bool trans_add(DisasContext *ctx, arg_rrr_cf_sh *a)
2584{
2585 return do_add_reg(ctx, a, false, false, false, false);
2586}
2587
2588static bool trans_add_l(DisasContext *ctx, arg_rrr_cf_sh *a)
2589{
2590 return do_add_reg(ctx, a, true, false, false, false);
2591}
2592
2593static bool trans_add_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
2594{
2595 return do_add_reg(ctx, a, false, true, false, false);
2596}
2597
2598static bool trans_add_c(DisasContext *ctx, arg_rrr_cf_sh *a)
2599{
2600 return do_add_reg(ctx, a, false, false, false, true);
2601}
2602
2603static bool trans_add_c_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
2604{
2605 return do_add_reg(ctx, a, false, true, false, true);
2606}
2607
2608static bool trans_sub(DisasContext *ctx, arg_rrr_cf *a)
2609{
2610 return do_sub_reg(ctx, a, false, false, false);
2611}
2612
2613static bool trans_sub_tsv(DisasContext *ctx, arg_rrr_cf *a)
2614{
2615 return do_sub_reg(ctx, a, true, false, false);
2616}
2617
2618static bool trans_sub_tc(DisasContext *ctx, arg_rrr_cf *a)
2619{
2620 return do_sub_reg(ctx, a, false, false, true);
2621}
2622
2623static bool trans_sub_tsv_tc(DisasContext *ctx, arg_rrr_cf *a)
2624{
2625 return do_sub_reg(ctx, a, true, false, true);
2626}
2627
2628static bool trans_sub_b(DisasContext *ctx, arg_rrr_cf *a)
2629{
2630 return do_sub_reg(ctx, a, false, true, false);
2631}
2632
2633static bool trans_sub_b_tsv(DisasContext *ctx, arg_rrr_cf *a)
2634{
2635 return do_sub_reg(ctx, a, true, true, false);
2636}
2637
2638static bool trans_andcm(DisasContext *ctx, arg_rrr_cf *a)
2639{
2640 return do_log_reg(ctx, a, tcg_gen_andc_reg);
2641}
2642
2643static bool trans_and(DisasContext *ctx, arg_rrr_cf *a)
2644{
2645 return do_log_reg(ctx, a, tcg_gen_and_reg);
2646}
2647
2648static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
2649{
2650 if (a->cf == 0) {
2651 unsigned r2 = a->r2;
2652 unsigned r1 = a->r1;
2653 unsigned rt = a->t;
2654
2655 if (rt == 0) {
2656 cond_free(&ctx->null_cond);
2657 return true;
2658 }
2659 if (r2 == 0) {
2660 if (r1 == 0) {
2661 TCGv_reg dest = dest_gpr(ctx, rt);
2662 tcg_gen_movi_reg(dest, 0);
2663 save_gpr(ctx, rt, dest);
2664 } else {
2665 save_gpr(ctx, rt, cpu_gr[r1]);
2666 }
2667 cond_free(&ctx->null_cond);
2668 return true;
2669 }
2670#ifndef CONFIG_USER_ONLY
2671
2672
2673
2674
2675
2676
2677 if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) {
2678
2679
2680 nullify_over(ctx);
2681
2682
2683 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2684 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2685 nullify_set(ctx, 0);
2686
2687
2688 tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
2689 offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2690 gen_excp_1(EXCP_HALTED);
2691 ctx->base.is_jmp = DISAS_NORETURN;
2692
2693 return nullify_end(ctx);
2694 }
2695#endif
2696 }
2697 return do_log_reg(ctx, a, tcg_gen_or_reg);
2698}
2699
2700static bool trans_xor(DisasContext *ctx, arg_rrr_cf *a)
2701{
2702 return do_log_reg(ctx, a, tcg_gen_xor_reg);
2703}
2704
2705static bool trans_cmpclr(DisasContext *ctx, arg_rrr_cf *a)
2706{
2707 TCGv_reg tcg_r1, tcg_r2;
2708
2709 if (a->cf) {
2710 nullify_over(ctx);
2711 }
2712 tcg_r1 = load_gpr(ctx, a->r1);
2713 tcg_r2 = load_gpr(ctx, a->r2);
2714 do_cmpclr(ctx, a->t, tcg_r1, tcg_r2, a->cf);
2715 return nullify_end(ctx);
2716}
2717
2718static bool trans_uxor(DisasContext *ctx, arg_rrr_cf *a)
2719{
2720 TCGv_reg tcg_r1, tcg_r2;
2721
2722 if (a->cf) {
2723 nullify_over(ctx);
2724 }
2725 tcg_r1 = load_gpr(ctx, a->r1);
2726 tcg_r2 = load_gpr(ctx, a->r2);
2727 do_unit(ctx, a->t, tcg_r1, tcg_r2, a->cf, false, tcg_gen_xor_reg);
2728 return nullify_end(ctx);
2729}
2730
2731static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf *a, bool is_tc)
2732{
2733 TCGv_reg tcg_r1, tcg_r2, tmp;
2734
2735 if (a->cf) {
2736 nullify_over(ctx);
2737 }
2738 tcg_r1 = load_gpr(ctx, a->r1);
2739 tcg_r2 = load_gpr(ctx, a->r2);
2740 tmp = get_temp(ctx);
2741 tcg_gen_not_reg(tmp, tcg_r2);
2742 do_unit(ctx, a->t, tcg_r1, tmp, a->cf, is_tc, tcg_gen_add_reg);
2743 return nullify_end(ctx);
2744}
2745
2746static bool trans_uaddcm(DisasContext *ctx, arg_rrr_cf *a)
2747{
2748 return do_uaddcm(ctx, a, false);
2749}
2750
2751static bool trans_uaddcm_tc(DisasContext *ctx, arg_rrr_cf *a)
2752{
2753 return do_uaddcm(ctx, a, true);
2754}
2755
2756static bool do_dcor(DisasContext *ctx, arg_rr_cf *a, bool is_i)
2757{
2758 TCGv_reg tmp;
2759
2760 nullify_over(ctx);
2761
2762 tmp = get_temp(ctx);
2763 tcg_gen_shri_reg(tmp, cpu_psw_cb, 3);
2764 if (!is_i) {
2765 tcg_gen_not_reg(tmp, tmp);
2766 }
2767 tcg_gen_andi_reg(tmp, tmp, 0x11111111);
2768 tcg_gen_muli_reg(tmp, tmp, 6);
2769 do_unit(ctx, a->t, load_gpr(ctx, a->r), tmp, a->cf, false,
2770 is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
2771 return nullify_end(ctx);
2772}
2773
2774static bool trans_dcor(DisasContext *ctx, arg_rr_cf *a)
2775{
2776 return do_dcor(ctx, a, false);
2777}
2778
2779static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf *a)
2780{
2781 return do_dcor(ctx, a, true);
2782}
2783
2784static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
2785{
2786 TCGv_reg dest, add1, add2, addc, zero, in1, in2;
2787
2788 nullify_over(ctx);
2789
2790 in1 = load_gpr(ctx, a->r1);
2791 in2 = load_gpr(ctx, a->r2);
2792
2793 add1 = tcg_temp_new();
2794 add2 = tcg_temp_new();
2795 addc = tcg_temp_new();
2796 dest = tcg_temp_new();
2797 zero = tcg_constant_reg(0);
2798
2799
2800 tcg_gen_add_reg(add1, in1, in1);
2801 tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb);
2802
2803
2804
2805
2806
2807 tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1);
2808 tcg_gen_xor_reg(add2, in2, addc);
2809 tcg_gen_andi_reg(addc, addc, 1);
2810
2811 tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
2812 tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
2813
2814 tcg_temp_free(addc);
2815
2816
2817 save_gpr(ctx, a->t, dest);
2818
2819
2820 tcg_gen_xor_reg(cpu_psw_cb, add1, add2);
2821 tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest);
2822
2823
2824 tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb);
2825 tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
2826
2827
2828 if (a->cf) {
2829 TCGv_reg sv = NULL;
2830 if (cond_need_sv(a->cf >> 1)) {
2831
2832 sv = do_add_sv(ctx, dest, add1, add2);
2833 }
2834 ctx->null_cond = do_cond(a->cf, dest, cpu_psw_cb_msb, sv);
2835 }
2836
2837 tcg_temp_free(add1);
2838 tcg_temp_free(add2);
2839 tcg_temp_free(dest);
2840
2841 return nullify_end(ctx);
2842}
2843
2844static bool trans_addi(DisasContext *ctx, arg_rri_cf *a)
2845{
2846 return do_add_imm(ctx, a, false, false);
2847}
2848
2849static bool trans_addi_tsv(DisasContext *ctx, arg_rri_cf *a)
2850{
2851 return do_add_imm(ctx, a, true, false);
2852}
2853
2854static bool trans_addi_tc(DisasContext *ctx, arg_rri_cf *a)
2855{
2856 return do_add_imm(ctx, a, false, true);
2857}
2858
2859static bool trans_addi_tc_tsv(DisasContext *ctx, arg_rri_cf *a)
2860{
2861 return do_add_imm(ctx, a, true, true);
2862}
2863
2864static bool trans_subi(DisasContext *ctx, arg_rri_cf *a)
2865{
2866 return do_sub_imm(ctx, a, false);
2867}
2868
2869static bool trans_subi_tsv(DisasContext *ctx, arg_rri_cf *a)
2870{
2871 return do_sub_imm(ctx, a, true);
2872}
2873
2874static bool trans_cmpiclr(DisasContext *ctx, arg_rri_cf *a)
2875{
2876 TCGv_reg tcg_im, tcg_r2;
2877
2878 if (a->cf) {
2879 nullify_over(ctx);
2880 }
2881
2882 tcg_im = load_const(ctx, a->i);
2883 tcg_r2 = load_gpr(ctx, a->r);
2884 do_cmpclr(ctx, a->t, tcg_im, tcg_r2, a->cf);
2885
2886 return nullify_end(ctx);
2887}
2888
2889static bool trans_ld(DisasContext *ctx, arg_ldst *a)
2890{
2891 return do_load(ctx, a->t, a->b, a->x, a->scale ? a->size : 0,
2892 a->disp, a->sp, a->m, a->size | MO_TE);
2893}
2894
2895static bool trans_st(DisasContext *ctx, arg_ldst *a)
2896{
2897 assert(a->x == 0 && a->scale == 0);
2898 return do_store(ctx, a->t, a->b, a->disp, a->sp, a->m, a->size | MO_TE);
2899}
2900
2901static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
2902{
2903 MemOp mop = MO_TE | MO_ALIGN | a->size;
2904 TCGv_reg zero, dest, ofs;
2905 TCGv_tl addr;
2906
2907 nullify_over(ctx);
2908
2909 if (a->m) {
2910
2911
2912 dest = get_temp(ctx);
2913 } else {
2914 dest = dest_gpr(ctx, a->t);
2915 }
2916
2917 form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
2918 a->disp, a->sp, a->m, ctx->mmu_idx == MMU_PHYS_IDX);
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928 gen_helper_ldc_check(addr);
2929
2930 zero = tcg_constant_reg(0);
2931 tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
2932
2933 if (a->m) {
2934 save_gpr(ctx, a->b, ofs);
2935 }
2936 save_gpr(ctx, a->t, dest);
2937
2938 return nullify_end(ctx);
2939}
2940
2941static bool trans_stby(DisasContext *ctx, arg_stby *a)
2942{
2943 TCGv_reg ofs, val;
2944 TCGv_tl addr;
2945
2946 nullify_over(ctx);
2947
2948 form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
2949 ctx->mmu_idx == MMU_PHYS_IDX);
2950 val = load_gpr(ctx, a->r);
2951 if (a->a) {
2952 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2953 gen_helper_stby_e_parallel(cpu_env, addr, val);
2954 } else {
2955 gen_helper_stby_e(cpu_env, addr, val);
2956 }
2957 } else {
2958 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2959 gen_helper_stby_b_parallel(cpu_env, addr, val);
2960 } else {
2961 gen_helper_stby_b(cpu_env, addr, val);
2962 }
2963 }
2964 if (a->m) {
2965 tcg_gen_andi_reg(ofs, ofs, ~3);
2966 save_gpr(ctx, a->b, ofs);
2967 }
2968
2969 return nullify_end(ctx);
2970}
2971
2972static bool trans_lda(DisasContext *ctx, arg_ldst *a)
2973{
2974 int hold_mmu_idx = ctx->mmu_idx;
2975
2976 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2977 ctx->mmu_idx = MMU_PHYS_IDX;
2978 trans_ld(ctx, a);
2979 ctx->mmu_idx = hold_mmu_idx;
2980 return true;
2981}
2982
2983static bool trans_sta(DisasContext *ctx, arg_ldst *a)
2984{
2985 int hold_mmu_idx = ctx->mmu_idx;
2986
2987 CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2988 ctx->mmu_idx = MMU_PHYS_IDX;
2989 trans_st(ctx, a);
2990 ctx->mmu_idx = hold_mmu_idx;
2991 return true;
2992}
2993
2994static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
2995{
2996 TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
2997
2998 tcg_gen_movi_reg(tcg_rt, a->i);
2999 save_gpr(ctx, a->t, tcg_rt);
3000 cond_free(&ctx->null_cond);
3001 return true;
3002}
3003
3004static bool trans_addil(DisasContext *ctx, arg_addil *a)
3005{
3006 TCGv_reg tcg_rt = load_gpr(ctx, a->r);
3007 TCGv_reg tcg_r1 = dest_gpr(ctx, 1);
3008
3009 tcg_gen_addi_reg(tcg_r1, tcg_rt, a->i);
3010 save_gpr(ctx, 1, tcg_r1);
3011 cond_free(&ctx->null_cond);
3012 return true;
3013}
3014
3015static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
3016{
3017 TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
3018
3019
3020
3021 if (a->b == 0) {
3022 tcg_gen_movi_reg(tcg_rt, a->i);
3023 } else {
3024 tcg_gen_addi_reg(tcg_rt, cpu_gr[a->b], a->i);
3025 }
3026 save_gpr(ctx, a->t, tcg_rt);
3027 cond_free(&ctx->null_cond);
3028 return true;
3029}
3030
3031static bool do_cmpb(DisasContext *ctx, unsigned r, TCGv_reg in1,
3032 unsigned c, unsigned f, unsigned n, int disp)
3033{
3034 TCGv_reg dest, in2, sv;
3035 DisasCond cond;
3036
3037 in2 = load_gpr(ctx, r);
3038 dest = get_temp(ctx);
3039
3040 tcg_gen_sub_reg(dest, in1, in2);
3041
3042 sv = NULL;
3043 if (cond_need_sv(c)) {
3044 sv = do_sub_sv(ctx, dest, in1, in2);
3045 }
3046
3047 cond = do_sub_cond(c * 2 + f, dest, in1, in2, sv);
3048 return do_cbranch(ctx, disp, n, &cond);
3049}
3050
3051static bool trans_cmpb(DisasContext *ctx, arg_cmpb *a)
3052{
3053 nullify_over(ctx);
3054 return do_cmpb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3055}
3056
3057static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
3058{
3059 nullify_over(ctx);
3060 return do_cmpb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
3061}
3062
3063static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
3064 unsigned c, unsigned f, unsigned n, int disp)
3065{
3066 TCGv_reg dest, in2, sv, cb_msb;
3067 DisasCond cond;
3068
3069 in2 = load_gpr(ctx, r);
3070 dest = tcg_temp_new();
3071 sv = NULL;
3072 cb_msb = NULL;
3073
3074 if (cond_need_cb(c)) {
3075 cb_msb = get_temp(ctx);
3076 tcg_gen_movi_reg(cb_msb, 0);
3077 tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
3078 } else {
3079 tcg_gen_add_reg(dest, in1, in2);
3080 }
3081 if (cond_need_sv(c)) {
3082 sv = do_add_sv(ctx, dest, in1, in2);
3083 }
3084
3085 cond = do_cond(c * 2 + f, dest, cb_msb, sv);
3086 save_gpr(ctx, r, dest);
3087 tcg_temp_free(dest);
3088 return do_cbranch(ctx, disp, n, &cond);
3089}
3090
3091static bool trans_addb(DisasContext *ctx, arg_addb *a)
3092{
3093 nullify_over(ctx);
3094 return do_addb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3095}
3096
3097static bool trans_addbi(DisasContext *ctx, arg_addbi *a)
3098{
3099 nullify_over(ctx);
3100 return do_addb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
3101}
3102
3103static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
3104{
3105 TCGv_reg tmp, tcg_r;
3106 DisasCond cond;
3107
3108 nullify_over(ctx);
3109
3110 tmp = tcg_temp_new();
3111 tcg_r = load_gpr(ctx, a->r);
3112 tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
3113
3114 cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3115 tcg_temp_free(tmp);
3116 return do_cbranch(ctx, a->disp, a->n, &cond);
3117}
3118
3119static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
3120{
3121 TCGv_reg tmp, tcg_r;
3122 DisasCond cond;
3123
3124 nullify_over(ctx);
3125
3126 tmp = tcg_temp_new();
3127 tcg_r = load_gpr(ctx, a->r);
3128 tcg_gen_shli_reg(tmp, tcg_r, a->p);
3129
3130 cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3131 tcg_temp_free(tmp);
3132 return do_cbranch(ctx, a->disp, a->n, &cond);
3133}
3134
3135static bool trans_movb(DisasContext *ctx, arg_movb *a)
3136{
3137 TCGv_reg dest;
3138 DisasCond cond;
3139
3140 nullify_over(ctx);
3141
3142 dest = dest_gpr(ctx, a->r2);
3143 if (a->r1 == 0) {
3144 tcg_gen_movi_reg(dest, 0);
3145 } else {
3146 tcg_gen_mov_reg(dest, cpu_gr[a->r1]);
3147 }
3148
3149 cond = do_sed_cond(a->c, dest);
3150 return do_cbranch(ctx, a->disp, a->n, &cond);
3151}
3152
3153static bool trans_movbi(DisasContext *ctx, arg_movbi *a)
3154{
3155 TCGv_reg dest;
3156 DisasCond cond;
3157
3158 nullify_over(ctx);
3159
3160 dest = dest_gpr(ctx, a->r);
3161 tcg_gen_movi_reg(dest, a->i);
3162
3163 cond = do_sed_cond(a->c, dest);
3164 return do_cbranch(ctx, a->disp, a->n, &cond);
3165}
3166
3167static bool trans_shrpw_sar(DisasContext *ctx, arg_shrpw_sar *a)
3168{
3169 TCGv_reg dest;
3170
3171 if (a->c) {
3172 nullify_over(ctx);
3173 }
3174
3175 dest = dest_gpr(ctx, a->t);
3176 if (a->r1 == 0) {
3177 tcg_gen_ext32u_reg(dest, load_gpr(ctx, a->r2));
3178 tcg_gen_shr_reg(dest, dest, cpu_sar);
3179 } else if (a->r1 == a->r2) {
3180 TCGv_i32 t32 = tcg_temp_new_i32();
3181 tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, a->r2));
3182 tcg_gen_rotr_i32(t32, t32, cpu_sar);
3183 tcg_gen_extu_i32_reg(dest, t32);
3184 tcg_temp_free_i32(t32);
3185 } else {
3186 TCGv_i64 t = tcg_temp_new_i64();
3187 TCGv_i64 s = tcg_temp_new_i64();
3188
3189 tcg_gen_concat_reg_i64(t, load_gpr(ctx, a->r2), load_gpr(ctx, a->r1));
3190 tcg_gen_extu_reg_i64(s, cpu_sar);
3191 tcg_gen_shr_i64(t, t, s);
3192 tcg_gen_trunc_i64_reg(dest, t);
3193
3194 tcg_temp_free_i64(t);
3195 tcg_temp_free_i64(s);
3196 }
3197 save_gpr(ctx, a->t, dest);
3198
3199
3200 cond_free(&ctx->null_cond);
3201 if (a->c) {
3202 ctx->null_cond = do_sed_cond(a->c, dest);
3203 }
3204 return nullify_end(ctx);
3205}
3206
3207static bool trans_shrpw_imm(DisasContext *ctx, arg_shrpw_imm *a)
3208{
3209 unsigned sa = 31 - a->cpos;
3210 TCGv_reg dest, t2;
3211
3212 if (a->c) {
3213 nullify_over(ctx);
3214 }
3215
3216 dest = dest_gpr(ctx, a->t);
3217 t2 = load_gpr(ctx, a->r2);
3218 if (a->r1 == a->r2) {
3219 TCGv_i32 t32 = tcg_temp_new_i32();
3220 tcg_gen_trunc_reg_i32(t32, t2);
3221 tcg_gen_rotri_i32(t32, t32, sa);
3222 tcg_gen_extu_i32_reg(dest, t32);
3223 tcg_temp_free_i32(t32);
3224 } else if (a->r1 == 0) {
3225 tcg_gen_extract_reg(dest, t2, sa, 32 - sa);
3226 } else {
3227 TCGv_reg t0 = tcg_temp_new();
3228 tcg_gen_extract_reg(t0, t2, sa, 32 - sa);
3229 tcg_gen_deposit_reg(dest, t0, cpu_gr[a->r1], 32 - sa, sa);
3230 tcg_temp_free(t0);
3231 }
3232 save_gpr(ctx, a->t, dest);
3233
3234
3235 cond_free(&ctx->null_cond);
3236 if (a->c) {
3237 ctx->null_cond = do_sed_cond(a->c, dest);
3238 }
3239 return nullify_end(ctx);
3240}
3241
3242static bool trans_extrw_sar(DisasContext *ctx, arg_extrw_sar *a)
3243{
3244 unsigned len = 32 - a->clen;
3245 TCGv_reg dest, src, tmp;
3246
3247 if (a->c) {
3248 nullify_over(ctx);
3249 }
3250
3251 dest = dest_gpr(ctx, a->t);
3252 src = load_gpr(ctx, a->r);
3253 tmp = tcg_temp_new();
3254
3255
3256 tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1);
3257 if (a->se) {
3258 tcg_gen_sar_reg(dest, src, tmp);
3259 tcg_gen_sextract_reg(dest, dest, 0, len);
3260 } else {
3261 tcg_gen_shr_reg(dest, src, tmp);
3262 tcg_gen_extract_reg(dest, dest, 0, len);
3263 }
3264 tcg_temp_free(tmp);
3265 save_gpr(ctx, a->t, dest);
3266
3267
3268 cond_free(&ctx->null_cond);
3269 if (a->c) {
3270 ctx->null_cond = do_sed_cond(a->c, dest);
3271 }
3272 return nullify_end(ctx);
3273}
3274
3275static bool trans_extrw_imm(DisasContext *ctx, arg_extrw_imm *a)
3276{
3277 unsigned len = 32 - a->clen;
3278 unsigned cpos = 31 - a->pos;
3279 TCGv_reg dest, src;
3280
3281 if (a->c) {
3282 nullify_over(ctx);
3283 }
3284
3285 dest = dest_gpr(ctx, a->t);
3286 src = load_gpr(ctx, a->r);
3287 if (a->se) {
3288 tcg_gen_sextract_reg(dest, src, cpos, len);
3289 } else {
3290 tcg_gen_extract_reg(dest, src, cpos, len);
3291 }
3292 save_gpr(ctx, a->t, dest);
3293
3294
3295 cond_free(&ctx->null_cond);
3296 if (a->c) {
3297 ctx->null_cond = do_sed_cond(a->c, dest);
3298 }
3299 return nullify_end(ctx);
3300}
3301
3302static bool trans_depwi_imm(DisasContext *ctx, arg_depwi_imm *a)
3303{
3304 unsigned len = 32 - a->clen;
3305 target_sreg mask0, mask1;
3306 TCGv_reg dest;
3307
3308 if (a->c) {
3309 nullify_over(ctx);
3310 }
3311 if (a->cpos + len > 32) {
3312 len = 32 - a->cpos;
3313 }
3314
3315 dest = dest_gpr(ctx, a->t);
3316 mask0 = deposit64(0, a->cpos, len, a->i);
3317 mask1 = deposit64(-1, a->cpos, len, a->i);
3318
3319 if (a->nz) {
3320 TCGv_reg src = load_gpr(ctx, a->t);
3321 if (mask1 != -1) {
3322 tcg_gen_andi_reg(dest, src, mask1);
3323 src = dest;
3324 }
3325 tcg_gen_ori_reg(dest, src, mask0);
3326 } else {
3327 tcg_gen_movi_reg(dest, mask0);
3328 }
3329 save_gpr(ctx, a->t, dest);
3330
3331
3332 cond_free(&ctx->null_cond);
3333 if (a->c) {
3334 ctx->null_cond = do_sed_cond(a->c, dest);
3335 }
3336 return nullify_end(ctx);
3337}
3338
3339static bool trans_depw_imm(DisasContext *ctx, arg_depw_imm *a)
3340{
3341 unsigned rs = a->nz ? a->t : 0;
3342 unsigned len = 32 - a->clen;
3343 TCGv_reg dest, val;
3344
3345 if (a->c) {
3346 nullify_over(ctx);
3347 }
3348 if (a->cpos + len > 32) {
3349 len = 32 - a->cpos;
3350 }
3351
3352 dest = dest_gpr(ctx, a->t);
3353 val = load_gpr(ctx, a->r);
3354 if (rs == 0) {
3355 tcg_gen_deposit_z_reg(dest, val, a->cpos, len);
3356 } else {
3357 tcg_gen_deposit_reg(dest, cpu_gr[rs], val, a->cpos, len);
3358 }
3359 save_gpr(ctx, a->t, dest);
3360
3361
3362 cond_free(&ctx->null_cond);
3363 if (a->c) {
3364 ctx->null_cond = do_sed_cond(a->c, dest);
3365 }
3366 return nullify_end(ctx);
3367}
3368
3369static bool do_depw_sar(DisasContext *ctx, unsigned rt, unsigned c,
3370 unsigned nz, unsigned clen, TCGv_reg val)
3371{
3372 unsigned rs = nz ? rt : 0;
3373 unsigned len = 32 - clen;
3374 TCGv_reg mask, tmp, shift, dest;
3375 unsigned msb = 1U << (len - 1);
3376
3377 dest = dest_gpr(ctx, rt);
3378 shift = tcg_temp_new();
3379 tmp = tcg_temp_new();
3380
3381
3382 tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1);
3383
3384 mask = tcg_const_reg(msb + (msb - 1));
3385 tcg_gen_and_reg(tmp, val, mask);
3386 if (rs) {
3387 tcg_gen_shl_reg(mask, mask, shift);
3388 tcg_gen_shl_reg(tmp, tmp, shift);
3389 tcg_gen_andc_reg(dest, cpu_gr[rs], mask);
3390 tcg_gen_or_reg(dest, dest, tmp);
3391 } else {
3392 tcg_gen_shl_reg(dest, tmp, shift);
3393 }
3394 tcg_temp_free(shift);
3395 tcg_temp_free(mask);
3396 tcg_temp_free(tmp);
3397 save_gpr(ctx, rt, dest);
3398
3399
3400 cond_free(&ctx->null_cond);
3401 if (c) {
3402 ctx->null_cond = do_sed_cond(c, dest);
3403 }
3404 return nullify_end(ctx);
3405}
3406
3407static bool trans_depw_sar(DisasContext *ctx, arg_depw_sar *a)
3408{
3409 if (a->c) {
3410 nullify_over(ctx);
3411 }
3412 return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_gpr(ctx, a->r));
3413}
3414
3415static bool trans_depwi_sar(DisasContext *ctx, arg_depwi_sar *a)
3416{
3417 if (a->c) {
3418 nullify_over(ctx);
3419 }
3420 return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_const(ctx, a->i));
3421}
3422
3423static bool trans_be(DisasContext *ctx, arg_be *a)
3424{
3425 TCGv_reg tmp;
3426
3427#ifdef CONFIG_USER_ONLY
3428
3429
3430
3431
3432
3433
3434
3435
3436 if (a->b == 0) {
3437 return do_dbranch(ctx, a->disp, a->l, a->n);
3438 }
3439#else
3440 nullify_over(ctx);
3441#endif
3442
3443 tmp = get_temp(ctx);
3444 tcg_gen_addi_reg(tmp, load_gpr(ctx, a->b), a->disp);
3445 tmp = do_ibranch_priv(ctx, tmp);
3446
3447#ifdef CONFIG_USER_ONLY
3448 return do_ibranch(ctx, tmp, a->l, a->n);
3449#else
3450 TCGv_i64 new_spc = tcg_temp_new_i64();
3451
3452 load_spr(ctx, new_spc, a->sp);
3453 if (a->l) {
3454 copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3455 tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
3456 }
3457 if (a->n && use_nullify_skip(ctx)) {
3458 tcg_gen_mov_reg(cpu_iaoq_f, tmp);
3459 tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
3460 tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3461 tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3462 } else {
3463 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3464 if (ctx->iaoq_b == -1) {
3465 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3466 }
3467 tcg_gen_mov_reg(cpu_iaoq_b, tmp);
3468 tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3469 nullify_set(ctx, a->n);
3470 }
3471 tcg_temp_free_i64(new_spc);
3472 tcg_gen_lookup_and_goto_ptr();
3473 ctx->base.is_jmp = DISAS_NORETURN;
3474 return nullify_end(ctx);
3475#endif
3476}
3477
3478static bool trans_bl(DisasContext *ctx, arg_bl *a)
3479{
3480 return do_dbranch(ctx, iaoq_dest(ctx, a->disp), a->l, a->n);
3481}
3482
3483static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
3484{
3485 target_ureg dest = iaoq_dest(ctx, a->disp);
3486
3487 nullify_over(ctx);
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500 if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
3501 return gen_illegal(ctx);
3502 }
3503
3504#ifndef CONFIG_USER_ONLY
3505 if (ctx->tb_flags & PSW_C) {
3506 CPUHPPAState *env = ctx->cs->env_ptr;
3507 int type = hppa_artype_for_page(env, ctx->base.pc_next);
3508
3509
3510
3511
3512
3513 if (type < 0) {
3514 gen_excp(ctx, EXCP_ITLB_MISS);
3515 return true;
3516 }
3517
3518 if (type >= 4 && type - 4 < ctx->privilege) {
3519 dest = deposit32(dest, 0, 2, type - 4);
3520 }
3521 } else {
3522 dest &= -4;
3523 }
3524#endif
3525
3526 if (a->l) {
3527 TCGv_reg tmp = dest_gpr(ctx, a->l);
3528 if (ctx->privilege < 3) {
3529 tcg_gen_andi_reg(tmp, tmp, -4);
3530 }
3531 tcg_gen_ori_reg(tmp, tmp, ctx->privilege);
3532 save_gpr(ctx, a->l, tmp);
3533 }
3534
3535 return do_dbranch(ctx, dest, 0, a->n);
3536}
3537
3538static bool trans_blr(DisasContext *ctx, arg_blr *a)
3539{
3540 if (a->x) {
3541 TCGv_reg tmp = get_temp(ctx);
3542 tcg_gen_shli_reg(tmp, load_gpr(ctx, a->x), 3);
3543 tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
3544
3545 return do_ibranch(ctx, tmp, a->l, a->n);
3546 } else {
3547
3548 return do_dbranch(ctx, ctx->iaoq_f + 8, a->l, a->n);
3549 }
3550}
3551
3552static bool trans_bv(DisasContext *ctx, arg_bv *a)
3553{
3554 TCGv_reg dest;
3555
3556 if (a->x == 0) {
3557 dest = load_gpr(ctx, a->b);
3558 } else {
3559 dest = get_temp(ctx);
3560 tcg_gen_shli_reg(dest, load_gpr(ctx, a->x), 3);
3561 tcg_gen_add_reg(dest, dest, load_gpr(ctx, a->b));
3562 }
3563 dest = do_ibranch_priv(ctx, dest);
3564 return do_ibranch(ctx, dest, 0, a->n);
3565}
3566
3567static bool trans_bve(DisasContext *ctx, arg_bve *a)
3568{
3569 TCGv_reg dest;
3570
3571#ifdef CONFIG_USER_ONLY
3572 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3573 return do_ibranch(ctx, dest, a->l, a->n);
3574#else
3575 nullify_over(ctx);
3576 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3577
3578 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3579 if (ctx->iaoq_b == -1) {
3580 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3581 }
3582 copy_iaoq_entry(cpu_iaoq_b, -1, dest);
3583 tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
3584 if (a->l) {
3585 copy_iaoq_entry(cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
3586 }
3587 nullify_set(ctx, a->n);
3588 tcg_gen_lookup_and_goto_ptr();
3589 ctx->base.is_jmp = DISAS_NORETURN;
3590 return nullify_end(ctx);
3591#endif
3592}
3593
3594
3595
3596
3597
3598static void gen_fcpy_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3599{
3600 tcg_gen_mov_i32(dst, src);
3601}
3602
3603static bool trans_fcpy_f(DisasContext *ctx, arg_fclass01 *a)
3604{
3605 return do_fop_wew(ctx, a->t, a->r, gen_fcpy_f);
3606}
3607
3608static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3609{
3610 tcg_gen_mov_i64(dst, src);
3611}
3612
3613static bool trans_fcpy_d(DisasContext *ctx, arg_fclass01 *a)
3614{
3615 return do_fop_ded(ctx, a->t, a->r, gen_fcpy_d);
3616}
3617
3618static void gen_fabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3619{
3620 tcg_gen_andi_i32(dst, src, INT32_MAX);
3621}
3622
3623static bool trans_fabs_f(DisasContext *ctx, arg_fclass01 *a)
3624{
3625 return do_fop_wew(ctx, a->t, a->r, gen_fabs_f);
3626}
3627
3628static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3629{
3630 tcg_gen_andi_i64(dst, src, INT64_MAX);
3631}
3632
3633static bool trans_fabs_d(DisasContext *ctx, arg_fclass01 *a)
3634{
3635 return do_fop_ded(ctx, a->t, a->r, gen_fabs_d);
3636}
3637
3638static bool trans_fsqrt_f(DisasContext *ctx, arg_fclass01 *a)
3639{
3640 return do_fop_wew(ctx, a->t, a->r, gen_helper_fsqrt_s);
3641}
3642
3643static bool trans_fsqrt_d(DisasContext *ctx, arg_fclass01 *a)
3644{
3645 return do_fop_ded(ctx, a->t, a->r, gen_helper_fsqrt_d);
3646}
3647
3648static bool trans_frnd_f(DisasContext *ctx, arg_fclass01 *a)
3649{
3650 return do_fop_wew(ctx, a->t, a->r, gen_helper_frnd_s);
3651}
3652
3653static bool trans_frnd_d(DisasContext *ctx, arg_fclass01 *a)
3654{
3655 return do_fop_ded(ctx, a->t, a->r, gen_helper_frnd_d);
3656}
3657
3658static void gen_fneg_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3659{
3660 tcg_gen_xori_i32(dst, src, INT32_MIN);
3661}
3662
3663static bool trans_fneg_f(DisasContext *ctx, arg_fclass01 *a)
3664{
3665 return do_fop_wew(ctx, a->t, a->r, gen_fneg_f);
3666}
3667
3668static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3669{
3670 tcg_gen_xori_i64(dst, src, INT64_MIN);
3671}
3672
3673static bool trans_fneg_d(DisasContext *ctx, arg_fclass01 *a)
3674{
3675 return do_fop_ded(ctx, a->t, a->r, gen_fneg_d);
3676}
3677
3678static void gen_fnegabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3679{
3680 tcg_gen_ori_i32(dst, src, INT32_MIN);
3681}
3682
3683static bool trans_fnegabs_f(DisasContext *ctx, arg_fclass01 *a)
3684{
3685 return do_fop_wew(ctx, a->t, a->r, gen_fnegabs_f);
3686}
3687
3688static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3689{
3690 tcg_gen_ori_i64(dst, src, INT64_MIN);
3691}
3692
3693static bool trans_fnegabs_d(DisasContext *ctx, arg_fclass01 *a)
3694{
3695 return do_fop_ded(ctx, a->t, a->r, gen_fnegabs_d);
3696}
3697
3698
3699
3700
3701
3702static bool trans_fcnv_d_f(DisasContext *ctx, arg_fclass01 *a)
3703{
3704 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_s);
3705}
3706
3707static bool trans_fcnv_f_d(DisasContext *ctx, arg_fclass01 *a)
3708{
3709 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_d);
3710}
3711
3712static bool trans_fcnv_w_f(DisasContext *ctx, arg_fclass01 *a)
3713{
3714 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_w_s);
3715}
3716
3717static bool trans_fcnv_q_f(DisasContext *ctx, arg_fclass01 *a)
3718{
3719 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_dw_s);
3720}
3721
3722static bool trans_fcnv_w_d(DisasContext *ctx, arg_fclass01 *a)
3723{
3724 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_w_d);
3725}
3726
3727static bool trans_fcnv_q_d(DisasContext *ctx, arg_fclass01 *a)
3728{
3729 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_dw_d);
3730}
3731
3732static bool trans_fcnv_f_w(DisasContext *ctx, arg_fclass01 *a)
3733{
3734 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_w);
3735}
3736
3737static bool trans_fcnv_d_w(DisasContext *ctx, arg_fclass01 *a)
3738{
3739 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_w);
3740}
3741
3742static bool trans_fcnv_f_q(DisasContext *ctx, arg_fclass01 *a)
3743{
3744 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_dw);
3745}
3746
3747static bool trans_fcnv_d_q(DisasContext *ctx, arg_fclass01 *a)
3748{
3749 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_dw);
3750}
3751
3752static bool trans_fcnv_t_f_w(DisasContext *ctx, arg_fclass01 *a)
3753{
3754 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_w);
3755}
3756
3757static bool trans_fcnv_t_d_w(DisasContext *ctx, arg_fclass01 *a)
3758{
3759 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_w);
3760}
3761
3762static bool trans_fcnv_t_f_q(DisasContext *ctx, arg_fclass01 *a)
3763{
3764 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_dw);
3765}
3766
3767static bool trans_fcnv_t_d_q(DisasContext *ctx, arg_fclass01 *a)
3768{
3769 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_dw);
3770}
3771
3772static bool trans_fcnv_uw_f(DisasContext *ctx, arg_fclass01 *a)
3773{
3774 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_uw_s);
3775}
3776
3777static bool trans_fcnv_uq_f(DisasContext *ctx, arg_fclass01 *a)
3778{
3779 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_udw_s);
3780}
3781
3782static bool trans_fcnv_uw_d(DisasContext *ctx, arg_fclass01 *a)
3783{
3784 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_uw_d);
3785}
3786
3787static bool trans_fcnv_uq_d(DisasContext *ctx, arg_fclass01 *a)
3788{
3789 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_udw_d);
3790}
3791
3792static bool trans_fcnv_f_uw(DisasContext *ctx, arg_fclass01 *a)
3793{
3794 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_uw);
3795}
3796
3797static bool trans_fcnv_d_uw(DisasContext *ctx, arg_fclass01 *a)
3798{
3799 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_uw);
3800}
3801
3802static bool trans_fcnv_f_uq(DisasContext *ctx, arg_fclass01 *a)
3803{
3804 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_udw);
3805}
3806
3807static bool trans_fcnv_d_uq(DisasContext *ctx, arg_fclass01 *a)
3808{
3809 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_udw);
3810}
3811
3812static bool trans_fcnv_t_f_uw(DisasContext *ctx, arg_fclass01 *a)
3813{
3814 return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_uw);
3815}
3816
3817static bool trans_fcnv_t_d_uw(DisasContext *ctx, arg_fclass01 *a)
3818{
3819 return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_uw);
3820}
3821
3822static bool trans_fcnv_t_f_uq(DisasContext *ctx, arg_fclass01 *a)
3823{
3824 return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_udw);
3825}
3826
3827static bool trans_fcnv_t_d_uq(DisasContext *ctx, arg_fclass01 *a)
3828{
3829 return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_udw);
3830}
3831
3832
3833
3834
3835
3836static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
3837{
3838 TCGv_i32 ta, tb, tc, ty;
3839
3840 nullify_over(ctx);
3841
3842 ta = load_frw0_i32(a->r1);
3843 tb = load_frw0_i32(a->r2);
3844 ty = tcg_constant_i32(a->y);
3845 tc = tcg_constant_i32(a->c);
3846
3847 gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
3848
3849 tcg_temp_free_i32(ta);
3850 tcg_temp_free_i32(tb);
3851
3852 return nullify_end(ctx);
3853}
3854
3855static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
3856{
3857 TCGv_i64 ta, tb;
3858 TCGv_i32 tc, ty;
3859
3860 nullify_over(ctx);
3861
3862 ta = load_frd0(a->r1);
3863 tb = load_frd0(a->r2);
3864 ty = tcg_constant_i32(a->y);
3865 tc = tcg_constant_i32(a->c);
3866
3867 gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
3868
3869 tcg_temp_free_i64(ta);
3870 tcg_temp_free_i64(tb);
3871
3872 return nullify_end(ctx);
3873}
3874
3875static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
3876{
3877 TCGv_reg t;
3878
3879 nullify_over(ctx);
3880
3881 t = get_temp(ctx);
3882 tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3883
3884 if (a->y == 1) {
3885 int mask;
3886 bool inv = false;
3887
3888 switch (a->c) {
3889 case 0:
3890 tcg_gen_andi_reg(t, t, 0x4000000);
3891 ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3892 goto done;
3893 case 2:
3894 inv = true;
3895
3896 case 1:
3897 mask = 0x43ff800;
3898 break;
3899 case 6:
3900 inv = true;
3901
3902 case 5:
3903 mask = 0x43f8000;
3904 break;
3905 case 9:
3906 mask = 0x43e0000;
3907 break;
3908 case 13:
3909 mask = 0x4380000;
3910 break;
3911 case 17:
3912 mask = 0x4200000;
3913 break;
3914 default:
3915 gen_illegal(ctx);
3916 return true;
3917 }
3918 if (inv) {
3919 TCGv_reg c = load_const(ctx, mask);
3920 tcg_gen_or_reg(t, t, c);
3921 ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
3922 } else {
3923 tcg_gen_andi_reg(t, t, mask);
3924 ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
3925 }
3926 } else {
3927 unsigned cbit = (a->y ^ 1) - 1;
3928
3929 tcg_gen_extract_reg(t, t, 21 - cbit, 1);
3930 ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3931 tcg_temp_free(t);
3932 }
3933
3934 done:
3935 return nullify_end(ctx);
3936}
3937
3938
3939
3940
3941
3942static bool trans_fadd_f(DisasContext *ctx, arg_fclass3 *a)
3943{
3944 return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fadd_s);
3945}
3946
3947static bool trans_fadd_d(DisasContext *ctx, arg_fclass3 *a)
3948{
3949 return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fadd_d);
3950}
3951
3952static bool trans_fsub_f(DisasContext *ctx, arg_fclass3 *a)
3953{
3954 return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fsub_s);
3955}
3956
3957static bool trans_fsub_d(DisasContext *ctx, arg_fclass3 *a)
3958{
3959 return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fsub_d);
3960}
3961
3962static bool trans_fmpy_f(DisasContext *ctx, arg_fclass3 *a)
3963{
3964 return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_s);
3965}
3966
3967static bool trans_fmpy_d(DisasContext *ctx, arg_fclass3 *a)
3968{
3969 return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_d);
3970}
3971
3972static bool trans_fdiv_f(DisasContext *ctx, arg_fclass3 *a)
3973{
3974 return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_s);
3975}
3976
3977static bool trans_fdiv_d(DisasContext *ctx, arg_fclass3 *a)
3978{
3979 return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_d);
3980}
3981
3982static bool trans_xmpyu(DisasContext *ctx, arg_xmpyu *a)
3983{
3984 TCGv_i64 x, y;
3985
3986 nullify_over(ctx);
3987
3988 x = load_frw0_i64(a->r1);
3989 y = load_frw0_i64(a->r2);
3990 tcg_gen_mul_i64(x, x, y);
3991 save_frd(a->t, x);
3992 tcg_temp_free_i64(x);
3993 tcg_temp_free_i64(y);
3994
3995 return nullify_end(ctx);
3996}
3997
3998
3999static inline int fmpyadd_s_reg(unsigned r)
4000{
4001 return (r & 16) * 2 + 16 + (r & 15);
4002}
4003
4004static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4005{
4006 int tm = fmpyadd_s_reg(a->tm);
4007 int ra = fmpyadd_s_reg(a->ra);
4008 int ta = fmpyadd_s_reg(a->ta);
4009 int rm2 = fmpyadd_s_reg(a->rm2);
4010 int rm1 = fmpyadd_s_reg(a->rm1);
4011
4012 nullify_over(ctx);
4013
4014 do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
4015 do_fop_weww(ctx, ta, ta, ra,
4016 is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
4017
4018 return nullify_end(ctx);
4019}
4020
4021static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
4022{
4023 return do_fmpyadd_s(ctx, a, false);
4024}
4025
4026static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
4027{
4028 return do_fmpyadd_s(ctx, a, true);
4029}
4030
4031static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4032{
4033 nullify_over(ctx);
4034
4035 do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
4036 do_fop_dedd(ctx, a->ta, a->ta, a->ra,
4037 is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
4038
4039 return nullify_end(ctx);
4040}
4041
4042static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
4043{
4044 return do_fmpyadd_d(ctx, a, false);
4045}
4046
4047static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
4048{
4049 return do_fmpyadd_d(ctx, a, true);
4050}
4051
4052static bool trans_fmpyfadd_f(DisasContext *ctx, arg_fmpyfadd_f *a)
4053{
4054 TCGv_i32 x, y, z;
4055
4056 nullify_over(ctx);
4057 x = load_frw0_i32(a->rm1);
4058 y = load_frw0_i32(a->rm2);
4059 z = load_frw0_i32(a->ra3);
4060
4061 if (a->neg) {
4062 gen_helper_fmpynfadd_s(x, cpu_env, x, y, z);
4063 } else {
4064 gen_helper_fmpyfadd_s(x, cpu_env, x, y, z);
4065 }
4066
4067 tcg_temp_free_i32(y);
4068 tcg_temp_free_i32(z);
4069 save_frw_i32(a->t, x);
4070 tcg_temp_free_i32(x);
4071 return nullify_end(ctx);
4072}
4073
4074static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
4075{
4076 TCGv_i64 x, y, z;
4077
4078 nullify_over(ctx);
4079 x = load_frd0(a->rm1);
4080 y = load_frd0(a->rm2);
4081 z = load_frd0(a->ra3);
4082
4083 if (a->neg) {
4084 gen_helper_fmpynfadd_d(x, cpu_env, x, y, z);
4085 } else {
4086 gen_helper_fmpyfadd_d(x, cpu_env, x, y, z);
4087 }
4088
4089 tcg_temp_free_i64(y);
4090 tcg_temp_free_i64(z);
4091 save_frd(a->t, x);
4092 tcg_temp_free_i64(x);
4093 return nullify_end(ctx);
4094}
4095
4096static bool trans_diag(DisasContext *ctx, arg_diag *a)
4097{
4098 qemu_log_mask(LOG_UNIMP, "DIAG opcode ignored\n");
4099 cond_free(&ctx->null_cond);
4100 return true;
4101}
4102
4103static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4104{
4105 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4106 int bound;
4107
4108 ctx->cs = cs;
4109 ctx->tb_flags = ctx->base.tb->flags;
4110
4111#ifdef CONFIG_USER_ONLY
4112 ctx->privilege = MMU_USER_IDX;
4113 ctx->mmu_idx = MMU_USER_IDX;
4114 ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
4115 ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
4116#else
4117 ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
4118 ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX);
4119
4120
4121 uint64_t cs_base = ctx->base.tb->cs_base;
4122 uint64_t iasq_f = cs_base & ~0xffffffffull;
4123 int32_t diff = cs_base;
4124
4125 ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
4126 ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
4127#endif
4128 ctx->iaoq_n = -1;
4129 ctx->iaoq_n_var = NULL;
4130
4131
4132 bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
4133 ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
4134
4135 ctx->ntempr = 0;
4136 ctx->ntempl = 0;
4137 memset(ctx->tempr, 0, sizeof(ctx->tempr));
4138 memset(ctx->templ, 0, sizeof(ctx->templ));
4139}
4140
4141static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
4142{
4143 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4144
4145
4146 ctx->null_cond = cond_make_f();
4147 ctx->psw_n_nonzero = false;
4148 if (ctx->tb_flags & PSW_N) {
4149 ctx->null_cond.c = TCG_COND_ALWAYS;
4150 ctx->psw_n_nonzero = true;
4151 }
4152 ctx->null_lab = NULL;
4153}
4154
4155static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
4156{
4157 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4158
4159 tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
4160}
4161
4162static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
4163{
4164 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4165 CPUHPPAState *env = cs->env_ptr;
4166 DisasJumpType ret;
4167 int i, n;
4168
4169
4170#ifdef CONFIG_USER_ONLY
4171 if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
4172 do_page_zero(ctx);
4173 ret = ctx->base.is_jmp;
4174 assert(ret != DISAS_NEXT);
4175 } else
4176#endif
4177 {
4178
4179
4180 uint32_t insn = translator_ldl(env, ctx->base.pc_next);
4181
4182
4183
4184 if (ctx->iaoq_b == -1) {
4185 ctx->iaoq_n = -1;
4186 ctx->iaoq_n_var = get_temp(ctx);
4187 tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
4188 } else {
4189 ctx->iaoq_n = ctx->iaoq_b + 4;
4190 ctx->iaoq_n_var = NULL;
4191 }
4192
4193 if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
4194 ctx->null_cond.c = TCG_COND_NEVER;
4195 ret = DISAS_NEXT;
4196 } else {
4197 ctx->insn = insn;
4198 if (!decode(ctx, insn)) {
4199 gen_illegal(ctx);
4200 }
4201 ret = ctx->base.is_jmp;
4202 assert(ctx->null_lab == NULL);
4203 }
4204 }
4205
4206
4207 for (i = 0, n = ctx->ntempr; i < n; ++i) {
4208 tcg_temp_free(ctx->tempr[i]);
4209 ctx->tempr[i] = NULL;
4210 }
4211 for (i = 0, n = ctx->ntempl; i < n; ++i) {
4212 tcg_temp_free_tl(ctx->templ[i]);
4213 ctx->templ[i] = NULL;
4214 }
4215 ctx->ntempr = 0;
4216 ctx->ntempl = 0;
4217
4218
4219
4220 if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
4221 if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1
4222 && use_goto_tb(ctx, ctx->iaoq_b)
4223 && (ctx->null_cond.c == TCG_COND_NEVER
4224 || ctx->null_cond.c == TCG_COND_ALWAYS)) {
4225 nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
4226 gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
4227 ctx->base.is_jmp = ret = DISAS_NORETURN;
4228 } else {
4229 ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
4230 }
4231 }
4232 ctx->iaoq_f = ctx->iaoq_b;
4233 ctx->iaoq_b = ctx->iaoq_n;
4234 ctx->base.pc_next += 4;
4235
4236 switch (ret) {
4237 case DISAS_NORETURN:
4238 case DISAS_IAQ_N_UPDATED:
4239 break;
4240
4241 case DISAS_NEXT:
4242 case DISAS_IAQ_N_STALE:
4243 case DISAS_IAQ_N_STALE_EXIT:
4244 if (ctx->iaoq_f == -1) {
4245 tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
4246 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4247#ifndef CONFIG_USER_ONLY
4248 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4249#endif
4250 nullify_save(ctx);
4251 ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
4252 ? DISAS_EXIT
4253 : DISAS_IAQ_N_UPDATED);
4254 } else if (ctx->iaoq_b == -1) {
4255 tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
4256 }
4257 break;
4258
4259 default:
4260 g_assert_not_reached();
4261 }
4262}
4263
4264static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
4265{
4266 DisasContext *ctx = container_of(dcbase, DisasContext, base);
4267 DisasJumpType is_jmp = ctx->base.is_jmp;
4268
4269 switch (is_jmp) {
4270 case DISAS_NORETURN:
4271 break;
4272 case DISAS_TOO_MANY:
4273 case DISAS_IAQ_N_STALE:
4274 case DISAS_IAQ_N_STALE_EXIT:
4275 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4276 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4277 nullify_save(ctx);
4278
4279 case DISAS_IAQ_N_UPDATED:
4280 if (ctx->base.singlestep_enabled) {
4281 gen_excp_1(EXCP_DEBUG);
4282 } else if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
4283 tcg_gen_lookup_and_goto_ptr();
4284 }
4285
4286 case DISAS_EXIT:
4287 tcg_gen_exit_tb(NULL, 0);
4288 break;
4289 default:
4290 g_assert_not_reached();
4291 }
4292}
4293
4294static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
4295{
4296 target_ulong pc = dcbase->pc_first;
4297
4298#ifdef CONFIG_USER_ONLY
4299 switch (pc) {
4300 case 0x00:
4301 qemu_log("IN:\n0x00000000: (null)\n");
4302 return;
4303 case 0xb0:
4304 qemu_log("IN:\n0x000000b0: light-weight-syscall\n");
4305 return;
4306 case 0xe0:
4307 qemu_log("IN:\n0x000000e0: set-thread-pointer-syscall\n");
4308 return;
4309 case 0x100:
4310 qemu_log("IN:\n0x00000100: syscall\n");
4311 return;
4312 }
4313#endif
4314
4315 qemu_log("IN: %s\n", lookup_symbol(pc));
4316 log_target_disas(cs, pc, dcbase->tb->size);
4317}
4318
4319static const TranslatorOps hppa_tr_ops = {
4320 .init_disas_context = hppa_tr_init_disas_context,
4321 .tb_start = hppa_tr_tb_start,
4322 .insn_start = hppa_tr_insn_start,
4323 .translate_insn = hppa_tr_translate_insn,
4324 .tb_stop = hppa_tr_tb_stop,
4325 .disas_log = hppa_tr_disas_log,
4326};
4327
4328void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
4329{
4330 DisasContext ctx;
4331 translator_loop(&hppa_tr_ops, &ctx.base, cs, tb, max_insns);
4332}
4333
4334void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
4335 target_ulong *data)
4336{
4337 env->iaoq_f = data[0];
4338 if (data[1] != (target_ureg)-1) {
4339 env->iaoq_b = data[1];
4340 }
4341
4342
4343
4344 env->psw_n = 0;
4345}
4346