xref: /openbmc/qemu/target/hppa/translate.c (revision 3df4c288)
1 /*
2  * HPPA emulation cpu translation for qemu.
3  *
4  * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
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 "tcg/tcg-op-gvec.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 #define HELPER_H "helper.h"
33 #include "exec/helper-info.c.inc"
34 #undef  HELPER_H
35 
36 /* Choose to use explicit sizes within this file. */
37 #undef tcg_temp_new
38 
39 typedef struct DisasCond {
40     TCGCond c;
41     TCGv_i64 a0, a1;
42 } DisasCond;
43 
44 typedef struct DisasContext {
45     DisasContextBase base;
46     CPUState *cs;
47 
48     uint64_t iaoq_f;
49     uint64_t iaoq_b;
50     uint64_t iaoq_n;
51     TCGv_i64 iaoq_n_var;
52 
53     DisasCond null_cond;
54     TCGLabel *null_lab;
55 
56     TCGv_i64 zero;
57 
58     uint32_t insn;
59     uint32_t tb_flags;
60     int mmu_idx;
61     int privilege;
62     bool psw_n_nonzero;
63     bool is_pa20;
64     bool insn_start_updated;
65 
66 #ifdef CONFIG_USER_ONLY
67     MemOp unalign;
68 #endif
69 } DisasContext;
70 
71 #ifdef CONFIG_USER_ONLY
72 #define UNALIGN(C)       (C)->unalign
73 #define MMU_DISABLED(C)  false
74 #else
75 #define UNALIGN(C)       MO_ALIGN
76 #define MMU_DISABLED(C)  MMU_IDX_MMU_DISABLED((C)->mmu_idx)
77 #endif
78 
79 /* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
80 static int expand_sm_imm(DisasContext *ctx, int val)
81 {
82     /* Keep unimplemented bits disabled -- see cpu_hppa_put_psw. */
83     if (ctx->is_pa20) {
84         if (val & PSW_SM_W) {
85             val |= PSW_W;
86         }
87         val &= ~(PSW_SM_W | PSW_SM_E | PSW_G);
88     } else {
89         val &= ~(PSW_SM_W | PSW_SM_E | PSW_O);
90     }
91     return val;
92 }
93 
94 /* Inverted space register indicates 0 means sr0 not inferred from base.  */
95 static int expand_sr3x(DisasContext *ctx, int val)
96 {
97     return ~val;
98 }
99 
100 /* Convert the M:A bits within a memory insn to the tri-state value
101    we use for the final M.  */
102 static int ma_to_m(DisasContext *ctx, int val)
103 {
104     return val & 2 ? (val & 1 ? -1 : 1) : 0;
105 }
106 
107 /* Convert the sign of the displacement to a pre or post-modify.  */
108 static int pos_to_m(DisasContext *ctx, int val)
109 {
110     return val ? 1 : -1;
111 }
112 
113 static int neg_to_m(DisasContext *ctx, int val)
114 {
115     return val ? -1 : 1;
116 }
117 
118 /* Used for branch targets and fp memory ops.  */
119 static int expand_shl2(DisasContext *ctx, int val)
120 {
121     return val << 2;
122 }
123 
124 /* Used for assemble_21.  */
125 static int expand_shl11(DisasContext *ctx, int val)
126 {
127     return val << 11;
128 }
129 
130 static int assemble_6(DisasContext *ctx, int val)
131 {
132     /*
133      * Officially, 32 * x + 32 - y.
134      * Here, x is already in bit 5, and y is [4:0].
135      * Since -y = ~y + 1, in 5 bits 32 - y => y ^ 31 + 1,
136      * with the overflow from bit 4 summing with x.
137      */
138     return (val ^ 31) + 1;
139 }
140 
141 /* Expander for assemble_16a(s,cat(im10a,0),i). */
142 static int expand_11a(DisasContext *ctx, int val)
143 {
144     /*
145      * @val is bit 0 and bits [4:15].
146      * Swizzle thing around depending on PSW.W.
147      */
148     int im10a = extract32(val, 1, 10);
149     int s = extract32(val, 11, 2);
150     int i = (-(val & 1) << 13) | (im10a << 3);
151 
152     if (ctx->tb_flags & PSW_W) {
153         i ^= s << 13;
154     }
155     return i;
156 }
157 
158 /* Expander for assemble_16a(s,im11a,i). */
159 static int expand_12a(DisasContext *ctx, int val)
160 {
161     /*
162      * @val is bit 0 and bits [3:15].
163      * Swizzle thing around depending on PSW.W.
164      */
165     int im11a = extract32(val, 1, 11);
166     int s = extract32(val, 12, 2);
167     int i = (-(val & 1) << 13) | (im11a << 2);
168 
169     if (ctx->tb_flags & PSW_W) {
170         i ^= s << 13;
171     }
172     return i;
173 }
174 
175 /* Expander for assemble_16(s,im14). */
176 static int expand_16(DisasContext *ctx, int val)
177 {
178     /*
179      * @val is bits [0:15], containing both im14 and s.
180      * Swizzle thing around depending on PSW.W.
181      */
182     int s = extract32(val, 14, 2);
183     int i = (-(val & 1) << 13) | extract32(val, 1, 13);
184 
185     if (ctx->tb_flags & PSW_W) {
186         i ^= s << 13;
187     }
188     return i;
189 }
190 
191 /* The sp field is only present with !PSW_W. */
192 static int sp0_if_wide(DisasContext *ctx, int sp)
193 {
194     return ctx->tb_flags & PSW_W ? 0 : sp;
195 }
196 
197 /* Translate CMPI doubleword conditions to standard. */
198 static int cmpbid_c(DisasContext *ctx, int val)
199 {
200     return val ? val : 4; /* 0 == "*<<" */
201 }
202 
203 /*
204  * In many places pa1.x did not decode the bit that later became
205  * the pa2.0 D bit.  Suppress D unless the cpu is pa2.0.
206  */
207 static int pa20_d(DisasContext *ctx, int val)
208 {
209     return ctx->is_pa20 & val;
210 }
211 
212 /* Include the auto-generated decoder.  */
213 #include "decode-insns.c.inc"
214 
215 /* We are not using a goto_tb (for whatever reason), but have updated
216    the iaq (for whatever reason), so don't do it again on exit.  */
217 #define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
218 
219 /* We are exiting the TB, but have neither emitted a goto_tb, nor
220    updated the iaq for the next instruction to be executed.  */
221 #define DISAS_IAQ_N_STALE    DISAS_TARGET_1
222 
223 /* Similarly, but we want to return to the main loop immediately
224    to recognize unmasked interrupts.  */
225 #define DISAS_IAQ_N_STALE_EXIT      DISAS_TARGET_2
226 #define DISAS_EXIT                  DISAS_TARGET_3
227 
228 /* global register indexes */
229 static TCGv_i64 cpu_gr[32];
230 static TCGv_i64 cpu_sr[4];
231 static TCGv_i64 cpu_srH;
232 static TCGv_i64 cpu_iaoq_f;
233 static TCGv_i64 cpu_iaoq_b;
234 static TCGv_i64 cpu_iasq_f;
235 static TCGv_i64 cpu_iasq_b;
236 static TCGv_i64 cpu_sar;
237 static TCGv_i64 cpu_psw_n;
238 static TCGv_i64 cpu_psw_v;
239 static TCGv_i64 cpu_psw_cb;
240 static TCGv_i64 cpu_psw_cb_msb;
241 
242 void hppa_translate_init(void)
243 {
244 #define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
245 
246     typedef struct { TCGv_i64 *var; const char *name; int ofs; } GlobalVar;
247     static const GlobalVar vars[] = {
248         { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) },
249         DEF_VAR(psw_n),
250         DEF_VAR(psw_v),
251         DEF_VAR(psw_cb),
252         DEF_VAR(psw_cb_msb),
253         DEF_VAR(iaoq_f),
254         DEF_VAR(iaoq_b),
255     };
256 
257 #undef DEF_VAR
258 
259     /* Use the symbolic register names that match the disassembler.  */
260     static const char gr_names[32][4] = {
261         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
262         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
263         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
264         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
265     };
266     /* SR[4-7] are not global registers so that we can index them.  */
267     static const char sr_names[5][4] = {
268         "sr0", "sr1", "sr2", "sr3", "srH"
269     };
270 
271     int i;
272 
273     cpu_gr[0] = NULL;
274     for (i = 1; i < 32; i++) {
275         cpu_gr[i] = tcg_global_mem_new(tcg_env,
276                                        offsetof(CPUHPPAState, gr[i]),
277                                        gr_names[i]);
278     }
279     for (i = 0; i < 4; i++) {
280         cpu_sr[i] = tcg_global_mem_new_i64(tcg_env,
281                                            offsetof(CPUHPPAState, sr[i]),
282                                            sr_names[i]);
283     }
284     cpu_srH = tcg_global_mem_new_i64(tcg_env,
285                                      offsetof(CPUHPPAState, sr[4]),
286                                      sr_names[4]);
287 
288     for (i = 0; i < ARRAY_SIZE(vars); ++i) {
289         const GlobalVar *v = &vars[i];
290         *v->var = tcg_global_mem_new(tcg_env, v->ofs, v->name);
291     }
292 
293     cpu_iasq_f = tcg_global_mem_new_i64(tcg_env,
294                                         offsetof(CPUHPPAState, iasq_f),
295                                         "iasq_f");
296     cpu_iasq_b = tcg_global_mem_new_i64(tcg_env,
297                                         offsetof(CPUHPPAState, iasq_b),
298                                         "iasq_b");
299 }
300 
301 static void set_insn_breg(DisasContext *ctx, int breg)
302 {
303     assert(!ctx->insn_start_updated);
304     ctx->insn_start_updated = true;
305     tcg_set_insn_start_param(ctx->base.insn_start, 2, breg);
306 }
307 
308 static DisasCond cond_make_f(void)
309 {
310     return (DisasCond){
311         .c = TCG_COND_NEVER,
312         .a0 = NULL,
313         .a1 = NULL,
314     };
315 }
316 
317 static DisasCond cond_make_t(void)
318 {
319     return (DisasCond){
320         .c = TCG_COND_ALWAYS,
321         .a0 = NULL,
322         .a1 = NULL,
323     };
324 }
325 
326 static DisasCond cond_make_n(void)
327 {
328     return (DisasCond){
329         .c = TCG_COND_NE,
330         .a0 = cpu_psw_n,
331         .a1 = tcg_constant_i64(0)
332     };
333 }
334 
335 static DisasCond cond_make_tmp(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
336 {
337     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
338     return (DisasCond){ .c = c, .a0 = a0, .a1 = a1 };
339 }
340 
341 static DisasCond cond_make_0_tmp(TCGCond c, TCGv_i64 a0)
342 {
343     return cond_make_tmp(c, a0, tcg_constant_i64(0));
344 }
345 
346 static DisasCond cond_make_0(TCGCond c, TCGv_i64 a0)
347 {
348     TCGv_i64 tmp = tcg_temp_new_i64();
349     tcg_gen_mov_i64(tmp, a0);
350     return cond_make_0_tmp(c, tmp);
351 }
352 
353 static DisasCond cond_make(TCGCond c, TCGv_i64 a0, TCGv_i64 a1)
354 {
355     TCGv_i64 t0 = tcg_temp_new_i64();
356     TCGv_i64 t1 = tcg_temp_new_i64();
357 
358     tcg_gen_mov_i64(t0, a0);
359     tcg_gen_mov_i64(t1, a1);
360     return cond_make_tmp(c, t0, t1);
361 }
362 
363 static void cond_free(DisasCond *cond)
364 {
365     switch (cond->c) {
366     default:
367         cond->a0 = NULL;
368         cond->a1 = NULL;
369         /* fallthru */
370     case TCG_COND_ALWAYS:
371         cond->c = TCG_COND_NEVER;
372         break;
373     case TCG_COND_NEVER:
374         break;
375     }
376 }
377 
378 static TCGv_i64 load_gpr(DisasContext *ctx, unsigned reg)
379 {
380     if (reg == 0) {
381         return ctx->zero;
382     } else {
383         return cpu_gr[reg];
384     }
385 }
386 
387 static TCGv_i64 dest_gpr(DisasContext *ctx, unsigned reg)
388 {
389     if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
390         return tcg_temp_new_i64();
391     } else {
392         return cpu_gr[reg];
393     }
394 }
395 
396 static void save_or_nullify(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 t)
397 {
398     if (ctx->null_cond.c != TCG_COND_NEVER) {
399         tcg_gen_movcond_i64(ctx->null_cond.c, dest, ctx->null_cond.a0,
400                             ctx->null_cond.a1, dest, t);
401     } else {
402         tcg_gen_mov_i64(dest, t);
403     }
404 }
405 
406 static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_i64 t)
407 {
408     if (reg != 0) {
409         save_or_nullify(ctx, cpu_gr[reg], t);
410     }
411 }
412 
413 #if HOST_BIG_ENDIAN
414 # define HI_OFS  0
415 # define LO_OFS  4
416 #else
417 # define HI_OFS  4
418 # define LO_OFS  0
419 #endif
420 
421 static TCGv_i32 load_frw_i32(unsigned rt)
422 {
423     TCGv_i32 ret = tcg_temp_new_i32();
424     tcg_gen_ld_i32(ret, tcg_env,
425                    offsetof(CPUHPPAState, fr[rt & 31])
426                    + (rt & 32 ? LO_OFS : HI_OFS));
427     return ret;
428 }
429 
430 static TCGv_i32 load_frw0_i32(unsigned rt)
431 {
432     if (rt == 0) {
433         TCGv_i32 ret = tcg_temp_new_i32();
434         tcg_gen_movi_i32(ret, 0);
435         return ret;
436     } else {
437         return load_frw_i32(rt);
438     }
439 }
440 
441 static TCGv_i64 load_frw0_i64(unsigned rt)
442 {
443     TCGv_i64 ret = tcg_temp_new_i64();
444     if (rt == 0) {
445         tcg_gen_movi_i64(ret, 0);
446     } else {
447         tcg_gen_ld32u_i64(ret, tcg_env,
448                           offsetof(CPUHPPAState, fr[rt & 31])
449                           + (rt & 32 ? LO_OFS : HI_OFS));
450     }
451     return ret;
452 }
453 
454 static void save_frw_i32(unsigned rt, TCGv_i32 val)
455 {
456     tcg_gen_st_i32(val, tcg_env,
457                    offsetof(CPUHPPAState, fr[rt & 31])
458                    + (rt & 32 ? LO_OFS : HI_OFS));
459 }
460 
461 #undef HI_OFS
462 #undef LO_OFS
463 
464 static TCGv_i64 load_frd(unsigned rt)
465 {
466     TCGv_i64 ret = tcg_temp_new_i64();
467     tcg_gen_ld_i64(ret, tcg_env, offsetof(CPUHPPAState, fr[rt]));
468     return ret;
469 }
470 
471 static TCGv_i64 load_frd0(unsigned rt)
472 {
473     if (rt == 0) {
474         TCGv_i64 ret = tcg_temp_new_i64();
475         tcg_gen_movi_i64(ret, 0);
476         return ret;
477     } else {
478         return load_frd(rt);
479     }
480 }
481 
482 static void save_frd(unsigned rt, TCGv_i64 val)
483 {
484     tcg_gen_st_i64(val, tcg_env, offsetof(CPUHPPAState, fr[rt]));
485 }
486 
487 static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
488 {
489 #ifdef CONFIG_USER_ONLY
490     tcg_gen_movi_i64(dest, 0);
491 #else
492     if (reg < 4) {
493         tcg_gen_mov_i64(dest, cpu_sr[reg]);
494     } else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
495         tcg_gen_mov_i64(dest, cpu_srH);
496     } else {
497         tcg_gen_ld_i64(dest, tcg_env, offsetof(CPUHPPAState, sr[reg]));
498     }
499 #endif
500 }
501 
502 /* Skip over the implementation of an insn that has been nullified.
503    Use this when the insn is too complex for a conditional move.  */
504 static void nullify_over(DisasContext *ctx)
505 {
506     if (ctx->null_cond.c != TCG_COND_NEVER) {
507         /* The always condition should have been handled in the main loop.  */
508         assert(ctx->null_cond.c != TCG_COND_ALWAYS);
509 
510         ctx->null_lab = gen_new_label();
511 
512         /* If we're using PSW[N], copy it to a temp because... */
513         if (ctx->null_cond.a0 == cpu_psw_n) {
514             ctx->null_cond.a0 = tcg_temp_new_i64();
515             tcg_gen_mov_i64(ctx->null_cond.a0, cpu_psw_n);
516         }
517         /* ... we clear it before branching over the implementation,
518            so that (1) it's clear after nullifying this insn and
519            (2) if this insn nullifies the next, PSW[N] is valid.  */
520         if (ctx->psw_n_nonzero) {
521             ctx->psw_n_nonzero = false;
522             tcg_gen_movi_i64(cpu_psw_n, 0);
523         }
524 
525         tcg_gen_brcond_i64(ctx->null_cond.c, ctx->null_cond.a0,
526                            ctx->null_cond.a1, ctx->null_lab);
527         cond_free(&ctx->null_cond);
528     }
529 }
530 
531 /* Save the current nullification state to PSW[N].  */
532 static void nullify_save(DisasContext *ctx)
533 {
534     if (ctx->null_cond.c == TCG_COND_NEVER) {
535         if (ctx->psw_n_nonzero) {
536             tcg_gen_movi_i64(cpu_psw_n, 0);
537         }
538         return;
539     }
540     if (ctx->null_cond.a0 != cpu_psw_n) {
541         tcg_gen_setcond_i64(ctx->null_cond.c, cpu_psw_n,
542                             ctx->null_cond.a0, ctx->null_cond.a1);
543         ctx->psw_n_nonzero = true;
544     }
545     cond_free(&ctx->null_cond);
546 }
547 
548 /* Set a PSW[N] to X.  The intention is that this is used immediately
549    before a goto_tb/exit_tb, so that there is no fallthru path to other
550    code within the TB.  Therefore we do not update psw_n_nonzero.  */
551 static void nullify_set(DisasContext *ctx, bool x)
552 {
553     if (ctx->psw_n_nonzero || x) {
554         tcg_gen_movi_i64(cpu_psw_n, x);
555     }
556 }
557 
558 /* Mark the end of an instruction that may have been nullified.
559    This is the pair to nullify_over.  Always returns true so that
560    it may be tail-called from a translate function.  */
561 static bool nullify_end(DisasContext *ctx)
562 {
563     TCGLabel *null_lab = ctx->null_lab;
564     DisasJumpType status = ctx->base.is_jmp;
565 
566     /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
567        For UPDATED, we cannot update on the nullified path.  */
568     assert(status != DISAS_IAQ_N_UPDATED);
569 
570     if (likely(null_lab == NULL)) {
571         /* The current insn wasn't conditional or handled the condition
572            applied to it without a branch, so the (new) setting of
573            NULL_COND can be applied directly to the next insn.  */
574         return true;
575     }
576     ctx->null_lab = NULL;
577 
578     if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
579         /* The next instruction will be unconditional,
580            and NULL_COND already reflects that.  */
581         gen_set_label(null_lab);
582     } else {
583         /* The insn that we just executed is itself nullifying the next
584            instruction.  Store the condition in the PSW[N] global.
585            We asserted PSW[N] = 0 in nullify_over, so that after the
586            label we have the proper value in place.  */
587         nullify_save(ctx);
588         gen_set_label(null_lab);
589         ctx->null_cond = cond_make_n();
590     }
591     if (status == DISAS_NORETURN) {
592         ctx->base.is_jmp = DISAS_NEXT;
593     }
594     return true;
595 }
596 
597 static void copy_iaoq_entry(DisasContext *ctx, TCGv_i64 dest,
598                             uint64_t ival, TCGv_i64 vval)
599 {
600     uint64_t mask = gva_offset_mask(ctx->tb_flags);
601 
602     if (ival != -1) {
603         tcg_gen_movi_i64(dest, ival & mask);
604         return;
605     }
606     tcg_debug_assert(vval != NULL);
607 
608     /*
609      * We know that the IAOQ is already properly masked.
610      * This optimization is primarily for "iaoq_f = iaoq_b".
611      */
612     if (vval == cpu_iaoq_f || vval == cpu_iaoq_b) {
613         tcg_gen_mov_i64(dest, vval);
614     } else {
615         tcg_gen_andi_i64(dest, vval, mask);
616     }
617 }
618 
619 static inline uint64_t iaoq_dest(DisasContext *ctx, int64_t disp)
620 {
621     return ctx->iaoq_f + disp + 8;
622 }
623 
624 static void gen_excp_1(int exception)
625 {
626     gen_helper_excp(tcg_env, tcg_constant_i32(exception));
627 }
628 
629 static void gen_excp(DisasContext *ctx, int exception)
630 {
631     copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
632     copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
633     nullify_save(ctx);
634     gen_excp_1(exception);
635     ctx->base.is_jmp = DISAS_NORETURN;
636 }
637 
638 static bool gen_excp_iir(DisasContext *ctx, int exc)
639 {
640     nullify_over(ctx);
641     tcg_gen_st_i64(tcg_constant_i64(ctx->insn),
642                    tcg_env, offsetof(CPUHPPAState, cr[CR_IIR]));
643     gen_excp(ctx, exc);
644     return nullify_end(ctx);
645 }
646 
647 static bool gen_illegal(DisasContext *ctx)
648 {
649     return gen_excp_iir(ctx, EXCP_ILL);
650 }
651 
652 #ifdef CONFIG_USER_ONLY
653 #define CHECK_MOST_PRIVILEGED(EXCP) \
654     return gen_excp_iir(ctx, EXCP)
655 #else
656 #define CHECK_MOST_PRIVILEGED(EXCP) \
657     do {                                     \
658         if (ctx->privilege != 0) {           \
659             return gen_excp_iir(ctx, EXCP);  \
660         }                                    \
661     } while (0)
662 #endif
663 
664 static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
665 {
666     return translator_use_goto_tb(&ctx->base, dest);
667 }
668 
669 /* If the next insn is to be nullified, and it's on the same page,
670    and we're not attempting to set a breakpoint on it, then we can
671    totally skip the nullified insn.  This avoids creating and
672    executing a TB that merely branches to the next TB.  */
673 static bool use_nullify_skip(DisasContext *ctx)
674 {
675     return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
676             && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
677 }
678 
679 static void gen_goto_tb(DisasContext *ctx, int which,
680                         uint64_t f, uint64_t b)
681 {
682     if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
683         tcg_gen_goto_tb(which);
684         copy_iaoq_entry(ctx, cpu_iaoq_f, f, NULL);
685         copy_iaoq_entry(ctx, cpu_iaoq_b, b, NULL);
686         tcg_gen_exit_tb(ctx->base.tb, which);
687     } else {
688         copy_iaoq_entry(ctx, cpu_iaoq_f, f, cpu_iaoq_b);
689         copy_iaoq_entry(ctx, cpu_iaoq_b, b, ctx->iaoq_n_var);
690         tcg_gen_lookup_and_goto_ptr();
691     }
692 }
693 
694 static bool cond_need_sv(int c)
695 {
696     return c == 2 || c == 3 || c == 6;
697 }
698 
699 static bool cond_need_cb(int c)
700 {
701     return c == 4 || c == 5;
702 }
703 
704 /*
705  * Compute conditional for arithmetic.  See Page 5-3, Table 5-1, of
706  * the Parisc 1.1 Architecture Reference Manual for details.
707  */
708 
709 static DisasCond do_cond(DisasContext *ctx, unsigned cf, bool d,
710                          TCGv_i64 res, TCGv_i64 uv, TCGv_i64 sv)
711 {
712     DisasCond cond;
713     TCGv_i64 tmp;
714 
715     switch (cf >> 1) {
716     case 0: /* Never / TR    (0 / 1) */
717         cond = cond_make_f();
718         break;
719     case 1: /* = / <>        (Z / !Z) */
720         if (!d) {
721             tmp = tcg_temp_new_i64();
722             tcg_gen_ext32u_i64(tmp, res);
723             res = tmp;
724         }
725         cond = cond_make_0(TCG_COND_EQ, res);
726         break;
727     case 2: /* < / >=        (N ^ V / !(N ^ V) */
728         tmp = tcg_temp_new_i64();
729         tcg_gen_xor_i64(tmp, res, sv);
730         if (!d) {
731             tcg_gen_ext32s_i64(tmp, tmp);
732         }
733         cond = cond_make_0_tmp(TCG_COND_LT, tmp);
734         break;
735     case 3: /* <= / >        (N ^ V) | Z / !((N ^ V) | Z) */
736         /*
737          * Simplify:
738          *   (N ^ V) | Z
739          *   ((res < 0) ^ (sv < 0)) | !res
740          *   ((res ^ sv) < 0) | !res
741          *   (~(res ^ sv) >= 0) | !res
742          *   !(~(res ^ sv) >> 31) | !res
743          *   !(~(res ^ sv) >> 31 & res)
744          */
745         tmp = tcg_temp_new_i64();
746         tcg_gen_eqv_i64(tmp, res, sv);
747         if (!d) {
748             tcg_gen_sextract_i64(tmp, tmp, 31, 1);
749             tcg_gen_and_i64(tmp, tmp, res);
750             tcg_gen_ext32u_i64(tmp, tmp);
751         } else {
752             tcg_gen_sari_i64(tmp, tmp, 63);
753             tcg_gen_and_i64(tmp, tmp, res);
754         }
755         cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
756         break;
757     case 4: /* NUV / UV      (!UV / UV) */
758         cond = cond_make_0(TCG_COND_EQ, uv);
759         break;
760     case 5: /* ZNV / VNZ     (!UV | Z / UV & !Z) */
761         tmp = tcg_temp_new_i64();
762         tcg_gen_movcond_i64(TCG_COND_EQ, tmp, uv, ctx->zero, ctx->zero, res);
763         if (!d) {
764             tcg_gen_ext32u_i64(tmp, tmp);
765         }
766         cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
767         break;
768     case 6: /* SV / NSV      (V / !V) */
769         if (!d) {
770             tmp = tcg_temp_new_i64();
771             tcg_gen_ext32s_i64(tmp, sv);
772             sv = tmp;
773         }
774         cond = cond_make_0(TCG_COND_LT, sv);
775         break;
776     case 7: /* OD / EV */
777         tmp = tcg_temp_new_i64();
778         tcg_gen_andi_i64(tmp, res, 1);
779         cond = cond_make_0_tmp(TCG_COND_NE, tmp);
780         break;
781     default:
782         g_assert_not_reached();
783     }
784     if (cf & 1) {
785         cond.c = tcg_invert_cond(cond.c);
786     }
787 
788     return cond;
789 }
790 
791 /* Similar, but for the special case of subtraction without borrow, we
792    can use the inputs directly.  This can allow other computation to be
793    deleted as unused.  */
794 
795 static DisasCond do_sub_cond(DisasContext *ctx, unsigned cf, bool d,
796                              TCGv_i64 res, TCGv_i64 in1,
797                              TCGv_i64 in2, TCGv_i64 sv)
798 {
799     TCGCond tc;
800     bool ext_uns;
801 
802     switch (cf >> 1) {
803     case 1: /* = / <> */
804         tc = TCG_COND_EQ;
805         ext_uns = true;
806         break;
807     case 2: /* < / >= */
808         tc = TCG_COND_LT;
809         ext_uns = false;
810         break;
811     case 3: /* <= / > */
812         tc = TCG_COND_LE;
813         ext_uns = false;
814         break;
815     case 4: /* << / >>= */
816         tc = TCG_COND_LTU;
817         ext_uns = true;
818         break;
819     case 5: /* <<= / >> */
820         tc = TCG_COND_LEU;
821         ext_uns = true;
822         break;
823     default:
824         return do_cond(ctx, cf, d, res, NULL, sv);
825     }
826 
827     if (cf & 1) {
828         tc = tcg_invert_cond(tc);
829     }
830     if (!d) {
831         TCGv_i64 t1 = tcg_temp_new_i64();
832         TCGv_i64 t2 = tcg_temp_new_i64();
833 
834         if (ext_uns) {
835             tcg_gen_ext32u_i64(t1, in1);
836             tcg_gen_ext32u_i64(t2, in2);
837         } else {
838             tcg_gen_ext32s_i64(t1, in1);
839             tcg_gen_ext32s_i64(t2, in2);
840         }
841         return cond_make_tmp(tc, t1, t2);
842     }
843     return cond_make(tc, in1, in2);
844 }
845 
846 /*
847  * Similar, but for logicals, where the carry and overflow bits are not
848  * computed, and use of them is undefined.
849  *
850  * Undefined or not, hardware does not trap.  It seems reasonable to
851  * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's
852  * how cases c={2,3} are treated.
853  */
854 
855 static DisasCond do_log_cond(DisasContext *ctx, unsigned cf, bool d,
856                              TCGv_i64 res)
857 {
858     TCGCond tc;
859     bool ext_uns;
860 
861     switch (cf) {
862     case 0:  /* never */
863     case 9:  /* undef, C */
864     case 11: /* undef, C & !Z */
865     case 12: /* undef, V */
866         return cond_make_f();
867 
868     case 1:  /* true */
869     case 8:  /* undef, !C */
870     case 10: /* undef, !C | Z */
871     case 13: /* undef, !V */
872         return cond_make_t();
873 
874     case 2:  /* == */
875         tc = TCG_COND_EQ;
876         ext_uns = true;
877         break;
878     case 3:  /* <> */
879         tc = TCG_COND_NE;
880         ext_uns = true;
881         break;
882     case 4:  /* < */
883         tc = TCG_COND_LT;
884         ext_uns = false;
885         break;
886     case 5:  /* >= */
887         tc = TCG_COND_GE;
888         ext_uns = false;
889         break;
890     case 6:  /* <= */
891         tc = TCG_COND_LE;
892         ext_uns = false;
893         break;
894     case 7:  /* > */
895         tc = TCG_COND_GT;
896         ext_uns = false;
897         break;
898 
899     case 14: /* OD */
900     case 15: /* EV */
901         return do_cond(ctx, cf, d, res, NULL, NULL);
902 
903     default:
904         g_assert_not_reached();
905     }
906 
907     if (!d) {
908         TCGv_i64 tmp = tcg_temp_new_i64();
909 
910         if (ext_uns) {
911             tcg_gen_ext32u_i64(tmp, res);
912         } else {
913             tcg_gen_ext32s_i64(tmp, res);
914         }
915         return cond_make_0_tmp(tc, tmp);
916     }
917     return cond_make_0(tc, res);
918 }
919 
920 /* Similar, but for shift/extract/deposit conditions.  */
921 
922 static DisasCond do_sed_cond(DisasContext *ctx, unsigned orig, bool d,
923                              TCGv_i64 res)
924 {
925     unsigned c, f;
926 
927     /* Convert the compressed condition codes to standard.
928        0-2 are the same as logicals (nv,<,<=), while 3 is OD.
929        4-7 are the reverse of 0-3.  */
930     c = orig & 3;
931     if (c == 3) {
932         c = 7;
933     }
934     f = (orig & 4) / 4;
935 
936     return do_log_cond(ctx, c * 2 + f, d, res);
937 }
938 
939 /* Similar, but for unit zero conditions.  */
940 static DisasCond do_unit_zero_cond(unsigned cf, bool d, TCGv_i64 res)
941 {
942     TCGv_i64 tmp;
943     uint64_t d_repl = d ? 0x0000000100000001ull : 1;
944     uint64_t ones = 0, sgns = 0;
945 
946     switch (cf >> 1) {
947     case 1: /* SBW / NBW */
948         if (d) {
949             ones = d_repl;
950             sgns = d_repl << 31;
951         }
952         break;
953     case 2: /* SBZ / NBZ */
954         ones = d_repl * 0x01010101u;
955         sgns = ones << 7;
956         break;
957     case 3: /* SHZ / NHZ */
958         ones = d_repl * 0x00010001u;
959         sgns = ones << 15;
960         break;
961     }
962     if (ones == 0) {
963         /* Undefined, or 0/1 (never/always). */
964         return cf & 1 ? cond_make_t() : cond_make_f();
965     }
966 
967     /*
968      * See hasless(v,1) from
969      * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
970      */
971     tmp = tcg_temp_new_i64();
972     tcg_gen_subi_i64(tmp, res, ones);
973     tcg_gen_andc_i64(tmp, tmp, res);
974     tcg_gen_andi_i64(tmp, tmp, sgns);
975 
976     return cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, tmp);
977 }
978 
979 static TCGv_i64 get_carry(DisasContext *ctx, bool d,
980                           TCGv_i64 cb, TCGv_i64 cb_msb)
981 {
982     if (!d) {
983         TCGv_i64 t = tcg_temp_new_i64();
984         tcg_gen_extract_i64(t, cb, 32, 1);
985         return t;
986     }
987     return cb_msb;
988 }
989 
990 static TCGv_i64 get_psw_carry(DisasContext *ctx, bool d)
991 {
992     return get_carry(ctx, d, cpu_psw_cb, cpu_psw_cb_msb);
993 }
994 
995 /* Compute signed overflow for addition.  */
996 static TCGv_i64 do_add_sv(DisasContext *ctx, TCGv_i64 res,
997                           TCGv_i64 in1, TCGv_i64 in2,
998                           TCGv_i64 orig_in1, int shift, bool d)
999 {
1000     TCGv_i64 sv = tcg_temp_new_i64();
1001     TCGv_i64 tmp = tcg_temp_new_i64();
1002 
1003     tcg_gen_xor_i64(sv, res, in1);
1004     tcg_gen_xor_i64(tmp, in1, in2);
1005     tcg_gen_andc_i64(sv, sv, tmp);
1006 
1007     switch (shift) {
1008     case 0:
1009         break;
1010     case 1:
1011         /* Shift left by one and compare the sign. */
1012         tcg_gen_add_i64(tmp, orig_in1, orig_in1);
1013         tcg_gen_xor_i64(tmp, tmp, orig_in1);
1014         /* Incorporate into the overflow. */
1015         tcg_gen_or_i64(sv, sv, tmp);
1016         break;
1017     default:
1018         {
1019             int sign_bit = d ? 63 : 31;
1020 
1021             /* Compare the sign against all lower bits. */
1022             tcg_gen_sextract_i64(tmp, orig_in1, sign_bit, 1);
1023             tcg_gen_xor_i64(tmp, tmp, orig_in1);
1024             /*
1025              * If one of the bits shifting into or through the sign
1026              * differs, then we have overflow.
1027              */
1028             tcg_gen_extract_i64(tmp, tmp, sign_bit - shift, shift);
1029             tcg_gen_movcond_i64(TCG_COND_NE, sv, tmp, ctx->zero,
1030                                 tcg_constant_i64(-1), sv);
1031         }
1032     }
1033     return sv;
1034 }
1035 
1036 /* Compute unsigned overflow for addition.  */
1037 static TCGv_i64 do_add_uv(DisasContext *ctx, TCGv_i64 cb, TCGv_i64 cb_msb,
1038                           TCGv_i64 in1, int shift, bool d)
1039 {
1040     if (shift == 0) {
1041         return get_carry(ctx, d, cb, cb_msb);
1042     } else {
1043         TCGv_i64 tmp = tcg_temp_new_i64();
1044         tcg_gen_extract_i64(tmp, in1, (d ? 63 : 31) - shift, shift);
1045         tcg_gen_or_i64(tmp, tmp, get_carry(ctx, d, cb, cb_msb));
1046         return tmp;
1047     }
1048 }
1049 
1050 /* Compute signed overflow for subtraction.  */
1051 static TCGv_i64 do_sub_sv(DisasContext *ctx, TCGv_i64 res,
1052                           TCGv_i64 in1, TCGv_i64 in2)
1053 {
1054     TCGv_i64 sv = tcg_temp_new_i64();
1055     TCGv_i64 tmp = tcg_temp_new_i64();
1056 
1057     tcg_gen_xor_i64(sv, res, in1);
1058     tcg_gen_xor_i64(tmp, in1, in2);
1059     tcg_gen_and_i64(sv, sv, tmp);
1060 
1061     return sv;
1062 }
1063 
1064 static void do_add(DisasContext *ctx, unsigned rt, TCGv_i64 orig_in1,
1065                    TCGv_i64 in2, unsigned shift, bool is_l,
1066                    bool is_tsv, bool is_tc, bool is_c, unsigned cf, bool d)
1067 {
1068     TCGv_i64 dest, cb, cb_msb, in1, uv, sv, tmp;
1069     unsigned c = cf >> 1;
1070     DisasCond cond;
1071 
1072     dest = tcg_temp_new_i64();
1073     cb = NULL;
1074     cb_msb = NULL;
1075 
1076     in1 = orig_in1;
1077     if (shift) {
1078         tmp = tcg_temp_new_i64();
1079         tcg_gen_shli_i64(tmp, in1, shift);
1080         in1 = tmp;
1081     }
1082 
1083     if (!is_l || cond_need_cb(c)) {
1084         cb_msb = tcg_temp_new_i64();
1085         cb = tcg_temp_new_i64();
1086 
1087         tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero, in2, ctx->zero);
1088         if (is_c) {
1089             tcg_gen_add2_i64(dest, cb_msb, dest, cb_msb,
1090                              get_psw_carry(ctx, d), ctx->zero);
1091         }
1092         tcg_gen_xor_i64(cb, in1, in2);
1093         tcg_gen_xor_i64(cb, cb, dest);
1094     } else {
1095         tcg_gen_add_i64(dest, in1, in2);
1096         if (is_c) {
1097             tcg_gen_add_i64(dest, dest, get_psw_carry(ctx, d));
1098         }
1099     }
1100 
1101     /* Compute signed overflow if required.  */
1102     sv = NULL;
1103     if (is_tsv || cond_need_sv(c)) {
1104         sv = do_add_sv(ctx, dest, in1, in2, orig_in1, shift, d);
1105         if (is_tsv) {
1106             if (!d) {
1107                 tcg_gen_ext32s_i64(sv, sv);
1108             }
1109             gen_helper_tsv(tcg_env, sv);
1110         }
1111     }
1112 
1113     /* Compute unsigned overflow if required.  */
1114     uv = NULL;
1115     if (cond_need_cb(c)) {
1116         uv = do_add_uv(ctx, cb, cb_msb, orig_in1, shift, d);
1117     }
1118 
1119     /* Emit any conditional trap before any writeback.  */
1120     cond = do_cond(ctx, cf, d, dest, uv, sv);
1121     if (is_tc) {
1122         tmp = tcg_temp_new_i64();
1123         tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
1124         gen_helper_tcond(tcg_env, tmp);
1125     }
1126 
1127     /* Write back the result.  */
1128     if (!is_l) {
1129         save_or_nullify(ctx, cpu_psw_cb, cb);
1130         save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1131     }
1132     save_gpr(ctx, rt, dest);
1133 
1134     /* Install the new nullification.  */
1135     cond_free(&ctx->null_cond);
1136     ctx->null_cond = cond;
1137 }
1138 
1139 static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_d_sh *a,
1140                        bool is_l, bool is_tsv, bool is_tc, bool is_c)
1141 {
1142     TCGv_i64 tcg_r1, tcg_r2;
1143 
1144     if (a->cf) {
1145         nullify_over(ctx);
1146     }
1147     tcg_r1 = load_gpr(ctx, a->r1);
1148     tcg_r2 = load_gpr(ctx, a->r2);
1149     do_add(ctx, a->t, tcg_r1, tcg_r2, a->sh, is_l,
1150            is_tsv, is_tc, is_c, a->cf, a->d);
1151     return nullify_end(ctx);
1152 }
1153 
1154 static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
1155                        bool is_tsv, bool is_tc)
1156 {
1157     TCGv_i64 tcg_im, tcg_r2;
1158 
1159     if (a->cf) {
1160         nullify_over(ctx);
1161     }
1162     tcg_im = tcg_constant_i64(a->i);
1163     tcg_r2 = load_gpr(ctx, a->r);
1164     /* All ADDI conditions are 32-bit. */
1165     do_add(ctx, a->t, tcg_im, tcg_r2, 0, 0, is_tsv, is_tc, 0, a->cf, false);
1166     return nullify_end(ctx);
1167 }
1168 
1169 static void do_sub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1170                    TCGv_i64 in2, bool is_tsv, bool is_b,
1171                    bool is_tc, unsigned cf, bool d)
1172 {
1173     TCGv_i64 dest, sv, cb, cb_msb, tmp;
1174     unsigned c = cf >> 1;
1175     DisasCond cond;
1176 
1177     dest = tcg_temp_new_i64();
1178     cb = tcg_temp_new_i64();
1179     cb_msb = tcg_temp_new_i64();
1180 
1181     if (is_b) {
1182         /* DEST,C = IN1 + ~IN2 + C.  */
1183         tcg_gen_not_i64(cb, in2);
1184         tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero,
1185                          get_psw_carry(ctx, d), ctx->zero);
1186         tcg_gen_add2_i64(dest, cb_msb, dest, cb_msb, cb, ctx->zero);
1187         tcg_gen_xor_i64(cb, cb, in1);
1188         tcg_gen_xor_i64(cb, cb, dest);
1189     } else {
1190         /*
1191          * DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
1192          * operations by seeding the high word with 1 and subtracting.
1193          */
1194         TCGv_i64 one = tcg_constant_i64(1);
1195         tcg_gen_sub2_i64(dest, cb_msb, in1, one, in2, ctx->zero);
1196         tcg_gen_eqv_i64(cb, in1, in2);
1197         tcg_gen_xor_i64(cb, cb, dest);
1198     }
1199 
1200     /* Compute signed overflow if required.  */
1201     sv = NULL;
1202     if (is_tsv || cond_need_sv(c)) {
1203         sv = do_sub_sv(ctx, dest, in1, in2);
1204         if (is_tsv) {
1205             if (!d) {
1206                 tcg_gen_ext32s_i64(sv, sv);
1207             }
1208             gen_helper_tsv(tcg_env, sv);
1209         }
1210     }
1211 
1212     /* Compute the condition.  We cannot use the special case for borrow.  */
1213     if (!is_b) {
1214         cond = do_sub_cond(ctx, cf, d, dest, in1, in2, sv);
1215     } else {
1216         cond = do_cond(ctx, cf, d, dest, get_carry(ctx, d, cb, cb_msb), sv);
1217     }
1218 
1219     /* Emit any conditional trap before any writeback.  */
1220     if (is_tc) {
1221         tmp = tcg_temp_new_i64();
1222         tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
1223         gen_helper_tcond(tcg_env, tmp);
1224     }
1225 
1226     /* Write back the result.  */
1227     save_or_nullify(ctx, cpu_psw_cb, cb);
1228     save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1229     save_gpr(ctx, rt, dest);
1230 
1231     /* Install the new nullification.  */
1232     cond_free(&ctx->null_cond);
1233     ctx->null_cond = cond;
1234 }
1235 
1236 static bool do_sub_reg(DisasContext *ctx, arg_rrr_cf_d *a,
1237                        bool is_tsv, bool is_b, bool is_tc)
1238 {
1239     TCGv_i64 tcg_r1, tcg_r2;
1240 
1241     if (a->cf) {
1242         nullify_over(ctx);
1243     }
1244     tcg_r1 = load_gpr(ctx, a->r1);
1245     tcg_r2 = load_gpr(ctx, a->r2);
1246     do_sub(ctx, a->t, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, a->cf, a->d);
1247     return nullify_end(ctx);
1248 }
1249 
1250 static bool do_sub_imm(DisasContext *ctx, arg_rri_cf *a, bool is_tsv)
1251 {
1252     TCGv_i64 tcg_im, tcg_r2;
1253 
1254     if (a->cf) {
1255         nullify_over(ctx);
1256     }
1257     tcg_im = tcg_constant_i64(a->i);
1258     tcg_r2 = load_gpr(ctx, a->r);
1259     /* All SUBI conditions are 32-bit. */
1260     do_sub(ctx, a->t, tcg_im, tcg_r2, is_tsv, 0, 0, a->cf, false);
1261     return nullify_end(ctx);
1262 }
1263 
1264 static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1265                       TCGv_i64 in2, unsigned cf, bool d)
1266 {
1267     TCGv_i64 dest, sv;
1268     DisasCond cond;
1269 
1270     dest = tcg_temp_new_i64();
1271     tcg_gen_sub_i64(dest, in1, in2);
1272 
1273     /* Compute signed overflow if required.  */
1274     sv = NULL;
1275     if (cond_need_sv(cf >> 1)) {
1276         sv = do_sub_sv(ctx, dest, in1, in2);
1277     }
1278 
1279     /* Form the condition for the compare.  */
1280     cond = do_sub_cond(ctx, cf, d, dest, in1, in2, sv);
1281 
1282     /* Clear.  */
1283     tcg_gen_movi_i64(dest, 0);
1284     save_gpr(ctx, rt, dest);
1285 
1286     /* Install the new nullification.  */
1287     cond_free(&ctx->null_cond);
1288     ctx->null_cond = cond;
1289 }
1290 
1291 static void do_log(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1292                    TCGv_i64 in2, unsigned cf, bool d,
1293                    void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
1294 {
1295     TCGv_i64 dest = dest_gpr(ctx, rt);
1296 
1297     /* Perform the operation, and writeback.  */
1298     fn(dest, in1, in2);
1299     save_gpr(ctx, rt, dest);
1300 
1301     /* Install the new nullification.  */
1302     cond_free(&ctx->null_cond);
1303     if (cf) {
1304         ctx->null_cond = do_log_cond(ctx, cf, d, dest);
1305     }
1306 }
1307 
1308 static bool do_log_reg(DisasContext *ctx, arg_rrr_cf_d *a,
1309                        void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
1310 {
1311     TCGv_i64 tcg_r1, tcg_r2;
1312 
1313     if (a->cf) {
1314         nullify_over(ctx);
1315     }
1316     tcg_r1 = load_gpr(ctx, a->r1);
1317     tcg_r2 = load_gpr(ctx, a->r2);
1318     do_log(ctx, a->t, tcg_r1, tcg_r2, a->cf, a->d, fn);
1319     return nullify_end(ctx);
1320 }
1321 
1322 static void do_unit_addsub(DisasContext *ctx, unsigned rt, TCGv_i64 in1,
1323                            TCGv_i64 in2, unsigned cf, bool d,
1324                            bool is_tc, bool is_add)
1325 {
1326     TCGv_i64 dest = tcg_temp_new_i64();
1327     uint64_t test_cb = 0;
1328     DisasCond cond;
1329 
1330     /* Select which carry-out bits to test. */
1331     switch (cf >> 1) {
1332     case 4: /* NDC / SDC -- 4-bit carries */
1333         test_cb = dup_const(MO_8, 0x88);
1334         break;
1335     case 5: /* NWC / SWC -- 32-bit carries */
1336         if (d) {
1337             test_cb = dup_const(MO_32, INT32_MIN);
1338         } else {
1339             cf &= 1; /* undefined -- map to never/always */
1340         }
1341         break;
1342     case 6: /* NBC / SBC -- 8-bit carries */
1343         test_cb = dup_const(MO_8, INT8_MIN);
1344         break;
1345     case 7: /* NHC / SHC -- 16-bit carries */
1346         test_cb = dup_const(MO_16, INT16_MIN);
1347         break;
1348     }
1349     if (!d) {
1350         test_cb = (uint32_t)test_cb;
1351     }
1352 
1353     if (!test_cb) {
1354         /* No need to compute carries if we don't need to test them. */
1355         if (is_add) {
1356             tcg_gen_add_i64(dest, in1, in2);
1357         } else {
1358             tcg_gen_sub_i64(dest, in1, in2);
1359         }
1360         cond = do_unit_zero_cond(cf, d, dest);
1361     } else {
1362         TCGv_i64 cb = tcg_temp_new_i64();
1363 
1364         if (d) {
1365             TCGv_i64 cb_msb = tcg_temp_new_i64();
1366             if (is_add) {
1367                 tcg_gen_add2_i64(dest, cb_msb, in1, ctx->zero, in2, ctx->zero);
1368                 tcg_gen_xor_i64(cb, in1, in2);
1369             } else {
1370                 /* See do_sub, !is_b. */
1371                 TCGv_i64 one = tcg_constant_i64(1);
1372                 tcg_gen_sub2_i64(dest, cb_msb, in1, one, in2, ctx->zero);
1373                 tcg_gen_eqv_i64(cb, in1, in2);
1374             }
1375             tcg_gen_xor_i64(cb, cb, dest);
1376             tcg_gen_extract2_i64(cb, cb, cb_msb, 1);
1377         } else {
1378             if (is_add) {
1379                 tcg_gen_add_i64(dest, in1, in2);
1380                 tcg_gen_xor_i64(cb, in1, in2);
1381             } else {
1382                 tcg_gen_sub_i64(dest, in1, in2);
1383                 tcg_gen_eqv_i64(cb, in1, in2);
1384             }
1385             tcg_gen_xor_i64(cb, cb, dest);
1386             tcg_gen_shri_i64(cb, cb, 1);
1387         }
1388 
1389         tcg_gen_andi_i64(cb, cb, test_cb);
1390         cond = cond_make_0_tmp(cf & 1 ? TCG_COND_EQ : TCG_COND_NE, cb);
1391     }
1392 
1393     if (is_tc) {
1394         TCGv_i64 tmp = tcg_temp_new_i64();
1395         tcg_gen_setcond_i64(cond.c, tmp, cond.a0, cond.a1);
1396         gen_helper_tcond(tcg_env, tmp);
1397     }
1398     save_gpr(ctx, rt, dest);
1399 
1400     cond_free(&ctx->null_cond);
1401     ctx->null_cond = cond;
1402 }
1403 
1404 #ifndef CONFIG_USER_ONLY
1405 /* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
1406    from the top 2 bits of the base register.  There are a few system
1407    instructions that have a 3-bit space specifier, for which SR0 is
1408    not special.  To handle this, pass ~SP.  */
1409 static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_i64 base)
1410 {
1411     TCGv_ptr ptr;
1412     TCGv_i64 tmp;
1413     TCGv_i64 spc;
1414 
1415     if (sp != 0) {
1416         if (sp < 0) {
1417             sp = ~sp;
1418         }
1419         spc = tcg_temp_new_i64();
1420         load_spr(ctx, spc, sp);
1421         return spc;
1422     }
1423     if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1424         return cpu_srH;
1425     }
1426 
1427     ptr = tcg_temp_new_ptr();
1428     tmp = tcg_temp_new_i64();
1429     spc = tcg_temp_new_i64();
1430 
1431     /* Extract top 2 bits of the address, shift left 3 for uint64_t index. */
1432     tcg_gen_shri_i64(tmp, base, (ctx->tb_flags & PSW_W ? 64 : 32) - 5);
1433     tcg_gen_andi_i64(tmp, tmp, 030);
1434     tcg_gen_trunc_i64_ptr(ptr, tmp);
1435 
1436     tcg_gen_add_ptr(ptr, ptr, tcg_env);
1437     tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
1438 
1439     return spc;
1440 }
1441 #endif
1442 
1443 static void form_gva(DisasContext *ctx, TCGv_i64 *pgva, TCGv_i64 *pofs,
1444                      unsigned rb, unsigned rx, int scale, int64_t disp,
1445                      unsigned sp, int modify, bool is_phys)
1446 {
1447     TCGv_i64 base = load_gpr(ctx, rb);
1448     TCGv_i64 ofs;
1449     TCGv_i64 addr;
1450 
1451     set_insn_breg(ctx, rb);
1452 
1453     /* Note that RX is mutually exclusive with DISP.  */
1454     if (rx) {
1455         ofs = tcg_temp_new_i64();
1456         tcg_gen_shli_i64(ofs, cpu_gr[rx], scale);
1457         tcg_gen_add_i64(ofs, ofs, base);
1458     } else if (disp || modify) {
1459         ofs = tcg_temp_new_i64();
1460         tcg_gen_addi_i64(ofs, base, disp);
1461     } else {
1462         ofs = base;
1463     }
1464 
1465     *pofs = ofs;
1466     *pgva = addr = tcg_temp_new_i64();
1467     tcg_gen_andi_i64(addr, modify <= 0 ? ofs : base,
1468                      gva_offset_mask(ctx->tb_flags));
1469 #ifndef CONFIG_USER_ONLY
1470     if (!is_phys) {
1471         tcg_gen_or_i64(addr, addr, space_select(ctx, sp, base));
1472     }
1473 #endif
1474 }
1475 
1476 /* Emit a memory load.  The modify parameter should be
1477  * < 0 for pre-modify,
1478  * > 0 for post-modify,
1479  * = 0 for no base register update.
1480  */
1481 static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1482                        unsigned rx, int scale, int64_t disp,
1483                        unsigned sp, int modify, MemOp mop)
1484 {
1485     TCGv_i64 ofs;
1486     TCGv_i64 addr;
1487 
1488     /* Caller uses nullify_over/nullify_end.  */
1489     assert(ctx->null_cond.c == TCG_COND_NEVER);
1490 
1491     form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1492              MMU_DISABLED(ctx));
1493     tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1494     if (modify) {
1495         save_gpr(ctx, rb, ofs);
1496     }
1497 }
1498 
1499 static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1500                        unsigned rx, int scale, int64_t disp,
1501                        unsigned sp, int modify, MemOp mop)
1502 {
1503     TCGv_i64 ofs;
1504     TCGv_i64 addr;
1505 
1506     /* Caller uses nullify_over/nullify_end.  */
1507     assert(ctx->null_cond.c == TCG_COND_NEVER);
1508 
1509     form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1510              MMU_DISABLED(ctx));
1511     tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1512     if (modify) {
1513         save_gpr(ctx, rb, ofs);
1514     }
1515 }
1516 
1517 static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1518                         unsigned rx, int scale, int64_t disp,
1519                         unsigned sp, int modify, MemOp mop)
1520 {
1521     TCGv_i64 ofs;
1522     TCGv_i64 addr;
1523 
1524     /* Caller uses nullify_over/nullify_end.  */
1525     assert(ctx->null_cond.c == TCG_COND_NEVER);
1526 
1527     form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1528              MMU_DISABLED(ctx));
1529     tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1530     if (modify) {
1531         save_gpr(ctx, rb, ofs);
1532     }
1533 }
1534 
1535 static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1536                         unsigned rx, int scale, int64_t disp,
1537                         unsigned sp, int modify, MemOp mop)
1538 {
1539     TCGv_i64 ofs;
1540     TCGv_i64 addr;
1541 
1542     /* Caller uses nullify_over/nullify_end.  */
1543     assert(ctx->null_cond.c == TCG_COND_NEVER);
1544 
1545     form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1546              MMU_DISABLED(ctx));
1547     tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
1548     if (modify) {
1549         save_gpr(ctx, rb, ofs);
1550     }
1551 }
1552 
1553 static bool do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1554                     unsigned rx, int scale, int64_t disp,
1555                     unsigned sp, int modify, MemOp mop)
1556 {
1557     TCGv_i64 dest;
1558 
1559     nullify_over(ctx);
1560 
1561     if (modify == 0) {
1562         /* No base register update.  */
1563         dest = dest_gpr(ctx, rt);
1564     } else {
1565         /* Make sure if RT == RB, we see the result of the load.  */
1566         dest = tcg_temp_new_i64();
1567     }
1568     do_load_64(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
1569     save_gpr(ctx, rt, dest);
1570 
1571     return nullify_end(ctx);
1572 }
1573 
1574 static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1575                       unsigned rx, int scale, int64_t disp,
1576                       unsigned sp, int modify)
1577 {
1578     TCGv_i32 tmp;
1579 
1580     nullify_over(ctx);
1581 
1582     tmp = tcg_temp_new_i32();
1583     do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1584     save_frw_i32(rt, tmp);
1585 
1586     if (rt == 0) {
1587         gen_helper_loaded_fr0(tcg_env);
1588     }
1589 
1590     return nullify_end(ctx);
1591 }
1592 
1593 static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
1594 {
1595     return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1596                      a->disp, a->sp, a->m);
1597 }
1598 
1599 static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1600                       unsigned rx, int scale, int64_t disp,
1601                       unsigned sp, int modify)
1602 {
1603     TCGv_i64 tmp;
1604 
1605     nullify_over(ctx);
1606 
1607     tmp = tcg_temp_new_i64();
1608     do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
1609     save_frd(rt, tmp);
1610 
1611     if (rt == 0) {
1612         gen_helper_loaded_fr0(tcg_env);
1613     }
1614 
1615     return nullify_end(ctx);
1616 }
1617 
1618 static 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 
1624 static bool do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1625                      int64_t disp, unsigned sp,
1626                      int modify, MemOp mop)
1627 {
1628     nullify_over(ctx);
1629     do_store_64(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
1630     return nullify_end(ctx);
1631 }
1632 
1633 static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1634                        unsigned rx, int scale, int64_t 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 
1644     return nullify_end(ctx);
1645 }
1646 
1647 static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
1648 {
1649     return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1650                       a->disp, a->sp, a->m);
1651 }
1652 
1653 static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1654                        unsigned rx, int scale, int64_t disp,
1655                        unsigned sp, int modify)
1656 {
1657     TCGv_i64 tmp;
1658 
1659     nullify_over(ctx);
1660 
1661     tmp = load_frd(rt);
1662     do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ);
1663 
1664     return nullify_end(ctx);
1665 }
1666 
1667 static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
1668 {
1669     return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1670                       a->disp, a->sp, a->m);
1671 }
1672 
1673 static bool do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1674                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1675 {
1676     TCGv_i32 tmp;
1677 
1678     nullify_over(ctx);
1679     tmp = load_frw0_i32(ra);
1680 
1681     func(tmp, tcg_env, tmp);
1682 
1683     save_frw_i32(rt, tmp);
1684     return nullify_end(ctx);
1685 }
1686 
1687 static bool do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1688                        void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1689 {
1690     TCGv_i32 dst;
1691     TCGv_i64 src;
1692 
1693     nullify_over(ctx);
1694     src = load_frd(ra);
1695     dst = tcg_temp_new_i32();
1696 
1697     func(dst, tcg_env, src);
1698 
1699     save_frw_i32(rt, dst);
1700     return nullify_end(ctx);
1701 }
1702 
1703 static bool do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1704                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1705 {
1706     TCGv_i64 tmp;
1707 
1708     nullify_over(ctx);
1709     tmp = load_frd0(ra);
1710 
1711     func(tmp, tcg_env, tmp);
1712 
1713     save_frd(rt, tmp);
1714     return nullify_end(ctx);
1715 }
1716 
1717 static bool do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1718                        void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1719 {
1720     TCGv_i32 src;
1721     TCGv_i64 dst;
1722 
1723     nullify_over(ctx);
1724     src = load_frw0_i32(ra);
1725     dst = tcg_temp_new_i64();
1726 
1727     func(dst, tcg_env, src);
1728 
1729     save_frd(rt, dst);
1730     return nullify_end(ctx);
1731 }
1732 
1733 static bool do_fop_weww(DisasContext *ctx, unsigned rt,
1734                         unsigned ra, unsigned rb,
1735                         void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
1736 {
1737     TCGv_i32 a, b;
1738 
1739     nullify_over(ctx);
1740     a = load_frw0_i32(ra);
1741     b = load_frw0_i32(rb);
1742 
1743     func(a, tcg_env, a, b);
1744 
1745     save_frw_i32(rt, a);
1746     return nullify_end(ctx);
1747 }
1748 
1749 static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
1750                         unsigned ra, unsigned rb,
1751                         void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1752 {
1753     TCGv_i64 a, b;
1754 
1755     nullify_over(ctx);
1756     a = load_frd0(ra);
1757     b = load_frd0(rb);
1758 
1759     func(a, tcg_env, a, b);
1760 
1761     save_frd(rt, a);
1762     return nullify_end(ctx);
1763 }
1764 
1765 /* Emit an unconditional branch to a direct target, which may or may not
1766    have already had nullification handled.  */
1767 static bool do_dbranch(DisasContext *ctx, uint64_t dest,
1768                        unsigned link, bool is_n)
1769 {
1770     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1771         if (link != 0) {
1772             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1773         }
1774         ctx->iaoq_n = dest;
1775         if (is_n) {
1776             ctx->null_cond.c = TCG_COND_ALWAYS;
1777         }
1778     } else {
1779         nullify_over(ctx);
1780 
1781         if (link != 0) {
1782             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1783         }
1784 
1785         if (is_n && use_nullify_skip(ctx)) {
1786             nullify_set(ctx, 0);
1787             gen_goto_tb(ctx, 0, dest, dest + 4);
1788         } else {
1789             nullify_set(ctx, is_n);
1790             gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
1791         }
1792 
1793         nullify_end(ctx);
1794 
1795         nullify_set(ctx, 0);
1796         gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1797         ctx->base.is_jmp = DISAS_NORETURN;
1798     }
1799     return true;
1800 }
1801 
1802 /* Emit a conditional branch to a direct target.  If the branch itself
1803    is nullified, we should have already used nullify_over.  */
1804 static bool do_cbranch(DisasContext *ctx, int64_t disp, bool is_n,
1805                        DisasCond *cond)
1806 {
1807     uint64_t dest = iaoq_dest(ctx, disp);
1808     TCGLabel *taken = NULL;
1809     TCGCond c = cond->c;
1810     bool n;
1811 
1812     assert(ctx->null_cond.c == TCG_COND_NEVER);
1813 
1814     /* Handle TRUE and NEVER as direct branches.  */
1815     if (c == TCG_COND_ALWAYS) {
1816         return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
1817     }
1818     if (c == TCG_COND_NEVER) {
1819         return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
1820     }
1821 
1822     taken = gen_new_label();
1823     tcg_gen_brcond_i64(c, cond->a0, cond->a1, taken);
1824     cond_free(cond);
1825 
1826     /* Not taken: Condition not satisfied; nullify on backward branches. */
1827     n = is_n && disp < 0;
1828     if (n && use_nullify_skip(ctx)) {
1829         nullify_set(ctx, 0);
1830         gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
1831     } else {
1832         if (!n && ctx->null_lab) {
1833             gen_set_label(ctx->null_lab);
1834             ctx->null_lab = NULL;
1835         }
1836         nullify_set(ctx, n);
1837         if (ctx->iaoq_n == -1) {
1838             /* The temporary iaoq_n_var died at the branch above.
1839                Regenerate it here instead of saving it.  */
1840             tcg_gen_addi_i64(ctx->iaoq_n_var, cpu_iaoq_b, 4);
1841         }
1842         gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
1843     }
1844 
1845     gen_set_label(taken);
1846 
1847     /* Taken: Condition satisfied; nullify on forward branches.  */
1848     n = is_n && disp >= 0;
1849     if (n && use_nullify_skip(ctx)) {
1850         nullify_set(ctx, 0);
1851         gen_goto_tb(ctx, 1, dest, dest + 4);
1852     } else {
1853         nullify_set(ctx, n);
1854         gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
1855     }
1856 
1857     /* Not taken: the branch itself was nullified.  */
1858     if (ctx->null_lab) {
1859         gen_set_label(ctx->null_lab);
1860         ctx->null_lab = NULL;
1861         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
1862     } else {
1863         ctx->base.is_jmp = DISAS_NORETURN;
1864     }
1865     return true;
1866 }
1867 
1868 /* Emit an unconditional branch to an indirect target.  This handles
1869    nullification of the branch itself.  */
1870 static bool do_ibranch(DisasContext *ctx, TCGv_i64 dest,
1871                        unsigned link, bool is_n)
1872 {
1873     TCGv_i64 a0, a1, next, tmp;
1874     TCGCond c;
1875 
1876     assert(ctx->null_lab == NULL);
1877 
1878     if (ctx->null_cond.c == TCG_COND_NEVER) {
1879         if (link != 0) {
1880             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1881         }
1882         next = tcg_temp_new_i64();
1883         tcg_gen_mov_i64(next, dest);
1884         if (is_n) {
1885             if (use_nullify_skip(ctx)) {
1886                 copy_iaoq_entry(ctx, cpu_iaoq_f, -1, next);
1887                 tcg_gen_addi_i64(next, next, 4);
1888                 copy_iaoq_entry(ctx, cpu_iaoq_b, -1, next);
1889                 nullify_set(ctx, 0);
1890                 ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
1891                 return true;
1892             }
1893             ctx->null_cond.c = TCG_COND_ALWAYS;
1894         }
1895         ctx->iaoq_n = -1;
1896         ctx->iaoq_n_var = next;
1897     } else if (is_n && use_nullify_skip(ctx)) {
1898         /* The (conditional) branch, B, nullifies the next insn, N,
1899            and we're allowed to skip execution N (no single-step or
1900            tracepoint in effect).  Since the goto_ptr that we must use
1901            for the indirect branch consumes no special resources, we
1902            can (conditionally) skip B and continue execution.  */
1903         /* The use_nullify_skip test implies we have a known control path.  */
1904         tcg_debug_assert(ctx->iaoq_b != -1);
1905         tcg_debug_assert(ctx->iaoq_n != -1);
1906 
1907         /* We do have to handle the non-local temporary, DEST, before
1908            branching.  Since IOAQ_F is not really live at this point, we
1909            can simply store DEST optimistically.  Similarly with IAOQ_B.  */
1910         copy_iaoq_entry(ctx, cpu_iaoq_f, -1, dest);
1911         next = tcg_temp_new_i64();
1912         tcg_gen_addi_i64(next, dest, 4);
1913         copy_iaoq_entry(ctx, cpu_iaoq_b, -1, next);
1914 
1915         nullify_over(ctx);
1916         if (link != 0) {
1917             copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1918         }
1919         tcg_gen_lookup_and_goto_ptr();
1920         return nullify_end(ctx);
1921     } else {
1922         c = ctx->null_cond.c;
1923         a0 = ctx->null_cond.a0;
1924         a1 = ctx->null_cond.a1;
1925 
1926         tmp = tcg_temp_new_i64();
1927         next = tcg_temp_new_i64();
1928 
1929         copy_iaoq_entry(ctx, tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1930         tcg_gen_movcond_i64(c, next, a0, a1, tmp, dest);
1931         ctx->iaoq_n = -1;
1932         ctx->iaoq_n_var = next;
1933 
1934         if (link != 0) {
1935             tcg_gen_movcond_i64(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1936         }
1937 
1938         if (is_n) {
1939             /* The branch nullifies the next insn, which means the state of N
1940                after the branch is the inverse of the state of N that applied
1941                to the branch.  */
1942             tcg_gen_setcond_i64(tcg_invert_cond(c), cpu_psw_n, a0, a1);
1943             cond_free(&ctx->null_cond);
1944             ctx->null_cond = cond_make_n();
1945             ctx->psw_n_nonzero = true;
1946         } else {
1947             cond_free(&ctx->null_cond);
1948         }
1949     }
1950     return true;
1951 }
1952 
1953 /* Implement
1954  *    if (IAOQ_Front{30..31} < GR[b]{30..31})
1955  *      IAOQ_Next{30..31} ← GR[b]{30..31};
1956  *    else
1957  *      IAOQ_Next{30..31} ← IAOQ_Front{30..31};
1958  * which keeps the privilege level from being increased.
1959  */
1960 static TCGv_i64 do_ibranch_priv(DisasContext *ctx, TCGv_i64 offset)
1961 {
1962     TCGv_i64 dest;
1963     switch (ctx->privilege) {
1964     case 0:
1965         /* Privilege 0 is maximum and is allowed to decrease.  */
1966         return offset;
1967     case 3:
1968         /* Privilege 3 is minimum and is never allowed to increase.  */
1969         dest = tcg_temp_new_i64();
1970         tcg_gen_ori_i64(dest, offset, 3);
1971         break;
1972     default:
1973         dest = tcg_temp_new_i64();
1974         tcg_gen_andi_i64(dest, offset, -4);
1975         tcg_gen_ori_i64(dest, dest, ctx->privilege);
1976         tcg_gen_movcond_i64(TCG_COND_GTU, dest, dest, offset, dest, offset);
1977         break;
1978     }
1979     return dest;
1980 }
1981 
1982 #ifdef CONFIG_USER_ONLY
1983 /* On Linux, page zero is normally marked execute only + gateway.
1984    Therefore normal read or write is supposed to fail, but specific
1985    offsets have kernel code mapped to raise permissions to implement
1986    system calls.  Handling this via an explicit check here, rather
1987    in than the "be disp(sr2,r0)" instruction that probably sent us
1988    here, is the easiest way to handle the branch delay slot on the
1989    aforementioned BE.  */
1990 static void do_page_zero(DisasContext *ctx)
1991 {
1992     TCGv_i64 tmp;
1993 
1994     /* If by some means we get here with PSW[N]=1, that implies that
1995        the B,GATE instruction would be skipped, and we'd fault on the
1996        next insn within the privileged page.  */
1997     switch (ctx->null_cond.c) {
1998     case TCG_COND_NEVER:
1999         break;
2000     case TCG_COND_ALWAYS:
2001         tcg_gen_movi_i64(cpu_psw_n, 0);
2002         goto do_sigill;
2003     default:
2004         /* Since this is always the first (and only) insn within the
2005            TB, we should know the state of PSW[N] from TB->FLAGS.  */
2006         g_assert_not_reached();
2007     }
2008 
2009     /* Check that we didn't arrive here via some means that allowed
2010        non-sequential instruction execution.  Normally the PSW[B] bit
2011        detects this by disallowing the B,GATE instruction to execute
2012        under such conditions.  */
2013     if (ctx->iaoq_b != ctx->iaoq_f + 4) {
2014         goto do_sigill;
2015     }
2016 
2017     switch (ctx->iaoq_f & -4) {
2018     case 0x00: /* Null pointer call */
2019         gen_excp_1(EXCP_IMP);
2020         ctx->base.is_jmp = DISAS_NORETURN;
2021         break;
2022 
2023     case 0xb0: /* LWS */
2024         gen_excp_1(EXCP_SYSCALL_LWS);
2025         ctx->base.is_jmp = DISAS_NORETURN;
2026         break;
2027 
2028     case 0xe0: /* SET_THREAD_POINTER */
2029         tcg_gen_st_i64(cpu_gr[26], tcg_env, offsetof(CPUHPPAState, cr[27]));
2030         tmp = tcg_temp_new_i64();
2031         tcg_gen_ori_i64(tmp, cpu_gr[31], 3);
2032         copy_iaoq_entry(ctx, cpu_iaoq_f, -1, tmp);
2033         tcg_gen_addi_i64(tmp, tmp, 4);
2034         copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
2035         ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
2036         break;
2037 
2038     case 0x100: /* SYSCALL */
2039         gen_excp_1(EXCP_SYSCALL);
2040         ctx->base.is_jmp = DISAS_NORETURN;
2041         break;
2042 
2043     default:
2044     do_sigill:
2045         gen_excp_1(EXCP_ILL);
2046         ctx->base.is_jmp = DISAS_NORETURN;
2047         break;
2048     }
2049 }
2050 #endif
2051 
2052 static bool trans_nop(DisasContext *ctx, arg_nop *a)
2053 {
2054     cond_free(&ctx->null_cond);
2055     return true;
2056 }
2057 
2058 static bool trans_break(DisasContext *ctx, arg_break *a)
2059 {
2060     return gen_excp_iir(ctx, EXCP_BREAK);
2061 }
2062 
2063 static bool trans_sync(DisasContext *ctx, arg_sync *a)
2064 {
2065     /* No point in nullifying the memory barrier.  */
2066     tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
2067 
2068     cond_free(&ctx->null_cond);
2069     return true;
2070 }
2071 
2072 static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
2073 {
2074     unsigned rt = a->t;
2075     TCGv_i64 tmp = dest_gpr(ctx, rt);
2076     tcg_gen_movi_i64(tmp, ctx->iaoq_f & ~3ULL);
2077     save_gpr(ctx, rt, tmp);
2078 
2079     cond_free(&ctx->null_cond);
2080     return true;
2081 }
2082 
2083 static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
2084 {
2085     unsigned rt = a->t;
2086     unsigned rs = a->sp;
2087     TCGv_i64 t0 = tcg_temp_new_i64();
2088 
2089     load_spr(ctx, t0, rs);
2090     tcg_gen_shri_i64(t0, t0, 32);
2091 
2092     save_gpr(ctx, rt, t0);
2093 
2094     cond_free(&ctx->null_cond);
2095     return true;
2096 }
2097 
2098 static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
2099 {
2100     unsigned rt = a->t;
2101     unsigned ctl = a->r;
2102     TCGv_i64 tmp;
2103 
2104     switch (ctl) {
2105     case CR_SAR:
2106         if (a->e == 0) {
2107             /* MFSAR without ,W masks low 5 bits.  */
2108             tmp = dest_gpr(ctx, rt);
2109             tcg_gen_andi_i64(tmp, cpu_sar, 31);
2110             save_gpr(ctx, rt, tmp);
2111             goto done;
2112         }
2113         save_gpr(ctx, rt, cpu_sar);
2114         goto done;
2115     case CR_IT: /* Interval Timer */
2116         /* FIXME: Respect PSW_S bit.  */
2117         nullify_over(ctx);
2118         tmp = dest_gpr(ctx, rt);
2119         if (translator_io_start(&ctx->base)) {
2120             ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2121         }
2122         gen_helper_read_interval_timer(tmp);
2123         save_gpr(ctx, rt, tmp);
2124         return nullify_end(ctx);
2125     case 26:
2126     case 27:
2127         break;
2128     default:
2129         /* All other control registers are privileged.  */
2130         CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2131         break;
2132     }
2133 
2134     tmp = tcg_temp_new_i64();
2135     tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2136     save_gpr(ctx, rt, tmp);
2137 
2138  done:
2139     cond_free(&ctx->null_cond);
2140     return true;
2141 }
2142 
2143 static bool trans_mtsp(DisasContext *ctx, arg_mtsp *a)
2144 {
2145     unsigned rr = a->r;
2146     unsigned rs = a->sp;
2147     TCGv_i64 tmp;
2148 
2149     if (rs >= 5) {
2150         CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2151     }
2152     nullify_over(ctx);
2153 
2154     tmp = tcg_temp_new_i64();
2155     tcg_gen_shli_i64(tmp, load_gpr(ctx, rr), 32);
2156 
2157     if (rs >= 4) {
2158         tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUHPPAState, sr[rs]));
2159         ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2160     } else {
2161         tcg_gen_mov_i64(cpu_sr[rs], tmp);
2162     }
2163 
2164     return nullify_end(ctx);
2165 }
2166 
2167 static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
2168 {
2169     unsigned ctl = a->t;
2170     TCGv_i64 reg;
2171     TCGv_i64 tmp;
2172 
2173     if (ctl == CR_SAR) {
2174         reg = load_gpr(ctx, a->r);
2175         tmp = tcg_temp_new_i64();
2176         tcg_gen_andi_i64(tmp, reg, ctx->is_pa20 ? 63 : 31);
2177         save_or_nullify(ctx, cpu_sar, tmp);
2178 
2179         cond_free(&ctx->null_cond);
2180         return true;
2181     }
2182 
2183     /* All other control registers are privileged or read-only.  */
2184     CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2185 
2186 #ifndef CONFIG_USER_ONLY
2187     nullify_over(ctx);
2188 
2189     if (ctx->is_pa20) {
2190         reg = load_gpr(ctx, a->r);
2191     } else {
2192         reg = tcg_temp_new_i64();
2193         tcg_gen_ext32u_i64(reg, load_gpr(ctx, a->r));
2194     }
2195 
2196     switch (ctl) {
2197     case CR_IT:
2198         if (translator_io_start(&ctx->base)) {
2199             ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2200         }
2201         gen_helper_write_interval_timer(tcg_env, reg);
2202         break;
2203     case CR_EIRR:
2204         /* Helper modifies interrupt lines and is therefore IO. */
2205         translator_io_start(&ctx->base);
2206         gen_helper_write_eirr(tcg_env, reg);
2207         /* Exit to re-evaluate interrupts in the main loop. */
2208         ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2209         break;
2210 
2211     case CR_IIASQ:
2212     case CR_IIAOQ:
2213         /* FIXME: Respect PSW_Q bit */
2214         /* The write advances the queue and stores to the back element.  */
2215         tmp = tcg_temp_new_i64();
2216         tcg_gen_ld_i64(tmp, tcg_env,
2217                        offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2218         tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2219         tcg_gen_st_i64(reg, tcg_env,
2220                        offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2221         break;
2222 
2223     case CR_PID1:
2224     case CR_PID2:
2225     case CR_PID3:
2226     case CR_PID4:
2227         tcg_gen_st_i64(reg, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2228 #ifndef CONFIG_USER_ONLY
2229         gen_helper_change_prot_id(tcg_env);
2230 #endif
2231         break;
2232 
2233     case CR_EIEM:
2234         /* Exit to re-evaluate interrupts in the main loop. */
2235         ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2236         /* FALLTHRU */
2237     default:
2238         tcg_gen_st_i64(reg, tcg_env, offsetof(CPUHPPAState, cr[ctl]));
2239         break;
2240     }
2241     return nullify_end(ctx);
2242 #endif
2243 }
2244 
2245 static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
2246 {
2247     TCGv_i64 tmp = tcg_temp_new_i64();
2248 
2249     tcg_gen_not_i64(tmp, load_gpr(ctx, a->r));
2250     tcg_gen_andi_i64(tmp, tmp, ctx->is_pa20 ? 63 : 31);
2251     save_or_nullify(ctx, cpu_sar, tmp);
2252 
2253     cond_free(&ctx->null_cond);
2254     return true;
2255 }
2256 
2257 static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
2258 {
2259     TCGv_i64 dest = dest_gpr(ctx, a->t);
2260 
2261 #ifdef CONFIG_USER_ONLY
2262     /* We don't implement space registers in user mode. */
2263     tcg_gen_movi_i64(dest, 0);
2264 #else
2265     tcg_gen_mov_i64(dest, space_select(ctx, a->sp, load_gpr(ctx, a->b)));
2266     tcg_gen_shri_i64(dest, dest, 32);
2267 #endif
2268     save_gpr(ctx, a->t, dest);
2269 
2270     cond_free(&ctx->null_cond);
2271     return true;
2272 }
2273 
2274 static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
2275 {
2276 #ifdef CONFIG_USER_ONLY
2277     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2278 #else
2279     TCGv_i64 tmp;
2280 
2281     /* HP-UX 11i and HP ODE use rsm for read-access to PSW */
2282     if (a->i) {
2283         CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2284     }
2285 
2286     nullify_over(ctx);
2287 
2288     tmp = tcg_temp_new_i64();
2289     tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, psw));
2290     tcg_gen_andi_i64(tmp, tmp, ~a->i);
2291     gen_helper_swap_system_mask(tmp, tcg_env, tmp);
2292     save_gpr(ctx, a->t, tmp);
2293 
2294     /* Exit the TB to recognize new interrupts, e.g. PSW_M.  */
2295     ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2296     return nullify_end(ctx);
2297 #endif
2298 }
2299 
2300 static bool trans_ssm(DisasContext *ctx, arg_ssm *a)
2301 {
2302     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2303 #ifndef CONFIG_USER_ONLY
2304     TCGv_i64 tmp;
2305 
2306     nullify_over(ctx);
2307 
2308     tmp = tcg_temp_new_i64();
2309     tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUHPPAState, psw));
2310     tcg_gen_ori_i64(tmp, tmp, a->i);
2311     gen_helper_swap_system_mask(tmp, tcg_env, tmp);
2312     save_gpr(ctx, a->t, tmp);
2313 
2314     /* Exit the TB to recognize new interrupts, e.g. PSW_I.  */
2315     ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2316     return nullify_end(ctx);
2317 #endif
2318 }
2319 
2320 static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a)
2321 {
2322     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2323 #ifndef CONFIG_USER_ONLY
2324     TCGv_i64 tmp, reg;
2325     nullify_over(ctx);
2326 
2327     reg = load_gpr(ctx, a->r);
2328     tmp = tcg_temp_new_i64();
2329     gen_helper_swap_system_mask(tmp, tcg_env, reg);
2330 
2331     /* Exit the TB to recognize new interrupts.  */
2332     ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2333     return nullify_end(ctx);
2334 #endif
2335 }
2336 
2337 static bool do_rfi(DisasContext *ctx, bool rfi_r)
2338 {
2339     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2340 #ifndef CONFIG_USER_ONLY
2341     nullify_over(ctx);
2342 
2343     if (rfi_r) {
2344         gen_helper_rfi_r(tcg_env);
2345     } else {
2346         gen_helper_rfi(tcg_env);
2347     }
2348     /* Exit the TB to recognize new interrupts.  */
2349     tcg_gen_exit_tb(NULL, 0);
2350     ctx->base.is_jmp = DISAS_NORETURN;
2351 
2352     return nullify_end(ctx);
2353 #endif
2354 }
2355 
2356 static bool trans_rfi(DisasContext *ctx, arg_rfi *a)
2357 {
2358     return do_rfi(ctx, false);
2359 }
2360 
2361 static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a)
2362 {
2363     return do_rfi(ctx, true);
2364 }
2365 
2366 static bool trans_halt(DisasContext *ctx, arg_halt *a)
2367 {
2368     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2369 #ifndef CONFIG_USER_ONLY
2370     nullify_over(ctx);
2371     gen_helper_halt(tcg_env);
2372     ctx->base.is_jmp = DISAS_NORETURN;
2373     return nullify_end(ctx);
2374 #endif
2375 }
2376 
2377 static bool trans_reset(DisasContext *ctx, arg_reset *a)
2378 {
2379     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2380 #ifndef CONFIG_USER_ONLY
2381     nullify_over(ctx);
2382     gen_helper_reset(tcg_env);
2383     ctx->base.is_jmp = DISAS_NORETURN;
2384     return nullify_end(ctx);
2385 #endif
2386 }
2387 
2388 static bool do_getshadowregs(DisasContext *ctx)
2389 {
2390     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2391     nullify_over(ctx);
2392     tcg_gen_ld_i64(cpu_gr[1], tcg_env, offsetof(CPUHPPAState, shadow[0]));
2393     tcg_gen_ld_i64(cpu_gr[8], tcg_env, offsetof(CPUHPPAState, shadow[1]));
2394     tcg_gen_ld_i64(cpu_gr[9], tcg_env, offsetof(CPUHPPAState, shadow[2]));
2395     tcg_gen_ld_i64(cpu_gr[16], tcg_env, offsetof(CPUHPPAState, shadow[3]));
2396     tcg_gen_ld_i64(cpu_gr[17], tcg_env, offsetof(CPUHPPAState, shadow[4]));
2397     tcg_gen_ld_i64(cpu_gr[24], tcg_env, offsetof(CPUHPPAState, shadow[5]));
2398     tcg_gen_ld_i64(cpu_gr[25], tcg_env, offsetof(CPUHPPAState, shadow[6]));
2399     return nullify_end(ctx);
2400 }
2401 
2402 static bool do_putshadowregs(DisasContext *ctx)
2403 {
2404     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2405     nullify_over(ctx);
2406     tcg_gen_st_i64(cpu_gr[1], tcg_env, offsetof(CPUHPPAState, shadow[0]));
2407     tcg_gen_st_i64(cpu_gr[8], tcg_env, offsetof(CPUHPPAState, shadow[1]));
2408     tcg_gen_st_i64(cpu_gr[9], tcg_env, offsetof(CPUHPPAState, shadow[2]));
2409     tcg_gen_st_i64(cpu_gr[16], tcg_env, offsetof(CPUHPPAState, shadow[3]));
2410     tcg_gen_st_i64(cpu_gr[17], tcg_env, offsetof(CPUHPPAState, shadow[4]));
2411     tcg_gen_st_i64(cpu_gr[24], tcg_env, offsetof(CPUHPPAState, shadow[5]));
2412     tcg_gen_st_i64(cpu_gr[25], tcg_env, offsetof(CPUHPPAState, shadow[6]));
2413     return nullify_end(ctx);
2414 }
2415 
2416 static bool trans_getshadowregs(DisasContext *ctx, arg_getshadowregs *a)
2417 {
2418     return do_getshadowregs(ctx);
2419 }
2420 
2421 static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
2422 {
2423     if (a->m) {
2424         TCGv_i64 dest = dest_gpr(ctx, a->b);
2425         TCGv_i64 src1 = load_gpr(ctx, a->b);
2426         TCGv_i64 src2 = load_gpr(ctx, a->x);
2427 
2428         /* The only thing we need to do is the base register modification.  */
2429         tcg_gen_add_i64(dest, src1, src2);
2430         save_gpr(ctx, a->b, dest);
2431     }
2432     cond_free(&ctx->null_cond);
2433     return true;
2434 }
2435 
2436 static bool trans_fic(DisasContext *ctx, arg_ldst *a)
2437 {
2438     /* End TB for flush instruction cache, so we pick up new insns. */
2439     ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2440     return trans_nop_addrx(ctx, a);
2441 }
2442 
2443 static bool trans_probe(DisasContext *ctx, arg_probe *a)
2444 {
2445     TCGv_i64 dest, ofs;
2446     TCGv_i32 level, want;
2447     TCGv_i64 addr;
2448 
2449     nullify_over(ctx);
2450 
2451     dest = dest_gpr(ctx, a->t);
2452     form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2453 
2454     if (a->imm) {
2455         level = tcg_constant_i32(a->ri & 3);
2456     } else {
2457         level = tcg_temp_new_i32();
2458         tcg_gen_extrl_i64_i32(level, load_gpr(ctx, a->ri));
2459         tcg_gen_andi_i32(level, level, 3);
2460     }
2461     want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ);
2462 
2463     gen_helper_probe(dest, tcg_env, addr, level, want);
2464 
2465     save_gpr(ctx, a->t, dest);
2466     return nullify_end(ctx);
2467 }
2468 
2469 static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
2470 {
2471     if (ctx->is_pa20) {
2472         return false;
2473     }
2474     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2475 #ifndef CONFIG_USER_ONLY
2476     TCGv_i64 addr;
2477     TCGv_i64 ofs, reg;
2478 
2479     nullify_over(ctx);
2480 
2481     form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2482     reg = load_gpr(ctx, a->r);
2483     if (a->addr) {
2484         gen_helper_itlba_pa11(tcg_env, addr, reg);
2485     } else {
2486         gen_helper_itlbp_pa11(tcg_env, addr, reg);
2487     }
2488 
2489     /* Exit TB for TLB change if mmu is enabled.  */
2490     if (ctx->tb_flags & PSW_C) {
2491         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2492     }
2493     return nullify_end(ctx);
2494 #endif
2495 }
2496 
2497 static bool do_pxtlb(DisasContext *ctx, arg_ldst *a, bool local)
2498 {
2499     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2500 #ifndef CONFIG_USER_ONLY
2501     TCGv_i64 addr;
2502     TCGv_i64 ofs;
2503 
2504     nullify_over(ctx);
2505 
2506     form_gva(ctx, &addr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2507 
2508     /*
2509      * Page align now, rather than later, so that we can add in the
2510      * page_size field from pa2.0 from the low 4 bits of GR[b].
2511      */
2512     tcg_gen_andi_i64(addr, addr, TARGET_PAGE_MASK);
2513     if (ctx->is_pa20) {
2514         tcg_gen_deposit_i64(addr, addr, load_gpr(ctx, a->b), 0, 4);
2515     }
2516 
2517     if (local) {
2518         gen_helper_ptlb_l(tcg_env, addr);
2519     } else {
2520         gen_helper_ptlb(tcg_env, addr);
2521     }
2522 
2523     if (a->m) {
2524         save_gpr(ctx, a->b, ofs);
2525     }
2526 
2527     /* Exit TB for TLB change if mmu is enabled.  */
2528     if (ctx->tb_flags & PSW_C) {
2529         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2530     }
2531     return nullify_end(ctx);
2532 #endif
2533 }
2534 
2535 static bool trans_pxtlb(DisasContext *ctx, arg_ldst *a)
2536 {
2537     return do_pxtlb(ctx, a, false);
2538 }
2539 
2540 static bool trans_pxtlb_l(DisasContext *ctx, arg_ldst *a)
2541 {
2542     return ctx->is_pa20 && do_pxtlb(ctx, a, true);
2543 }
2544 
2545 static bool trans_pxtlbe(DisasContext *ctx, arg_ldst *a)
2546 {
2547     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2548 #ifndef CONFIG_USER_ONLY
2549     nullify_over(ctx);
2550 
2551     trans_nop_addrx(ctx, a);
2552     gen_helper_ptlbe(tcg_env);
2553 
2554     /* Exit TB for TLB change if mmu is enabled.  */
2555     if (ctx->tb_flags & PSW_C) {
2556         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2557     }
2558     return nullify_end(ctx);
2559 #endif
2560 }
2561 
2562 /*
2563  * Implement the pcxl and pcxl2 Fast TLB Insert instructions.
2564  * See
2565  *     https://parisc.wiki.kernel.org/images-parisc/a/a9/Pcxl2_ers.pdf
2566  *     page 13-9 (195/206)
2567  */
2568 static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
2569 {
2570     if (ctx->is_pa20) {
2571         return false;
2572     }
2573     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2574 #ifndef CONFIG_USER_ONLY
2575     TCGv_i64 addr, atl, stl;
2576     TCGv_i64 reg;
2577 
2578     nullify_over(ctx);
2579 
2580     /*
2581      * FIXME:
2582      *  if (not (pcxl or pcxl2))
2583      *    return gen_illegal(ctx);
2584      */
2585 
2586     atl = tcg_temp_new_i64();
2587     stl = tcg_temp_new_i64();
2588     addr = tcg_temp_new_i64();
2589 
2590     tcg_gen_ld32u_i64(stl, tcg_env,
2591                       a->data ? offsetof(CPUHPPAState, cr[CR_ISR])
2592                       : offsetof(CPUHPPAState, cr[CR_IIASQ]));
2593     tcg_gen_ld32u_i64(atl, tcg_env,
2594                       a->data ? offsetof(CPUHPPAState, cr[CR_IOR])
2595                       : offsetof(CPUHPPAState, cr[CR_IIAOQ]));
2596     tcg_gen_shli_i64(stl, stl, 32);
2597     tcg_gen_or_i64(addr, atl, stl);
2598 
2599     reg = load_gpr(ctx, a->r);
2600     if (a->addr) {
2601         gen_helper_itlba_pa11(tcg_env, addr, reg);
2602     } else {
2603         gen_helper_itlbp_pa11(tcg_env, addr, reg);
2604     }
2605 
2606     /* Exit TB for TLB change if mmu is enabled.  */
2607     if (ctx->tb_flags & PSW_C) {
2608         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2609     }
2610     return nullify_end(ctx);
2611 #endif
2612 }
2613 
2614 static bool trans_ixtlbt(DisasContext *ctx, arg_ixtlbt *a)
2615 {
2616     if (!ctx->is_pa20) {
2617         return false;
2618     }
2619     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2620 #ifndef CONFIG_USER_ONLY
2621     nullify_over(ctx);
2622     {
2623         TCGv_i64 src1 = load_gpr(ctx, a->r1);
2624         TCGv_i64 src2 = load_gpr(ctx, a->r2);
2625 
2626         if (a->data) {
2627             gen_helper_idtlbt_pa20(tcg_env, src1, src2);
2628         } else {
2629             gen_helper_iitlbt_pa20(tcg_env, src1, src2);
2630         }
2631     }
2632     /* Exit TB for TLB change if mmu is enabled.  */
2633     if (ctx->tb_flags & PSW_C) {
2634         ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2635     }
2636     return nullify_end(ctx);
2637 #endif
2638 }
2639 
2640 static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
2641 {
2642     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2643 #ifndef CONFIG_USER_ONLY
2644     TCGv_i64 vaddr;
2645     TCGv_i64 ofs, paddr;
2646 
2647     nullify_over(ctx);
2648 
2649     form_gva(ctx, &vaddr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2650 
2651     paddr = tcg_temp_new_i64();
2652     gen_helper_lpa(paddr, tcg_env, vaddr);
2653 
2654     /* Note that physical address result overrides base modification.  */
2655     if (a->m) {
2656         save_gpr(ctx, a->b, ofs);
2657     }
2658     save_gpr(ctx, a->t, paddr);
2659 
2660     return nullify_end(ctx);
2661 #endif
2662 }
2663 
2664 static bool trans_lci(DisasContext *ctx, arg_lci *a)
2665 {
2666     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2667 
2668     /* The Coherence Index is an implementation-defined function of the
2669        physical address.  Two addresses with the same CI have a coherent
2670        view of the cache.  Our implementation is to return 0 for all,
2671        since the entire address space is coherent.  */
2672     save_gpr(ctx, a->t, ctx->zero);
2673 
2674     cond_free(&ctx->null_cond);
2675     return true;
2676 }
2677 
2678 static bool trans_add(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2679 {
2680     return do_add_reg(ctx, a, false, false, false, false);
2681 }
2682 
2683 static bool trans_add_l(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2684 {
2685     return do_add_reg(ctx, a, true, false, false, false);
2686 }
2687 
2688 static bool trans_add_tsv(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2689 {
2690     return do_add_reg(ctx, a, false, true, false, false);
2691 }
2692 
2693 static bool trans_add_c(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2694 {
2695     return do_add_reg(ctx, a, false, false, false, true);
2696 }
2697 
2698 static bool trans_add_c_tsv(DisasContext *ctx, arg_rrr_cf_d_sh *a)
2699 {
2700     return do_add_reg(ctx, a, false, true, false, true);
2701 }
2702 
2703 static bool trans_sub(DisasContext *ctx, arg_rrr_cf_d *a)
2704 {
2705     return do_sub_reg(ctx, a, false, false, false);
2706 }
2707 
2708 static bool trans_sub_tsv(DisasContext *ctx, arg_rrr_cf_d *a)
2709 {
2710     return do_sub_reg(ctx, a, true, false, false);
2711 }
2712 
2713 static bool trans_sub_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2714 {
2715     return do_sub_reg(ctx, a, false, false, true);
2716 }
2717 
2718 static bool trans_sub_tsv_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2719 {
2720     return do_sub_reg(ctx, a, true, false, true);
2721 }
2722 
2723 static bool trans_sub_b(DisasContext *ctx, arg_rrr_cf_d *a)
2724 {
2725     return do_sub_reg(ctx, a, false, true, false);
2726 }
2727 
2728 static bool trans_sub_b_tsv(DisasContext *ctx, arg_rrr_cf_d *a)
2729 {
2730     return do_sub_reg(ctx, a, true, true, false);
2731 }
2732 
2733 static bool trans_andcm(DisasContext *ctx, arg_rrr_cf_d *a)
2734 {
2735     return do_log_reg(ctx, a, tcg_gen_andc_i64);
2736 }
2737 
2738 static bool trans_and(DisasContext *ctx, arg_rrr_cf_d *a)
2739 {
2740     return do_log_reg(ctx, a, tcg_gen_and_i64);
2741 }
2742 
2743 static bool trans_or(DisasContext *ctx, arg_rrr_cf_d *a)
2744 {
2745     if (a->cf == 0) {
2746         unsigned r2 = a->r2;
2747         unsigned r1 = a->r1;
2748         unsigned rt = a->t;
2749 
2750         if (rt == 0) { /* NOP */
2751             cond_free(&ctx->null_cond);
2752             return true;
2753         }
2754         if (r2 == 0) { /* COPY */
2755             if (r1 == 0) {
2756                 TCGv_i64 dest = dest_gpr(ctx, rt);
2757                 tcg_gen_movi_i64(dest, 0);
2758                 save_gpr(ctx, rt, dest);
2759             } else {
2760                 save_gpr(ctx, rt, cpu_gr[r1]);
2761             }
2762             cond_free(&ctx->null_cond);
2763             return true;
2764         }
2765 #ifndef CONFIG_USER_ONLY
2766         /* These are QEMU extensions and are nops in the real architecture:
2767          *
2768          * or %r10,%r10,%r10 -- idle loop; wait for interrupt
2769          * or %r31,%r31,%r31 -- death loop; offline cpu
2770          *                      currently implemented as idle.
2771          */
2772         if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
2773             /* No need to check for supervisor, as userland can only pause
2774                until the next timer interrupt.  */
2775             nullify_over(ctx);
2776 
2777             /* Advance the instruction queue.  */
2778             copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2779             copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2780             nullify_set(ctx, 0);
2781 
2782             /* Tell the qemu main loop to halt until this cpu has work.  */
2783             tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
2784                            offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2785             gen_excp_1(EXCP_HALTED);
2786             ctx->base.is_jmp = DISAS_NORETURN;
2787 
2788             return nullify_end(ctx);
2789         }
2790 #endif
2791     }
2792     return do_log_reg(ctx, a, tcg_gen_or_i64);
2793 }
2794 
2795 static bool trans_xor(DisasContext *ctx, arg_rrr_cf_d *a)
2796 {
2797     return do_log_reg(ctx, a, tcg_gen_xor_i64);
2798 }
2799 
2800 static bool trans_cmpclr(DisasContext *ctx, arg_rrr_cf_d *a)
2801 {
2802     TCGv_i64 tcg_r1, tcg_r2;
2803 
2804     if (a->cf) {
2805         nullify_over(ctx);
2806     }
2807     tcg_r1 = load_gpr(ctx, a->r1);
2808     tcg_r2 = load_gpr(ctx, a->r2);
2809     do_cmpclr(ctx, a->t, tcg_r1, tcg_r2, a->cf, a->d);
2810     return nullify_end(ctx);
2811 }
2812 
2813 static bool trans_uxor(DisasContext *ctx, arg_rrr_cf_d *a)
2814 {
2815     TCGv_i64 tcg_r1, tcg_r2, dest;
2816 
2817     if (a->cf) {
2818         nullify_over(ctx);
2819     }
2820 
2821     tcg_r1 = load_gpr(ctx, a->r1);
2822     tcg_r2 = load_gpr(ctx, a->r2);
2823     dest = dest_gpr(ctx, a->t);
2824 
2825     tcg_gen_xor_i64(dest, tcg_r1, tcg_r2);
2826     save_gpr(ctx, a->t, dest);
2827 
2828     cond_free(&ctx->null_cond);
2829     if (a->cf) {
2830         ctx->null_cond = do_unit_zero_cond(a->cf, a->d, dest);
2831     }
2832 
2833     return nullify_end(ctx);
2834 }
2835 
2836 static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf_d *a, bool is_tc)
2837 {
2838     TCGv_i64 tcg_r1, tcg_r2, tmp;
2839 
2840     if (a->cf == 0) {
2841         tcg_r2 = load_gpr(ctx, a->r2);
2842         tmp = dest_gpr(ctx, a->t);
2843 
2844         if (a->r1 == 0) {
2845             /* UADDCM r0,src,dst is the common idiom for dst = ~src. */
2846             tcg_gen_not_i64(tmp, tcg_r2);
2847         } else {
2848             /*
2849              * Recall that r1 - r2 == r1 + ~r2 + 1.
2850              * Thus r1 + ~r2 == r1 - r2 - 1,
2851              * which does not require an extra temporary.
2852              */
2853             tcg_r1 = load_gpr(ctx, a->r1);
2854             tcg_gen_sub_i64(tmp, tcg_r1, tcg_r2);
2855             tcg_gen_subi_i64(tmp, tmp, 1);
2856         }
2857         save_gpr(ctx, a->t, tmp);
2858         cond_free(&ctx->null_cond);
2859         return true;
2860     }
2861 
2862     nullify_over(ctx);
2863     tcg_r1 = load_gpr(ctx, a->r1);
2864     tcg_r2 = load_gpr(ctx, a->r2);
2865     tmp = tcg_temp_new_i64();
2866     tcg_gen_not_i64(tmp, tcg_r2);
2867     do_unit_addsub(ctx, a->t, tcg_r1, tmp, a->cf, a->d, is_tc, true);
2868     return nullify_end(ctx);
2869 }
2870 
2871 static bool trans_uaddcm(DisasContext *ctx, arg_rrr_cf_d *a)
2872 {
2873     return do_uaddcm(ctx, a, false);
2874 }
2875 
2876 static bool trans_uaddcm_tc(DisasContext *ctx, arg_rrr_cf_d *a)
2877 {
2878     return do_uaddcm(ctx, a, true);
2879 }
2880 
2881 static bool do_dcor(DisasContext *ctx, arg_rr_cf_d *a, bool is_i)
2882 {
2883     TCGv_i64 tmp;
2884 
2885     nullify_over(ctx);
2886 
2887     tmp = tcg_temp_new_i64();
2888     tcg_gen_extract2_i64(tmp, cpu_psw_cb, cpu_psw_cb_msb, 4);
2889     if (!is_i) {
2890         tcg_gen_not_i64(tmp, tmp);
2891     }
2892     tcg_gen_andi_i64(tmp, tmp, (uint64_t)0x1111111111111111ull);
2893     tcg_gen_muli_i64(tmp, tmp, 6);
2894     do_unit_addsub(ctx, a->t, load_gpr(ctx, a->r), tmp,
2895                    a->cf, a->d, false, is_i);
2896     return nullify_end(ctx);
2897 }
2898 
2899 static bool trans_dcor(DisasContext *ctx, arg_rr_cf_d *a)
2900 {
2901     return do_dcor(ctx, a, false);
2902 }
2903 
2904 static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf_d *a)
2905 {
2906     return do_dcor(ctx, a, true);
2907 }
2908 
2909 static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
2910 {
2911     TCGv_i64 dest, add1, add2, addc, in1, in2;
2912 
2913     nullify_over(ctx);
2914 
2915     in1 = load_gpr(ctx, a->r1);
2916     in2 = load_gpr(ctx, a->r2);
2917 
2918     add1 = tcg_temp_new_i64();
2919     add2 = tcg_temp_new_i64();
2920     addc = tcg_temp_new_i64();
2921     dest = tcg_temp_new_i64();
2922 
2923     /* Form R1 << 1 | PSW[CB]{8}.  */
2924     tcg_gen_add_i64(add1, in1, in1);
2925     tcg_gen_add_i64(add1, add1, get_psw_carry(ctx, false));
2926 
2927     /*
2928      * Add or subtract R2, depending on PSW[V].  Proper computation of
2929      * carry requires that we subtract via + ~R2 + 1, as described in
2930      * the manual.  By extracting and masking V, we can produce the
2931      * proper inputs to the addition without movcond.
2932      */
2933     tcg_gen_sextract_i64(addc, cpu_psw_v, 31, 1);
2934     tcg_gen_xor_i64(add2, in2, addc);
2935     tcg_gen_andi_i64(addc, addc, 1);
2936 
2937     tcg_gen_add2_i64(dest, cpu_psw_cb_msb, add1, ctx->zero, add2, ctx->zero);
2938     tcg_gen_add2_i64(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb,
2939                      addc, ctx->zero);
2940 
2941     /* Write back the result register.  */
2942     save_gpr(ctx, a->t, dest);
2943 
2944     /* Write back PSW[CB].  */
2945     tcg_gen_xor_i64(cpu_psw_cb, add1, add2);
2946     tcg_gen_xor_i64(cpu_psw_cb, cpu_psw_cb, dest);
2947 
2948     /*
2949      * Write back PSW[V] for the division step.
2950      * Shift cb{8} from where it lives in bit 32 to bit 31,
2951      * so that it overlaps r2{32} in bit 31.
2952      */
2953     tcg_gen_shri_i64(cpu_psw_v, cpu_psw_cb, 1);
2954     tcg_gen_xor_i64(cpu_psw_v, cpu_psw_v, in2);
2955 
2956     /* Install the new nullification.  */
2957     if (a->cf) {
2958         TCGv_i64 sv = NULL, uv = NULL;
2959         if (cond_need_sv(a->cf >> 1)) {
2960             sv = do_add_sv(ctx, dest, add1, add2, in1, 1, false);
2961         } else if (cond_need_cb(a->cf >> 1)) {
2962             uv = do_add_uv(ctx, cpu_psw_cb, NULL, in1, 1, false);
2963         }
2964         ctx->null_cond = do_cond(ctx, a->cf, false, dest, uv, sv);
2965     }
2966 
2967     return nullify_end(ctx);
2968 }
2969 
2970 static bool trans_addi(DisasContext *ctx, arg_rri_cf *a)
2971 {
2972     return do_add_imm(ctx, a, false, false);
2973 }
2974 
2975 static bool trans_addi_tsv(DisasContext *ctx, arg_rri_cf *a)
2976 {
2977     return do_add_imm(ctx, a, true, false);
2978 }
2979 
2980 static bool trans_addi_tc(DisasContext *ctx, arg_rri_cf *a)
2981 {
2982     return do_add_imm(ctx, a, false, true);
2983 }
2984 
2985 static bool trans_addi_tc_tsv(DisasContext *ctx, arg_rri_cf *a)
2986 {
2987     return do_add_imm(ctx, a, true, true);
2988 }
2989 
2990 static bool trans_subi(DisasContext *ctx, arg_rri_cf *a)
2991 {
2992     return do_sub_imm(ctx, a, false);
2993 }
2994 
2995 static bool trans_subi_tsv(DisasContext *ctx, arg_rri_cf *a)
2996 {
2997     return do_sub_imm(ctx, a, true);
2998 }
2999 
3000 static bool trans_cmpiclr(DisasContext *ctx, arg_rri_cf_d *a)
3001 {
3002     TCGv_i64 tcg_im, tcg_r2;
3003 
3004     if (a->cf) {
3005         nullify_over(ctx);
3006     }
3007 
3008     tcg_im = tcg_constant_i64(a->i);
3009     tcg_r2 = load_gpr(ctx, a->r);
3010     do_cmpclr(ctx, a->t, tcg_im, tcg_r2, a->cf, a->d);
3011 
3012     return nullify_end(ctx);
3013 }
3014 
3015 static bool do_multimedia(DisasContext *ctx, arg_rrr *a,
3016                           void (*fn)(TCGv_i64, TCGv_i64, TCGv_i64))
3017 {
3018     TCGv_i64 r1, r2, dest;
3019 
3020     if (!ctx->is_pa20) {
3021         return false;
3022     }
3023 
3024     nullify_over(ctx);
3025 
3026     r1 = load_gpr(ctx, a->r1);
3027     r2 = load_gpr(ctx, a->r2);
3028     dest = dest_gpr(ctx, a->t);
3029 
3030     fn(dest, r1, r2);
3031     save_gpr(ctx, a->t, dest);
3032 
3033     return nullify_end(ctx);
3034 }
3035 
3036 static bool do_multimedia_sh(DisasContext *ctx, arg_rri *a,
3037                              void (*fn)(TCGv_i64, TCGv_i64, int64_t))
3038 {
3039     TCGv_i64 r, dest;
3040 
3041     if (!ctx->is_pa20) {
3042         return false;
3043     }
3044 
3045     nullify_over(ctx);
3046 
3047     r = load_gpr(ctx, a->r);
3048     dest = dest_gpr(ctx, a->t);
3049 
3050     fn(dest, r, a->i);
3051     save_gpr(ctx, a->t, dest);
3052 
3053     return nullify_end(ctx);
3054 }
3055 
3056 static bool do_multimedia_shadd(DisasContext *ctx, arg_rrr_sh *a,
3057                                 void (*fn)(TCGv_i64, TCGv_i64,
3058                                            TCGv_i64, TCGv_i32))
3059 {
3060     TCGv_i64 r1, r2, dest;
3061 
3062     if (!ctx->is_pa20) {
3063         return false;
3064     }
3065 
3066     nullify_over(ctx);
3067 
3068     r1 = load_gpr(ctx, a->r1);
3069     r2 = load_gpr(ctx, a->r2);
3070     dest = dest_gpr(ctx, a->t);
3071 
3072     fn(dest, r1, r2, tcg_constant_i32(a->sh));
3073     save_gpr(ctx, a->t, dest);
3074 
3075     return nullify_end(ctx);
3076 }
3077 
3078 static bool trans_hadd(DisasContext *ctx, arg_rrr *a)
3079 {
3080     return do_multimedia(ctx, a, tcg_gen_vec_add16_i64);
3081 }
3082 
3083 static bool trans_hadd_ss(DisasContext *ctx, arg_rrr *a)
3084 {
3085     return do_multimedia(ctx, a, gen_helper_hadd_ss);
3086 }
3087 
3088 static bool trans_hadd_us(DisasContext *ctx, arg_rrr *a)
3089 {
3090     return do_multimedia(ctx, a, gen_helper_hadd_us);
3091 }
3092 
3093 static bool trans_havg(DisasContext *ctx, arg_rrr *a)
3094 {
3095     return do_multimedia(ctx, a, gen_helper_havg);
3096 }
3097 
3098 static bool trans_hshl(DisasContext *ctx, arg_rri *a)
3099 {
3100     return do_multimedia_sh(ctx, a, tcg_gen_vec_shl16i_i64);
3101 }
3102 
3103 static bool trans_hshr_s(DisasContext *ctx, arg_rri *a)
3104 {
3105     return do_multimedia_sh(ctx, a, tcg_gen_vec_sar16i_i64);
3106 }
3107 
3108 static bool trans_hshr_u(DisasContext *ctx, arg_rri *a)
3109 {
3110     return do_multimedia_sh(ctx, a, tcg_gen_vec_shr16i_i64);
3111 }
3112 
3113 static bool trans_hshladd(DisasContext *ctx, arg_rrr_sh *a)
3114 {
3115     return do_multimedia_shadd(ctx, a, gen_helper_hshladd);
3116 }
3117 
3118 static bool trans_hshradd(DisasContext *ctx, arg_rrr_sh *a)
3119 {
3120     return do_multimedia_shadd(ctx, a, gen_helper_hshradd);
3121 }
3122 
3123 static bool trans_hsub(DisasContext *ctx, arg_rrr *a)
3124 {
3125     return do_multimedia(ctx, a, tcg_gen_vec_sub16_i64);
3126 }
3127 
3128 static bool trans_hsub_ss(DisasContext *ctx, arg_rrr *a)
3129 {
3130     return do_multimedia(ctx, a, gen_helper_hsub_ss);
3131 }
3132 
3133 static bool trans_hsub_us(DisasContext *ctx, arg_rrr *a)
3134 {
3135     return do_multimedia(ctx, a, gen_helper_hsub_us);
3136 }
3137 
3138 static void gen_mixh_l(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3139 {
3140     uint64_t mask = 0xffff0000ffff0000ull;
3141     TCGv_i64 tmp = tcg_temp_new_i64();
3142 
3143     tcg_gen_andi_i64(tmp, r2, mask);
3144     tcg_gen_andi_i64(dst, r1, mask);
3145     tcg_gen_shri_i64(tmp, tmp, 16);
3146     tcg_gen_or_i64(dst, dst, tmp);
3147 }
3148 
3149 static bool trans_mixh_l(DisasContext *ctx, arg_rrr *a)
3150 {
3151     return do_multimedia(ctx, a, gen_mixh_l);
3152 }
3153 
3154 static void gen_mixh_r(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3155 {
3156     uint64_t mask = 0x0000ffff0000ffffull;
3157     TCGv_i64 tmp = tcg_temp_new_i64();
3158 
3159     tcg_gen_andi_i64(tmp, r1, mask);
3160     tcg_gen_andi_i64(dst, r2, mask);
3161     tcg_gen_shli_i64(tmp, tmp, 16);
3162     tcg_gen_or_i64(dst, dst, tmp);
3163 }
3164 
3165 static bool trans_mixh_r(DisasContext *ctx, arg_rrr *a)
3166 {
3167     return do_multimedia(ctx, a, gen_mixh_r);
3168 }
3169 
3170 static void gen_mixw_l(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3171 {
3172     TCGv_i64 tmp = tcg_temp_new_i64();
3173 
3174     tcg_gen_shri_i64(tmp, r2, 32);
3175     tcg_gen_deposit_i64(dst, r1, tmp, 0, 32);
3176 }
3177 
3178 static bool trans_mixw_l(DisasContext *ctx, arg_rrr *a)
3179 {
3180     return do_multimedia(ctx, a, gen_mixw_l);
3181 }
3182 
3183 static void gen_mixw_r(TCGv_i64 dst, TCGv_i64 r1, TCGv_i64 r2)
3184 {
3185     tcg_gen_deposit_i64(dst, r2, r1, 32, 32);
3186 }
3187 
3188 static bool trans_mixw_r(DisasContext *ctx, arg_rrr *a)
3189 {
3190     return do_multimedia(ctx, a, gen_mixw_r);
3191 }
3192 
3193 static bool trans_permh(DisasContext *ctx, arg_permh *a)
3194 {
3195     TCGv_i64 r, t0, t1, t2, t3;
3196 
3197     if (!ctx->is_pa20) {
3198         return false;
3199     }
3200 
3201     nullify_over(ctx);
3202 
3203     r = load_gpr(ctx, a->r1);
3204     t0 = tcg_temp_new_i64();
3205     t1 = tcg_temp_new_i64();
3206     t2 = tcg_temp_new_i64();
3207     t3 = tcg_temp_new_i64();
3208 
3209     tcg_gen_extract_i64(t0, r, (3 - a->c0) * 16, 16);
3210     tcg_gen_extract_i64(t1, r, (3 - a->c1) * 16, 16);
3211     tcg_gen_extract_i64(t2, r, (3 - a->c2) * 16, 16);
3212     tcg_gen_extract_i64(t3, r, (3 - a->c3) * 16, 16);
3213 
3214     tcg_gen_deposit_i64(t0, t1, t0, 16, 48);
3215     tcg_gen_deposit_i64(t2, t3, t2, 16, 48);
3216     tcg_gen_deposit_i64(t0, t2, t0, 32, 32);
3217 
3218     save_gpr(ctx, a->t, t0);
3219     return nullify_end(ctx);
3220 }
3221 
3222 static bool trans_ld(DisasContext *ctx, arg_ldst *a)
3223 {
3224     if (ctx->is_pa20) {
3225        /*
3226         * With pa20, LDB, LDH, LDW, LDD to %g0 are prefetches.
3227         * Any base modification still occurs.
3228         */
3229         if (a->t == 0) {
3230             return trans_nop_addrx(ctx, a);
3231         }
3232     } else if (a->size > MO_32) {
3233         return gen_illegal(ctx);
3234     }
3235     return do_load(ctx, a->t, a->b, a->x, a->scale ? a->size : 0,
3236                    a->disp, a->sp, a->m, a->size | MO_TE);
3237 }
3238 
3239 static bool trans_st(DisasContext *ctx, arg_ldst *a)
3240 {
3241     assert(a->x == 0 && a->scale == 0);
3242     if (!ctx->is_pa20 && a->size > MO_32) {
3243         return gen_illegal(ctx);
3244     }
3245     return do_store(ctx, a->t, a->b, a->disp, a->sp, a->m, a->size | MO_TE);
3246 }
3247 
3248 static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
3249 {
3250     MemOp mop = MO_TE | MO_ALIGN | a->size;
3251     TCGv_i64 dest, ofs;
3252     TCGv_i64 addr;
3253 
3254     if (!ctx->is_pa20 && a->size > MO_32) {
3255         return gen_illegal(ctx);
3256     }
3257 
3258     nullify_over(ctx);
3259 
3260     if (a->m) {
3261         /* Base register modification.  Make sure if RT == RB,
3262            we see the result of the load.  */
3263         dest = tcg_temp_new_i64();
3264     } else {
3265         dest = dest_gpr(ctx, a->t);
3266     }
3267 
3268     form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? 3 : 0,
3269              a->disp, a->sp, a->m, MMU_DISABLED(ctx));
3270 
3271     /*
3272      * For hppa1.1, LDCW is undefined unless aligned mod 16.
3273      * However actual hardware succeeds with aligned mod 4.
3274      * Detect this case and log a GUEST_ERROR.
3275      *
3276      * TODO: HPPA64 relaxes the over-alignment requirement
3277      * with the ,co completer.
3278      */
3279     gen_helper_ldc_check(addr);
3280 
3281     tcg_gen_atomic_xchg_i64(dest, addr, ctx->zero, ctx->mmu_idx, mop);
3282 
3283     if (a->m) {
3284         save_gpr(ctx, a->b, ofs);
3285     }
3286     save_gpr(ctx, a->t, dest);
3287 
3288     return nullify_end(ctx);
3289 }
3290 
3291 static bool trans_stby(DisasContext *ctx, arg_stby *a)
3292 {
3293     TCGv_i64 ofs, val;
3294     TCGv_i64 addr;
3295 
3296     nullify_over(ctx);
3297 
3298     form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
3299              MMU_DISABLED(ctx));
3300     val = load_gpr(ctx, a->r);
3301     if (a->a) {
3302         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3303             gen_helper_stby_e_parallel(tcg_env, addr, val);
3304         } else {
3305             gen_helper_stby_e(tcg_env, addr, val);
3306         }
3307     } else {
3308         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3309             gen_helper_stby_b_parallel(tcg_env, addr, val);
3310         } else {
3311             gen_helper_stby_b(tcg_env, addr, val);
3312         }
3313     }
3314     if (a->m) {
3315         tcg_gen_andi_i64(ofs, ofs, ~3);
3316         save_gpr(ctx, a->b, ofs);
3317     }
3318 
3319     return nullify_end(ctx);
3320 }
3321 
3322 static bool trans_stdby(DisasContext *ctx, arg_stby *a)
3323 {
3324     TCGv_i64 ofs, val;
3325     TCGv_i64 addr;
3326 
3327     if (!ctx->is_pa20) {
3328         return false;
3329     }
3330     nullify_over(ctx);
3331 
3332     form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
3333              MMU_DISABLED(ctx));
3334     val = load_gpr(ctx, a->r);
3335     if (a->a) {
3336         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3337             gen_helper_stdby_e_parallel(tcg_env, addr, val);
3338         } else {
3339             gen_helper_stdby_e(tcg_env, addr, val);
3340         }
3341     } else {
3342         if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3343             gen_helper_stdby_b_parallel(tcg_env, addr, val);
3344         } else {
3345             gen_helper_stdby_b(tcg_env, addr, val);
3346         }
3347     }
3348     if (a->m) {
3349         tcg_gen_andi_i64(ofs, ofs, ~7);
3350         save_gpr(ctx, a->b, ofs);
3351     }
3352 
3353     return nullify_end(ctx);
3354 }
3355 
3356 static bool trans_lda(DisasContext *ctx, arg_ldst *a)
3357 {
3358     int hold_mmu_idx = ctx->mmu_idx;
3359 
3360     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3361     ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
3362     trans_ld(ctx, a);
3363     ctx->mmu_idx = hold_mmu_idx;
3364     return true;
3365 }
3366 
3367 static bool trans_sta(DisasContext *ctx, arg_ldst *a)
3368 {
3369     int hold_mmu_idx = ctx->mmu_idx;
3370 
3371     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3372     ctx->mmu_idx = ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
3373     trans_st(ctx, a);
3374     ctx->mmu_idx = hold_mmu_idx;
3375     return true;
3376 }
3377 
3378 static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
3379 {
3380     TCGv_i64 tcg_rt = dest_gpr(ctx, a->t);
3381 
3382     tcg_gen_movi_i64(tcg_rt, a->i);
3383     save_gpr(ctx, a->t, tcg_rt);
3384     cond_free(&ctx->null_cond);
3385     return true;
3386 }
3387 
3388 static bool trans_addil(DisasContext *ctx, arg_addil *a)
3389 {
3390     TCGv_i64 tcg_rt = load_gpr(ctx, a->r);
3391     TCGv_i64 tcg_r1 = dest_gpr(ctx, 1);
3392 
3393     tcg_gen_addi_i64(tcg_r1, tcg_rt, a->i);
3394     save_gpr(ctx, 1, tcg_r1);
3395     cond_free(&ctx->null_cond);
3396     return true;
3397 }
3398 
3399 static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
3400 {
3401     TCGv_i64 tcg_rt = dest_gpr(ctx, a->t);
3402 
3403     /* Special case rb == 0, for the LDI pseudo-op.
3404        The COPY pseudo-op is handled for free within tcg_gen_addi_i64.  */
3405     if (a->b == 0) {
3406         tcg_gen_movi_i64(tcg_rt, a->i);
3407     } else {
3408         tcg_gen_addi_i64(tcg_rt, cpu_gr[a->b], a->i);
3409     }
3410     save_gpr(ctx, a->t, tcg_rt);
3411     cond_free(&ctx->null_cond);
3412     return true;
3413 }
3414 
3415 static bool do_cmpb(DisasContext *ctx, unsigned r, TCGv_i64 in1,
3416                     unsigned c, unsigned f, bool d, unsigned n, int disp)
3417 {
3418     TCGv_i64 dest, in2, sv;
3419     DisasCond cond;
3420 
3421     in2 = load_gpr(ctx, r);
3422     dest = tcg_temp_new_i64();
3423 
3424     tcg_gen_sub_i64(dest, in1, in2);
3425 
3426     sv = NULL;
3427     if (cond_need_sv(c)) {
3428         sv = do_sub_sv(ctx, dest, in1, in2);
3429     }
3430 
3431     cond = do_sub_cond(ctx, c * 2 + f, d, dest, in1, in2, sv);
3432     return do_cbranch(ctx, disp, n, &cond);
3433 }
3434 
3435 static bool trans_cmpb(DisasContext *ctx, arg_cmpb *a)
3436 {
3437     if (!ctx->is_pa20 && a->d) {
3438         return false;
3439     }
3440     nullify_over(ctx);
3441     return do_cmpb(ctx, a->r2, load_gpr(ctx, a->r1),
3442                    a->c, a->f, a->d, a->n, a->disp);
3443 }
3444 
3445 static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
3446 {
3447     if (!ctx->is_pa20 && a->d) {
3448         return false;
3449     }
3450     nullify_over(ctx);
3451     return do_cmpb(ctx, a->r, tcg_constant_i64(a->i),
3452                    a->c, a->f, a->d, a->n, a->disp);
3453 }
3454 
3455 static bool do_addb(DisasContext *ctx, unsigned r, TCGv_i64 in1,
3456                     unsigned c, unsigned f, unsigned n, int disp)
3457 {
3458     TCGv_i64 dest, in2, sv, cb_cond;
3459     DisasCond cond;
3460     bool d = false;
3461 
3462     /*
3463      * For hppa64, the ADDB conditions change with PSW.W,
3464      * dropping ZNV, SV, OD in favor of double-word EQ, LT, LE.
3465      */
3466     if (ctx->tb_flags & PSW_W) {
3467         d = c >= 5;
3468         if (d) {
3469             c &= 3;
3470         }
3471     }
3472 
3473     in2 = load_gpr(ctx, r);
3474     dest = tcg_temp_new_i64();
3475     sv = NULL;
3476     cb_cond = NULL;
3477 
3478     if (cond_need_cb(c)) {
3479         TCGv_i64 cb = tcg_temp_new_i64();
3480         TCGv_i64 cb_msb = tcg_temp_new_i64();
3481 
3482         tcg_gen_movi_i64(cb_msb, 0);
3483         tcg_gen_add2_i64(dest, cb_msb, in1, cb_msb, in2, cb_msb);
3484         tcg_gen_xor_i64(cb, in1, in2);
3485         tcg_gen_xor_i64(cb, cb, dest);
3486         cb_cond = get_carry(ctx, d, cb, cb_msb);
3487     } else {
3488         tcg_gen_add_i64(dest, in1, in2);
3489     }
3490     if (cond_need_sv(c)) {
3491         sv = do_add_sv(ctx, dest, in1, in2, in1, 0, d);
3492     }
3493 
3494     cond = do_cond(ctx, c * 2 + f, d, dest, cb_cond, sv);
3495     save_gpr(ctx, r, dest);
3496     return do_cbranch(ctx, disp, n, &cond);
3497 }
3498 
3499 static bool trans_addb(DisasContext *ctx, arg_addb *a)
3500 {
3501     nullify_over(ctx);
3502     return do_addb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3503 }
3504 
3505 static bool trans_addbi(DisasContext *ctx, arg_addbi *a)
3506 {
3507     nullify_over(ctx);
3508     return do_addb(ctx, a->r, tcg_constant_i64(a->i), a->c, a->f, a->n, a->disp);
3509 }
3510 
3511 static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
3512 {
3513     TCGv_i64 tmp, tcg_r;
3514     DisasCond cond;
3515 
3516     nullify_over(ctx);
3517 
3518     tmp = tcg_temp_new_i64();
3519     tcg_r = load_gpr(ctx, a->r);
3520     if (a->d) {
3521         tcg_gen_shl_i64(tmp, tcg_r, cpu_sar);
3522     } else {
3523         /* Force shift into [32,63] */
3524         tcg_gen_ori_i64(tmp, cpu_sar, 32);
3525         tcg_gen_shl_i64(tmp, tcg_r, tmp);
3526     }
3527 
3528     cond = cond_make_0_tmp(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3529     return do_cbranch(ctx, a->disp, a->n, &cond);
3530 }
3531 
3532 static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
3533 {
3534     TCGv_i64 tmp, tcg_r;
3535     DisasCond cond;
3536     int p;
3537 
3538     nullify_over(ctx);
3539 
3540     tmp = tcg_temp_new_i64();
3541     tcg_r = load_gpr(ctx, a->r);
3542     p = a->p | (a->d ? 0 : 32);
3543     tcg_gen_shli_i64(tmp, tcg_r, p);
3544 
3545     cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3546     return do_cbranch(ctx, a->disp, a->n, &cond);
3547 }
3548 
3549 static bool trans_movb(DisasContext *ctx, arg_movb *a)
3550 {
3551     TCGv_i64 dest;
3552     DisasCond cond;
3553 
3554     nullify_over(ctx);
3555 
3556     dest = dest_gpr(ctx, a->r2);
3557     if (a->r1 == 0) {
3558         tcg_gen_movi_i64(dest, 0);
3559     } else {
3560         tcg_gen_mov_i64(dest, cpu_gr[a->r1]);
3561     }
3562 
3563     /* All MOVB conditions are 32-bit. */
3564     cond = do_sed_cond(ctx, a->c, false, dest);
3565     return do_cbranch(ctx, a->disp, a->n, &cond);
3566 }
3567 
3568 static bool trans_movbi(DisasContext *ctx, arg_movbi *a)
3569 {
3570     TCGv_i64 dest;
3571     DisasCond cond;
3572 
3573     nullify_over(ctx);
3574 
3575     dest = dest_gpr(ctx, a->r);
3576     tcg_gen_movi_i64(dest, a->i);
3577 
3578     /* All MOVBI conditions are 32-bit. */
3579     cond = do_sed_cond(ctx, a->c, false, dest);
3580     return do_cbranch(ctx, a->disp, a->n, &cond);
3581 }
3582 
3583 static bool trans_shrp_sar(DisasContext *ctx, arg_shrp_sar *a)
3584 {
3585     TCGv_i64 dest, src2;
3586 
3587     if (!ctx->is_pa20 && a->d) {
3588         return false;
3589     }
3590     if (a->c) {
3591         nullify_over(ctx);
3592     }
3593 
3594     dest = dest_gpr(ctx, a->t);
3595     src2 = load_gpr(ctx, a->r2);
3596     if (a->r1 == 0) {
3597         if (a->d) {
3598             tcg_gen_shr_i64(dest, src2, cpu_sar);
3599         } else {
3600             TCGv_i64 tmp = tcg_temp_new_i64();
3601 
3602             tcg_gen_ext32u_i64(dest, src2);
3603             tcg_gen_andi_i64(tmp, cpu_sar, 31);
3604             tcg_gen_shr_i64(dest, dest, tmp);
3605         }
3606     } else if (a->r1 == a->r2) {
3607         if (a->d) {
3608             tcg_gen_rotr_i64(dest, src2, cpu_sar);
3609         } else {
3610             TCGv_i32 t32 = tcg_temp_new_i32();
3611             TCGv_i32 s32 = tcg_temp_new_i32();
3612 
3613             tcg_gen_extrl_i64_i32(t32, src2);
3614             tcg_gen_extrl_i64_i32(s32, cpu_sar);
3615             tcg_gen_andi_i32(s32, s32, 31);
3616             tcg_gen_rotr_i32(t32, t32, s32);
3617             tcg_gen_extu_i32_i64(dest, t32);
3618         }
3619     } else {
3620         TCGv_i64 src1 = load_gpr(ctx, a->r1);
3621 
3622         if (a->d) {
3623             TCGv_i64 t = tcg_temp_new_i64();
3624             TCGv_i64 n = tcg_temp_new_i64();
3625 
3626             tcg_gen_xori_i64(n, cpu_sar, 63);
3627             tcg_gen_shl_i64(t, src1, n);
3628             tcg_gen_shli_i64(t, t, 1);
3629             tcg_gen_shr_i64(dest, src2, cpu_sar);
3630             tcg_gen_or_i64(dest, dest, t);
3631         } else {
3632             TCGv_i64 t = tcg_temp_new_i64();
3633             TCGv_i64 s = tcg_temp_new_i64();
3634 
3635             tcg_gen_concat32_i64(t, src2, src1);
3636             tcg_gen_andi_i64(s, cpu_sar, 31);
3637             tcg_gen_shr_i64(dest, t, s);
3638         }
3639     }
3640     save_gpr(ctx, a->t, dest);
3641 
3642     /* Install the new nullification.  */
3643     cond_free(&ctx->null_cond);
3644     if (a->c) {
3645         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3646     }
3647     return nullify_end(ctx);
3648 }
3649 
3650 static bool trans_shrp_imm(DisasContext *ctx, arg_shrp_imm *a)
3651 {
3652     unsigned width, sa;
3653     TCGv_i64 dest, t2;
3654 
3655     if (!ctx->is_pa20 && a->d) {
3656         return false;
3657     }
3658     if (a->c) {
3659         nullify_over(ctx);
3660     }
3661 
3662     width = a->d ? 64 : 32;
3663     sa = width - 1 - a->cpos;
3664 
3665     dest = dest_gpr(ctx, a->t);
3666     t2 = load_gpr(ctx, a->r2);
3667     if (a->r1 == 0) {
3668         tcg_gen_extract_i64(dest, t2, sa, width - sa);
3669     } else if (width == TARGET_LONG_BITS) {
3670         tcg_gen_extract2_i64(dest, t2, cpu_gr[a->r1], sa);
3671     } else {
3672         assert(!a->d);
3673         if (a->r1 == a->r2) {
3674             TCGv_i32 t32 = tcg_temp_new_i32();
3675             tcg_gen_extrl_i64_i32(t32, t2);
3676             tcg_gen_rotri_i32(t32, t32, sa);
3677             tcg_gen_extu_i32_i64(dest, t32);
3678         } else {
3679             tcg_gen_concat32_i64(dest, t2, cpu_gr[a->r1]);
3680             tcg_gen_extract_i64(dest, dest, sa, 32);
3681         }
3682     }
3683     save_gpr(ctx, a->t, dest);
3684 
3685     /* Install the new nullification.  */
3686     cond_free(&ctx->null_cond);
3687     if (a->c) {
3688         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3689     }
3690     return nullify_end(ctx);
3691 }
3692 
3693 static bool trans_extr_sar(DisasContext *ctx, arg_extr_sar *a)
3694 {
3695     unsigned widthm1 = a->d ? 63 : 31;
3696     TCGv_i64 dest, src, tmp;
3697 
3698     if (!ctx->is_pa20 && a->d) {
3699         return false;
3700     }
3701     if (a->c) {
3702         nullify_over(ctx);
3703     }
3704 
3705     dest = dest_gpr(ctx, a->t);
3706     src = load_gpr(ctx, a->r);
3707     tmp = tcg_temp_new_i64();
3708 
3709     /* Recall that SAR is using big-endian bit numbering.  */
3710     tcg_gen_andi_i64(tmp, cpu_sar, widthm1);
3711     tcg_gen_xori_i64(tmp, tmp, widthm1);
3712 
3713     if (a->se) {
3714         if (!a->d) {
3715             tcg_gen_ext32s_i64(dest, src);
3716             src = dest;
3717         }
3718         tcg_gen_sar_i64(dest, src, tmp);
3719         tcg_gen_sextract_i64(dest, dest, 0, a->len);
3720     } else {
3721         if (!a->d) {
3722             tcg_gen_ext32u_i64(dest, src);
3723             src = dest;
3724         }
3725         tcg_gen_shr_i64(dest, src, tmp);
3726         tcg_gen_extract_i64(dest, dest, 0, a->len);
3727     }
3728     save_gpr(ctx, a->t, dest);
3729 
3730     /* Install the new nullification.  */
3731     cond_free(&ctx->null_cond);
3732     if (a->c) {
3733         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3734     }
3735     return nullify_end(ctx);
3736 }
3737 
3738 static bool trans_extr_imm(DisasContext *ctx, arg_extr_imm *a)
3739 {
3740     unsigned len, cpos, width;
3741     TCGv_i64 dest, src;
3742 
3743     if (!ctx->is_pa20 && a->d) {
3744         return false;
3745     }
3746     if (a->c) {
3747         nullify_over(ctx);
3748     }
3749 
3750     len = a->len;
3751     width = a->d ? 64 : 32;
3752     cpos = width - 1 - a->pos;
3753     if (cpos + len > width) {
3754         len = width - cpos;
3755     }
3756 
3757     dest = dest_gpr(ctx, a->t);
3758     src = load_gpr(ctx, a->r);
3759     if (a->se) {
3760         tcg_gen_sextract_i64(dest, src, cpos, len);
3761     } else {
3762         tcg_gen_extract_i64(dest, src, cpos, len);
3763     }
3764     save_gpr(ctx, a->t, dest);
3765 
3766     /* Install the new nullification.  */
3767     cond_free(&ctx->null_cond);
3768     if (a->c) {
3769         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3770     }
3771     return nullify_end(ctx);
3772 }
3773 
3774 static bool trans_depi_imm(DisasContext *ctx, arg_depi_imm *a)
3775 {
3776     unsigned len, width;
3777     uint64_t mask0, mask1;
3778     TCGv_i64 dest;
3779 
3780     if (!ctx->is_pa20 && a->d) {
3781         return false;
3782     }
3783     if (a->c) {
3784         nullify_over(ctx);
3785     }
3786 
3787     len = a->len;
3788     width = a->d ? 64 : 32;
3789     if (a->cpos + len > width) {
3790         len = width - a->cpos;
3791     }
3792 
3793     dest = dest_gpr(ctx, a->t);
3794     mask0 = deposit64(0, a->cpos, len, a->i);
3795     mask1 = deposit64(-1, a->cpos, len, a->i);
3796 
3797     if (a->nz) {
3798         TCGv_i64 src = load_gpr(ctx, a->t);
3799         tcg_gen_andi_i64(dest, src, mask1);
3800         tcg_gen_ori_i64(dest, dest, mask0);
3801     } else {
3802         tcg_gen_movi_i64(dest, mask0);
3803     }
3804     save_gpr(ctx, a->t, dest);
3805 
3806     /* Install the new nullification.  */
3807     cond_free(&ctx->null_cond);
3808     if (a->c) {
3809         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3810     }
3811     return nullify_end(ctx);
3812 }
3813 
3814 static bool trans_dep_imm(DisasContext *ctx, arg_dep_imm *a)
3815 {
3816     unsigned rs = a->nz ? a->t : 0;
3817     unsigned len, width;
3818     TCGv_i64 dest, val;
3819 
3820     if (!ctx->is_pa20 && a->d) {
3821         return false;
3822     }
3823     if (a->c) {
3824         nullify_over(ctx);
3825     }
3826 
3827     len = a->len;
3828     width = a->d ? 64 : 32;
3829     if (a->cpos + len > width) {
3830         len = width - a->cpos;
3831     }
3832 
3833     dest = dest_gpr(ctx, a->t);
3834     val = load_gpr(ctx, a->r);
3835     if (rs == 0) {
3836         tcg_gen_deposit_z_i64(dest, val, a->cpos, len);
3837     } else {
3838         tcg_gen_deposit_i64(dest, cpu_gr[rs], val, a->cpos, len);
3839     }
3840     save_gpr(ctx, a->t, dest);
3841 
3842     /* Install the new nullification.  */
3843     cond_free(&ctx->null_cond);
3844     if (a->c) {
3845         ctx->null_cond = do_sed_cond(ctx, a->c, a->d, dest);
3846     }
3847     return nullify_end(ctx);
3848 }
3849 
3850 static bool do_dep_sar(DisasContext *ctx, unsigned rt, unsigned c,
3851                        bool d, bool nz, unsigned len, TCGv_i64 val)
3852 {
3853     unsigned rs = nz ? rt : 0;
3854     unsigned widthm1 = d ? 63 : 31;
3855     TCGv_i64 mask, tmp, shift, dest;
3856     uint64_t msb = 1ULL << (len - 1);
3857 
3858     dest = dest_gpr(ctx, rt);
3859     shift = tcg_temp_new_i64();
3860     tmp = tcg_temp_new_i64();
3861 
3862     /* Convert big-endian bit numbering in SAR to left-shift.  */
3863     tcg_gen_andi_i64(shift, cpu_sar, widthm1);
3864     tcg_gen_xori_i64(shift, shift, widthm1);
3865 
3866     mask = tcg_temp_new_i64();
3867     tcg_gen_movi_i64(mask, msb + (msb - 1));
3868     tcg_gen_and_i64(tmp, val, mask);
3869     if (rs) {
3870         tcg_gen_shl_i64(mask, mask, shift);
3871         tcg_gen_shl_i64(tmp, tmp, shift);
3872         tcg_gen_andc_i64(dest, cpu_gr[rs], mask);
3873         tcg_gen_or_i64(dest, dest, tmp);
3874     } else {
3875         tcg_gen_shl_i64(dest, tmp, shift);
3876     }
3877     save_gpr(ctx, rt, dest);
3878 
3879     /* Install the new nullification.  */
3880     cond_free(&ctx->null_cond);
3881     if (c) {
3882         ctx->null_cond = do_sed_cond(ctx, c, d, dest);
3883     }
3884     return nullify_end(ctx);
3885 }
3886 
3887 static bool trans_dep_sar(DisasContext *ctx, arg_dep_sar *a)
3888 {
3889     if (!ctx->is_pa20 && a->d) {
3890         return false;
3891     }
3892     if (a->c) {
3893         nullify_over(ctx);
3894     }
3895     return do_dep_sar(ctx, a->t, a->c, a->d, a->nz, a->len,
3896                       load_gpr(ctx, a->r));
3897 }
3898 
3899 static bool trans_depi_sar(DisasContext *ctx, arg_depi_sar *a)
3900 {
3901     if (!ctx->is_pa20 && a->d) {
3902         return false;
3903     }
3904     if (a->c) {
3905         nullify_over(ctx);
3906     }
3907     return do_dep_sar(ctx, a->t, a->c, a->d, a->nz, a->len,
3908                       tcg_constant_i64(a->i));
3909 }
3910 
3911 static bool trans_be(DisasContext *ctx, arg_be *a)
3912 {
3913     TCGv_i64 tmp;
3914 
3915 #ifdef CONFIG_USER_ONLY
3916     /* ??? It seems like there should be a good way of using
3917        "be disp(sr2, r0)", the canonical gateway entry mechanism
3918        to our advantage.  But that appears to be inconvenient to
3919        manage along side branch delay slots.  Therefore we handle
3920        entry into the gateway page via absolute address.  */
3921     /* Since we don't implement spaces, just branch.  Do notice the special
3922        case of "be disp(*,r0)" using a direct branch to disp, so that we can
3923        goto_tb to the TB containing the syscall.  */
3924     if (a->b == 0) {
3925         return do_dbranch(ctx, a->disp, a->l, a->n);
3926     }
3927 #else
3928     nullify_over(ctx);
3929 #endif
3930 
3931     tmp = tcg_temp_new_i64();
3932     tcg_gen_addi_i64(tmp, load_gpr(ctx, a->b), a->disp);
3933     tmp = do_ibranch_priv(ctx, tmp);
3934 
3935 #ifdef CONFIG_USER_ONLY
3936     return do_ibranch(ctx, tmp, a->l, a->n);
3937 #else
3938     TCGv_i64 new_spc = tcg_temp_new_i64();
3939 
3940     load_spr(ctx, new_spc, a->sp);
3941     if (a->l) {
3942         copy_iaoq_entry(ctx, cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3943         tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_b);
3944     }
3945     if (a->n && use_nullify_skip(ctx)) {
3946         copy_iaoq_entry(ctx, cpu_iaoq_f, -1, tmp);
3947         tcg_gen_addi_i64(tmp, tmp, 4);
3948         copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
3949         tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3950         tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3951         nullify_set(ctx, 0);
3952     } else {
3953         copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3954         if (ctx->iaoq_b == -1) {
3955             tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3956         }
3957         copy_iaoq_entry(ctx, cpu_iaoq_b, -1, tmp);
3958         tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3959         nullify_set(ctx, a->n);
3960     }
3961     tcg_gen_lookup_and_goto_ptr();
3962     ctx->base.is_jmp = DISAS_NORETURN;
3963     return nullify_end(ctx);
3964 #endif
3965 }
3966 
3967 static bool trans_bl(DisasContext *ctx, arg_bl *a)
3968 {
3969     return do_dbranch(ctx, iaoq_dest(ctx, a->disp), a->l, a->n);
3970 }
3971 
3972 static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
3973 {
3974     uint64_t dest = iaoq_dest(ctx, a->disp);
3975 
3976     nullify_over(ctx);
3977 
3978     /* Make sure the caller hasn't done something weird with the queue.
3979      * ??? This is not quite the same as the PSW[B] bit, which would be
3980      * expensive to track.  Real hardware will trap for
3981      *    b  gateway
3982      *    b  gateway+4  (in delay slot of first branch)
3983      * However, checking for a non-sequential instruction queue *will*
3984      * diagnose the security hole
3985      *    b  gateway
3986      *    b  evil
3987      * in which instructions at evil would run with increased privs.
3988      */
3989     if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
3990         return gen_illegal(ctx);
3991     }
3992 
3993 #ifndef CONFIG_USER_ONLY
3994     if (ctx->tb_flags & PSW_C) {
3995         int type = hppa_artype_for_page(cpu_env(ctx->cs), ctx->base.pc_next);
3996         /* If we could not find a TLB entry, then we need to generate an
3997            ITLB miss exception so the kernel will provide it.
3998            The resulting TLB fill operation will invalidate this TB and
3999            we will re-translate, at which point we *will* be able to find
4000            the TLB entry and determine if this is in fact a gateway page.  */
4001         if (type < 0) {
4002             gen_excp(ctx, EXCP_ITLB_MISS);
4003             return true;
4004         }
4005         /* No change for non-gateway pages or for priv decrease.  */
4006         if (type >= 4 && type - 4 < ctx->privilege) {
4007             dest = deposit64(dest, 0, 2, type - 4);
4008         }
4009     } else {
4010         dest &= -4;  /* priv = 0 */
4011     }
4012 #endif
4013 
4014     if (a->l) {
4015         TCGv_i64 tmp = dest_gpr(ctx, a->l);
4016         if (ctx->privilege < 3) {
4017             tcg_gen_andi_i64(tmp, tmp, -4);
4018         }
4019         tcg_gen_ori_i64(tmp, tmp, ctx->privilege);
4020         save_gpr(ctx, a->l, tmp);
4021     }
4022 
4023     return do_dbranch(ctx, dest, 0, a->n);
4024 }
4025 
4026 static bool trans_blr(DisasContext *ctx, arg_blr *a)
4027 {
4028     if (a->x) {
4029         TCGv_i64 tmp = tcg_temp_new_i64();
4030         tcg_gen_shli_i64(tmp, load_gpr(ctx, a->x), 3);
4031         tcg_gen_addi_i64(tmp, tmp, ctx->iaoq_f + 8);
4032         /* The computation here never changes privilege level.  */
4033         return do_ibranch(ctx, tmp, a->l, a->n);
4034     } else {
4035         /* BLR R0,RX is a good way to load PC+8 into RX.  */
4036         return do_dbranch(ctx, ctx->iaoq_f + 8, a->l, a->n);
4037     }
4038 }
4039 
4040 static bool trans_bv(DisasContext *ctx, arg_bv *a)
4041 {
4042     TCGv_i64 dest;
4043 
4044     if (a->x == 0) {
4045         dest = load_gpr(ctx, a->b);
4046     } else {
4047         dest = tcg_temp_new_i64();
4048         tcg_gen_shli_i64(dest, load_gpr(ctx, a->x), 3);
4049         tcg_gen_add_i64(dest, dest, load_gpr(ctx, a->b));
4050     }
4051     dest = do_ibranch_priv(ctx, dest);
4052     return do_ibranch(ctx, dest, 0, a->n);
4053 }
4054 
4055 static bool trans_bve(DisasContext *ctx, arg_bve *a)
4056 {
4057     TCGv_i64 dest;
4058 
4059 #ifdef CONFIG_USER_ONLY
4060     dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
4061     return do_ibranch(ctx, dest, a->l, a->n);
4062 #else
4063     nullify_over(ctx);
4064     dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
4065 
4066     copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
4067     if (ctx->iaoq_b == -1) {
4068         tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4069     }
4070     copy_iaoq_entry(ctx, cpu_iaoq_b, -1, dest);
4071     tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
4072     if (a->l) {
4073         copy_iaoq_entry(ctx, cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
4074     }
4075     nullify_set(ctx, a->n);
4076     tcg_gen_lookup_and_goto_ptr();
4077     ctx->base.is_jmp = DISAS_NORETURN;
4078     return nullify_end(ctx);
4079 #endif
4080 }
4081 
4082 static bool trans_nopbts(DisasContext *ctx, arg_nopbts *a)
4083 {
4084     /* All branch target stack instructions implement as nop. */
4085     return ctx->is_pa20;
4086 }
4087 
4088 /*
4089  * Float class 0
4090  */
4091 
4092 static void gen_fcpy_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4093 {
4094     tcg_gen_mov_i32(dst, src);
4095 }
4096 
4097 static bool trans_fid_f(DisasContext *ctx, arg_fid_f *a)
4098 {
4099     uint64_t ret;
4100 
4101     if (ctx->is_pa20) {
4102         ret = 0x13080000000000ULL; /* PA8700 (PCX-W2) */
4103     } else {
4104         ret = 0x0f080000000000ULL; /* PA7300LC (PCX-L2) */
4105     }
4106 
4107     nullify_over(ctx);
4108     save_frd(0, tcg_constant_i64(ret));
4109     return nullify_end(ctx);
4110 }
4111 
4112 static bool trans_fcpy_f(DisasContext *ctx, arg_fclass01 *a)
4113 {
4114     return do_fop_wew(ctx, a->t, a->r, gen_fcpy_f);
4115 }
4116 
4117 static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4118 {
4119     tcg_gen_mov_i64(dst, src);
4120 }
4121 
4122 static bool trans_fcpy_d(DisasContext *ctx, arg_fclass01 *a)
4123 {
4124     return do_fop_ded(ctx, a->t, a->r, gen_fcpy_d);
4125 }
4126 
4127 static void gen_fabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4128 {
4129     tcg_gen_andi_i32(dst, src, INT32_MAX);
4130 }
4131 
4132 static bool trans_fabs_f(DisasContext *ctx, arg_fclass01 *a)
4133 {
4134     return do_fop_wew(ctx, a->t, a->r, gen_fabs_f);
4135 }
4136 
4137 static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4138 {
4139     tcg_gen_andi_i64(dst, src, INT64_MAX);
4140 }
4141 
4142 static bool trans_fabs_d(DisasContext *ctx, arg_fclass01 *a)
4143 {
4144     return do_fop_ded(ctx, a->t, a->r, gen_fabs_d);
4145 }
4146 
4147 static bool trans_fsqrt_f(DisasContext *ctx, arg_fclass01 *a)
4148 {
4149     return do_fop_wew(ctx, a->t, a->r, gen_helper_fsqrt_s);
4150 }
4151 
4152 static bool trans_fsqrt_d(DisasContext *ctx, arg_fclass01 *a)
4153 {
4154     return do_fop_ded(ctx, a->t, a->r, gen_helper_fsqrt_d);
4155 }
4156 
4157 static bool trans_frnd_f(DisasContext *ctx, arg_fclass01 *a)
4158 {
4159     return do_fop_wew(ctx, a->t, a->r, gen_helper_frnd_s);
4160 }
4161 
4162 static bool trans_frnd_d(DisasContext *ctx, arg_fclass01 *a)
4163 {
4164     return do_fop_ded(ctx, a->t, a->r, gen_helper_frnd_d);
4165 }
4166 
4167 static void gen_fneg_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4168 {
4169     tcg_gen_xori_i32(dst, src, INT32_MIN);
4170 }
4171 
4172 static bool trans_fneg_f(DisasContext *ctx, arg_fclass01 *a)
4173 {
4174     return do_fop_wew(ctx, a->t, a->r, gen_fneg_f);
4175 }
4176 
4177 static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4178 {
4179     tcg_gen_xori_i64(dst, src, INT64_MIN);
4180 }
4181 
4182 static bool trans_fneg_d(DisasContext *ctx, arg_fclass01 *a)
4183 {
4184     return do_fop_ded(ctx, a->t, a->r, gen_fneg_d);
4185 }
4186 
4187 static void gen_fnegabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4188 {
4189     tcg_gen_ori_i32(dst, src, INT32_MIN);
4190 }
4191 
4192 static bool trans_fnegabs_f(DisasContext *ctx, arg_fclass01 *a)
4193 {
4194     return do_fop_wew(ctx, a->t, a->r, gen_fnegabs_f);
4195 }
4196 
4197 static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4198 {
4199     tcg_gen_ori_i64(dst, src, INT64_MIN);
4200 }
4201 
4202 static bool trans_fnegabs_d(DisasContext *ctx, arg_fclass01 *a)
4203 {
4204     return do_fop_ded(ctx, a->t, a->r, gen_fnegabs_d);
4205 }
4206 
4207 /*
4208  * Float class 1
4209  */
4210 
4211 static bool trans_fcnv_d_f(DisasContext *ctx, arg_fclass01 *a)
4212 {
4213     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_s);
4214 }
4215 
4216 static bool trans_fcnv_f_d(DisasContext *ctx, arg_fclass01 *a)
4217 {
4218     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_d);
4219 }
4220 
4221 static bool trans_fcnv_w_f(DisasContext *ctx, arg_fclass01 *a)
4222 {
4223     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_w_s);
4224 }
4225 
4226 static bool trans_fcnv_q_f(DisasContext *ctx, arg_fclass01 *a)
4227 {
4228     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_dw_s);
4229 }
4230 
4231 static bool trans_fcnv_w_d(DisasContext *ctx, arg_fclass01 *a)
4232 {
4233     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_w_d);
4234 }
4235 
4236 static bool trans_fcnv_q_d(DisasContext *ctx, arg_fclass01 *a)
4237 {
4238     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_dw_d);
4239 }
4240 
4241 static bool trans_fcnv_f_w(DisasContext *ctx, arg_fclass01 *a)
4242 {
4243     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_w);
4244 }
4245 
4246 static bool trans_fcnv_d_w(DisasContext *ctx, arg_fclass01 *a)
4247 {
4248     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_w);
4249 }
4250 
4251 static bool trans_fcnv_f_q(DisasContext *ctx, arg_fclass01 *a)
4252 {
4253     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_dw);
4254 }
4255 
4256 static bool trans_fcnv_d_q(DisasContext *ctx, arg_fclass01 *a)
4257 {
4258     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_dw);
4259 }
4260 
4261 static bool trans_fcnv_t_f_w(DisasContext *ctx, arg_fclass01 *a)
4262 {
4263     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_w);
4264 }
4265 
4266 static bool trans_fcnv_t_d_w(DisasContext *ctx, arg_fclass01 *a)
4267 {
4268     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_w);
4269 }
4270 
4271 static bool trans_fcnv_t_f_q(DisasContext *ctx, arg_fclass01 *a)
4272 {
4273     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_dw);
4274 }
4275 
4276 static bool trans_fcnv_t_d_q(DisasContext *ctx, arg_fclass01 *a)
4277 {
4278     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_dw);
4279 }
4280 
4281 static bool trans_fcnv_uw_f(DisasContext *ctx, arg_fclass01 *a)
4282 {
4283     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_uw_s);
4284 }
4285 
4286 static bool trans_fcnv_uq_f(DisasContext *ctx, arg_fclass01 *a)
4287 {
4288     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_udw_s);
4289 }
4290 
4291 static bool trans_fcnv_uw_d(DisasContext *ctx, arg_fclass01 *a)
4292 {
4293     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_uw_d);
4294 }
4295 
4296 static bool trans_fcnv_uq_d(DisasContext *ctx, arg_fclass01 *a)
4297 {
4298     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_udw_d);
4299 }
4300 
4301 static bool trans_fcnv_f_uw(DisasContext *ctx, arg_fclass01 *a)
4302 {
4303     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_uw);
4304 }
4305 
4306 static bool trans_fcnv_d_uw(DisasContext *ctx, arg_fclass01 *a)
4307 {
4308     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_uw);
4309 }
4310 
4311 static bool trans_fcnv_f_uq(DisasContext *ctx, arg_fclass01 *a)
4312 {
4313     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_udw);
4314 }
4315 
4316 static bool trans_fcnv_d_uq(DisasContext *ctx, arg_fclass01 *a)
4317 {
4318     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_udw);
4319 }
4320 
4321 static bool trans_fcnv_t_f_uw(DisasContext *ctx, arg_fclass01 *a)
4322 {
4323     return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_uw);
4324 }
4325 
4326 static bool trans_fcnv_t_d_uw(DisasContext *ctx, arg_fclass01 *a)
4327 {
4328     return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_uw);
4329 }
4330 
4331 static bool trans_fcnv_t_f_uq(DisasContext *ctx, arg_fclass01 *a)
4332 {
4333     return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_udw);
4334 }
4335 
4336 static bool trans_fcnv_t_d_uq(DisasContext *ctx, arg_fclass01 *a)
4337 {
4338     return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_udw);
4339 }
4340 
4341 /*
4342  * Float class 2
4343  */
4344 
4345 static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
4346 {
4347     TCGv_i32 ta, tb, tc, ty;
4348 
4349     nullify_over(ctx);
4350 
4351     ta = load_frw0_i32(a->r1);
4352     tb = load_frw0_i32(a->r2);
4353     ty = tcg_constant_i32(a->y);
4354     tc = tcg_constant_i32(a->c);
4355 
4356     gen_helper_fcmp_s(tcg_env, ta, tb, ty, tc);
4357 
4358     return nullify_end(ctx);
4359 }
4360 
4361 static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
4362 {
4363     TCGv_i64 ta, tb;
4364     TCGv_i32 tc, ty;
4365 
4366     nullify_over(ctx);
4367 
4368     ta = load_frd0(a->r1);
4369     tb = load_frd0(a->r2);
4370     ty = tcg_constant_i32(a->y);
4371     tc = tcg_constant_i32(a->c);
4372 
4373     gen_helper_fcmp_d(tcg_env, ta, tb, ty, tc);
4374 
4375     return nullify_end(ctx);
4376 }
4377 
4378 static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
4379 {
4380     TCGv_i64 t;
4381 
4382     nullify_over(ctx);
4383 
4384     t = tcg_temp_new_i64();
4385     tcg_gen_ld32u_i64(t, tcg_env, offsetof(CPUHPPAState, fr0_shadow));
4386 
4387     if (a->y == 1) {
4388         int mask;
4389         bool inv = false;
4390 
4391         switch (a->c) {
4392         case 0: /* simple */
4393             tcg_gen_andi_i64(t, t, 0x4000000);
4394             ctx->null_cond = cond_make_0(TCG_COND_NE, t);
4395             goto done;
4396         case 2: /* rej */
4397             inv = true;
4398             /* fallthru */
4399         case 1: /* acc */
4400             mask = 0x43ff800;
4401             break;
4402         case 6: /* rej8 */
4403             inv = true;
4404             /* fallthru */
4405         case 5: /* acc8 */
4406             mask = 0x43f8000;
4407             break;
4408         case 9: /* acc6 */
4409             mask = 0x43e0000;
4410             break;
4411         case 13: /* acc4 */
4412             mask = 0x4380000;
4413             break;
4414         case 17: /* acc2 */
4415             mask = 0x4200000;
4416             break;
4417         default:
4418             gen_illegal(ctx);
4419             return true;
4420         }
4421         if (inv) {
4422             TCGv_i64 c = tcg_constant_i64(mask);
4423             tcg_gen_or_i64(t, t, c);
4424             ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
4425         } else {
4426             tcg_gen_andi_i64(t, t, mask);
4427             ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
4428         }
4429     } else {
4430         unsigned cbit = (a->y ^ 1) - 1;
4431 
4432         tcg_gen_extract_i64(t, t, 21 - cbit, 1);
4433         ctx->null_cond = cond_make_0(TCG_COND_NE, t);
4434     }
4435 
4436  done:
4437     return nullify_end(ctx);
4438 }
4439 
4440 /*
4441  * Float class 2
4442  */
4443 
4444 static bool trans_fadd_f(DisasContext *ctx, arg_fclass3 *a)
4445 {
4446     return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fadd_s);
4447 }
4448 
4449 static bool trans_fadd_d(DisasContext *ctx, arg_fclass3 *a)
4450 {
4451     return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fadd_d);
4452 }
4453 
4454 static bool trans_fsub_f(DisasContext *ctx, arg_fclass3 *a)
4455 {
4456     return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fsub_s);
4457 }
4458 
4459 static bool trans_fsub_d(DisasContext *ctx, arg_fclass3 *a)
4460 {
4461     return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fsub_d);
4462 }
4463 
4464 static bool trans_fmpy_f(DisasContext *ctx, arg_fclass3 *a)
4465 {
4466     return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_s);
4467 }
4468 
4469 static bool trans_fmpy_d(DisasContext *ctx, arg_fclass3 *a)
4470 {
4471     return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_d);
4472 }
4473 
4474 static bool trans_fdiv_f(DisasContext *ctx, arg_fclass3 *a)
4475 {
4476     return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_s);
4477 }
4478 
4479 static bool trans_fdiv_d(DisasContext *ctx, arg_fclass3 *a)
4480 {
4481     return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_d);
4482 }
4483 
4484 static bool trans_xmpyu(DisasContext *ctx, arg_xmpyu *a)
4485 {
4486     TCGv_i64 x, y;
4487 
4488     nullify_over(ctx);
4489 
4490     x = load_frw0_i64(a->r1);
4491     y = load_frw0_i64(a->r2);
4492     tcg_gen_mul_i64(x, x, y);
4493     save_frd(a->t, x);
4494 
4495     return nullify_end(ctx);
4496 }
4497 
4498 /* Convert the fmpyadd single-precision register encodings to standard.  */
4499 static inline int fmpyadd_s_reg(unsigned r)
4500 {
4501     return (r & 16) * 2 + 16 + (r & 15);
4502 }
4503 
4504 static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4505 {
4506     int tm = fmpyadd_s_reg(a->tm);
4507     int ra = fmpyadd_s_reg(a->ra);
4508     int ta = fmpyadd_s_reg(a->ta);
4509     int rm2 = fmpyadd_s_reg(a->rm2);
4510     int rm1 = fmpyadd_s_reg(a->rm1);
4511 
4512     nullify_over(ctx);
4513 
4514     do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
4515     do_fop_weww(ctx, ta, ta, ra,
4516                 is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
4517 
4518     return nullify_end(ctx);
4519 }
4520 
4521 static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
4522 {
4523     return do_fmpyadd_s(ctx, a, false);
4524 }
4525 
4526 static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
4527 {
4528     return do_fmpyadd_s(ctx, a, true);
4529 }
4530 
4531 static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4532 {
4533     nullify_over(ctx);
4534 
4535     do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
4536     do_fop_dedd(ctx, a->ta, a->ta, a->ra,
4537                 is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
4538 
4539     return nullify_end(ctx);
4540 }
4541 
4542 static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
4543 {
4544     return do_fmpyadd_d(ctx, a, false);
4545 }
4546 
4547 static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
4548 {
4549     return do_fmpyadd_d(ctx, a, true);
4550 }
4551 
4552 static bool trans_fmpyfadd_f(DisasContext *ctx, arg_fmpyfadd_f *a)
4553 {
4554     TCGv_i32 x, y, z;
4555 
4556     nullify_over(ctx);
4557     x = load_frw0_i32(a->rm1);
4558     y = load_frw0_i32(a->rm2);
4559     z = load_frw0_i32(a->ra3);
4560 
4561     if (a->neg) {
4562         gen_helper_fmpynfadd_s(x, tcg_env, x, y, z);
4563     } else {
4564         gen_helper_fmpyfadd_s(x, tcg_env, x, y, z);
4565     }
4566 
4567     save_frw_i32(a->t, x);
4568     return nullify_end(ctx);
4569 }
4570 
4571 static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
4572 {
4573     TCGv_i64 x, y, z;
4574 
4575     nullify_over(ctx);
4576     x = load_frd0(a->rm1);
4577     y = load_frd0(a->rm2);
4578     z = load_frd0(a->ra3);
4579 
4580     if (a->neg) {
4581         gen_helper_fmpynfadd_d(x, tcg_env, x, y, z);
4582     } else {
4583         gen_helper_fmpyfadd_d(x, tcg_env, x, y, z);
4584     }
4585 
4586     save_frd(a->t, x);
4587     return nullify_end(ctx);
4588 }
4589 
4590 /* Emulate PDC BTLB, called by SeaBIOS-hppa */
4591 static bool trans_diag_btlb(DisasContext *ctx, arg_diag_btlb *a)
4592 {
4593     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4594 #ifndef CONFIG_USER_ONLY
4595     nullify_over(ctx);
4596     gen_helper_diag_btlb(tcg_env);
4597     return nullify_end(ctx);
4598 #endif
4599 }
4600 
4601 /* Print char in %r26 to first serial console, used by SeaBIOS-hppa */
4602 static bool trans_diag_cout(DisasContext *ctx, arg_diag_cout *a)
4603 {
4604     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4605 #ifndef CONFIG_USER_ONLY
4606     nullify_over(ctx);
4607     gen_helper_diag_console_output(tcg_env);
4608     return nullify_end(ctx);
4609 #endif
4610 }
4611 
4612 static bool trans_diag_getshadowregs_pa1(DisasContext *ctx, arg_empty *a)
4613 {
4614     return !ctx->is_pa20 && do_getshadowregs(ctx);
4615 }
4616 
4617 static bool trans_diag_getshadowregs_pa2(DisasContext *ctx, arg_empty *a)
4618 {
4619     return ctx->is_pa20 && do_getshadowregs(ctx);
4620 }
4621 
4622 static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a)
4623 {
4624     return !ctx->is_pa20 && do_putshadowregs(ctx);
4625 }
4626 
4627 static bool trans_diag_putshadowregs_pa2(DisasContext *ctx, arg_empty *a)
4628 {
4629     return ctx->is_pa20 && do_putshadowregs(ctx);
4630 }
4631 
4632 static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a)
4633 {
4634     CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
4635     qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
4636     return true;
4637 }
4638 
4639 static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4640 {
4641     DisasContext *ctx = container_of(dcbase, DisasContext, base);
4642     int bound;
4643 
4644     ctx->cs = cs;
4645     ctx->tb_flags = ctx->base.tb->flags;
4646     ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
4647 
4648 #ifdef CONFIG_USER_ONLY
4649     ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX);
4650     ctx->mmu_idx = MMU_USER_IDX;
4651     ctx->iaoq_f = ctx->base.pc_first | ctx->privilege;
4652     ctx->iaoq_b = ctx->base.tb->cs_base | ctx->privilege;
4653     ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
4654 #else
4655     ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
4656     ctx->mmu_idx = (ctx->tb_flags & PSW_D
4657                     ? PRIV_P_TO_MMU_IDX(ctx->privilege, ctx->tb_flags & PSW_P)
4658                     : ctx->tb_flags & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
4659 
4660     /* Recover the IAOQ values from the GVA + PRIV.  */
4661     uint64_t cs_base = ctx->base.tb->cs_base;
4662     uint64_t iasq_f = cs_base & ~0xffffffffull;
4663     int32_t diff = cs_base;
4664 
4665     ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
4666     ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
4667 #endif
4668     ctx->iaoq_n = -1;
4669     ctx->iaoq_n_var = NULL;
4670 
4671     ctx->zero = tcg_constant_i64(0);
4672 
4673     /* Bound the number of instructions by those left on the page.  */
4674     bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
4675     ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
4676 }
4677 
4678 static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
4679 {
4680     DisasContext *ctx = container_of(dcbase, DisasContext, base);
4681 
4682     /* Seed the nullification status from PSW[N], as saved in TB->FLAGS.  */
4683     ctx->null_cond = cond_make_f();
4684     ctx->psw_n_nonzero = false;
4685     if (ctx->tb_flags & PSW_N) {
4686         ctx->null_cond.c = TCG_COND_ALWAYS;
4687         ctx->psw_n_nonzero = true;
4688     }
4689     ctx->null_lab = NULL;
4690 }
4691 
4692 static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
4693 {
4694     DisasContext *ctx = container_of(dcbase, DisasContext, base);
4695 
4696     tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b, 0);
4697     ctx->insn_start_updated = false;
4698 }
4699 
4700 static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
4701 {
4702     DisasContext *ctx = container_of(dcbase, DisasContext, base);
4703     CPUHPPAState *env = cpu_env(cs);
4704     DisasJumpType ret;
4705 
4706     /* Execute one insn.  */
4707 #ifdef CONFIG_USER_ONLY
4708     if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
4709         do_page_zero(ctx);
4710         ret = ctx->base.is_jmp;
4711         assert(ret != DISAS_NEXT);
4712     } else
4713 #endif
4714     {
4715         /* Always fetch the insn, even if nullified, so that we check
4716            the page permissions for execute.  */
4717         uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next);
4718 
4719         /* Set up the IA queue for the next insn.
4720            This will be overwritten by a branch.  */
4721         if (ctx->iaoq_b == -1) {
4722             ctx->iaoq_n = -1;
4723             ctx->iaoq_n_var = tcg_temp_new_i64();
4724             tcg_gen_addi_i64(ctx->iaoq_n_var, cpu_iaoq_b, 4);
4725         } else {
4726             ctx->iaoq_n = ctx->iaoq_b + 4;
4727             ctx->iaoq_n_var = NULL;
4728         }
4729 
4730         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
4731             ctx->null_cond.c = TCG_COND_NEVER;
4732             ret = DISAS_NEXT;
4733         } else {
4734             ctx->insn = insn;
4735             if (!decode(ctx, insn)) {
4736                 gen_illegal(ctx);
4737             }
4738             ret = ctx->base.is_jmp;
4739             assert(ctx->null_lab == NULL);
4740         }
4741     }
4742 
4743     /* Advance the insn queue.  Note that this check also detects
4744        a priority change within the instruction queue.  */
4745     if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
4746         if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1
4747             && use_goto_tb(ctx, ctx->iaoq_b)
4748             && (ctx->null_cond.c == TCG_COND_NEVER
4749                 || ctx->null_cond.c == TCG_COND_ALWAYS)) {
4750             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
4751             gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
4752             ctx->base.is_jmp = ret = DISAS_NORETURN;
4753         } else {
4754             ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
4755         }
4756     }
4757     ctx->iaoq_f = ctx->iaoq_b;
4758     ctx->iaoq_b = ctx->iaoq_n;
4759     ctx->base.pc_next += 4;
4760 
4761     switch (ret) {
4762     case DISAS_NORETURN:
4763     case DISAS_IAQ_N_UPDATED:
4764         break;
4765 
4766     case DISAS_NEXT:
4767     case DISAS_IAQ_N_STALE:
4768     case DISAS_IAQ_N_STALE_EXIT:
4769         if (ctx->iaoq_f == -1) {
4770             copy_iaoq_entry(ctx, cpu_iaoq_f, -1, cpu_iaoq_b);
4771             copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4772 #ifndef CONFIG_USER_ONLY
4773             tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4774 #endif
4775             nullify_save(ctx);
4776             ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
4777                                 ? DISAS_EXIT
4778                                 : DISAS_IAQ_N_UPDATED);
4779         } else if (ctx->iaoq_b == -1) {
4780             copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
4781         }
4782         break;
4783 
4784     default:
4785         g_assert_not_reached();
4786     }
4787 }
4788 
4789 static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
4790 {
4791     DisasContext *ctx = container_of(dcbase, DisasContext, base);
4792     DisasJumpType is_jmp = ctx->base.is_jmp;
4793 
4794     switch (is_jmp) {
4795     case DISAS_NORETURN:
4796         break;
4797     case DISAS_TOO_MANY:
4798     case DISAS_IAQ_N_STALE:
4799     case DISAS_IAQ_N_STALE_EXIT:
4800         copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4801         copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4802         nullify_save(ctx);
4803         /* FALLTHRU */
4804     case DISAS_IAQ_N_UPDATED:
4805         if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
4806             tcg_gen_lookup_and_goto_ptr();
4807             break;
4808         }
4809         /* FALLTHRU */
4810     case DISAS_EXIT:
4811         tcg_gen_exit_tb(NULL, 0);
4812         break;
4813     default:
4814         g_assert_not_reached();
4815     }
4816 }
4817 
4818 static void hppa_tr_disas_log(const DisasContextBase *dcbase,
4819                               CPUState *cs, FILE *logfile)
4820 {
4821     target_ulong pc = dcbase->pc_first;
4822 
4823 #ifdef CONFIG_USER_ONLY
4824     switch (pc) {
4825     case 0x00:
4826         fprintf(logfile, "IN:\n0x00000000:  (null)\n");
4827         return;
4828     case 0xb0:
4829         fprintf(logfile, "IN:\n0x000000b0:  light-weight-syscall\n");
4830         return;
4831     case 0xe0:
4832         fprintf(logfile, "IN:\n0x000000e0:  set-thread-pointer-syscall\n");
4833         return;
4834     case 0x100:
4835         fprintf(logfile, "IN:\n0x00000100:  syscall\n");
4836         return;
4837     }
4838 #endif
4839 
4840     fprintf(logfile, "IN: %s\n", lookup_symbol(pc));
4841     target_disas(logfile, cs, pc, dcbase->tb->size);
4842 }
4843 
4844 static const TranslatorOps hppa_tr_ops = {
4845     .init_disas_context = hppa_tr_init_disas_context,
4846     .tb_start           = hppa_tr_tb_start,
4847     .insn_start         = hppa_tr_insn_start,
4848     .translate_insn     = hppa_tr_translate_insn,
4849     .tb_stop            = hppa_tr_tb_stop,
4850     .disas_log          = hppa_tr_disas_log,
4851 };
4852 
4853 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
4854                            vaddr pc, void *host_pc)
4855 {
4856     DisasContext ctx;
4857     translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
4858 }
4859