xref: /openbmc/qemu/target/hppa/translate.c (revision 083fab02)
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 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-op.h"
26 #include "exec/cpu_ldst.h"
27 #include "exec/helper-proto.h"
28 #include "exec/helper-gen.h"
29 #include "exec/translator.h"
30 #include "trace-tcg.h"
31 #include "exec/log.h"
32 
33 typedef struct DisasCond {
34     TCGCond c;
35     TCGv a0, a1;
36     bool a0_is_n;
37     bool a1_is_0;
38 } DisasCond;
39 
40 typedef struct DisasContext {
41     DisasContextBase base;
42     CPUState *cs;
43 
44     target_ulong iaoq_f;
45     target_ulong iaoq_b;
46     target_ulong iaoq_n;
47     TCGv iaoq_n_var;
48 
49     int ntemps;
50     TCGv temps[8];
51 
52     DisasCond null_cond;
53     TCGLabel *null_lab;
54 
55     bool psw_n_nonzero;
56 } DisasContext;
57 
58 /* Target-specific return values from translate_one, indicating the
59    state of the TB.  Note that DISAS_NEXT indicates that we are not
60    exiting the TB.  */
61 
62 /* We are not using a goto_tb (for whatever reason), but have updated
63    the iaq (for whatever reason), so don't do it again on exit.  */
64 #define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
65 
66 /* We are exiting the TB, but have neither emitted a goto_tb, nor
67    updated the iaq for the next instruction to be executed.  */
68 #define DISAS_IAQ_N_STALE    DISAS_TARGET_1
69 
70 typedef struct DisasInsn {
71     uint32_t insn, mask;
72     DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
73                            const struct DisasInsn *f);
74     union {
75         void (*ttt)(TCGv, TCGv, TCGv);
76         void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32);
77         void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64);
78         void (*wew)(TCGv_i32, TCGv_env, TCGv_i32);
79         void (*ded)(TCGv_i64, TCGv_env, TCGv_i64);
80         void (*wed)(TCGv_i32, TCGv_env, TCGv_i64);
81         void (*dew)(TCGv_i64, TCGv_env, TCGv_i32);
82     } f;
83 } DisasInsn;
84 
85 /* global register indexes */
86 static TCGv_env cpu_env;
87 static TCGv cpu_gr[32];
88 static TCGv cpu_iaoq_f;
89 static TCGv cpu_iaoq_b;
90 static TCGv cpu_sar;
91 static TCGv cpu_psw_n;
92 static TCGv cpu_psw_v;
93 static TCGv cpu_psw_cb;
94 static TCGv cpu_psw_cb_msb;
95 static TCGv cpu_cr26;
96 static TCGv cpu_cr27;
97 
98 #include "exec/gen-icount.h"
99 
100 void hppa_translate_init(void)
101 {
102 #define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
103 
104     typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
105     static const GlobalVar vars[] = {
106         DEF_VAR(sar),
107         DEF_VAR(cr26),
108         DEF_VAR(cr27),
109         DEF_VAR(psw_n),
110         DEF_VAR(psw_v),
111         DEF_VAR(psw_cb),
112         DEF_VAR(psw_cb_msb),
113         DEF_VAR(iaoq_f),
114         DEF_VAR(iaoq_b),
115     };
116 
117 #undef DEF_VAR
118 
119     /* Use the symbolic register names that match the disassembler.  */
120     static const char gr_names[32][4] = {
121         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
122         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
123         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
124         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
125     };
126 
127     static bool done_init = 0;
128     int i;
129 
130     if (done_init) {
131         return;
132     }
133     done_init = 1;
134 
135     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
136     tcg_ctx.tcg_env = cpu_env;
137 
138     TCGV_UNUSED(cpu_gr[0]);
139     for (i = 1; i < 32; i++) {
140         cpu_gr[i] = tcg_global_mem_new(cpu_env,
141                                        offsetof(CPUHPPAState, gr[i]),
142                                        gr_names[i]);
143     }
144 
145     for (i = 0; i < ARRAY_SIZE(vars); ++i) {
146         const GlobalVar *v = &vars[i];
147         *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name);
148     }
149 }
150 
151 static DisasCond cond_make_f(void)
152 {
153     DisasCond r = { .c = TCG_COND_NEVER };
154     TCGV_UNUSED(r.a0);
155     TCGV_UNUSED(r.a1);
156     return r;
157 }
158 
159 static DisasCond cond_make_n(void)
160 {
161     DisasCond r = { .c = TCG_COND_NE, .a0_is_n = true, .a1_is_0 = true };
162     r.a0 = cpu_psw_n;
163     TCGV_UNUSED(r.a1);
164     return r;
165 }
166 
167 static DisasCond cond_make_0(TCGCond c, TCGv a0)
168 {
169     DisasCond r = { .c = c, .a1_is_0 = true };
170 
171     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
172     r.a0 = tcg_temp_new();
173     tcg_gen_mov_tl(r.a0, a0);
174     TCGV_UNUSED(r.a1);
175 
176     return r;
177 }
178 
179 static DisasCond cond_make(TCGCond c, TCGv a0, TCGv a1)
180 {
181     DisasCond r = { .c = c };
182 
183     assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
184     r.a0 = tcg_temp_new();
185     tcg_gen_mov_tl(r.a0, a0);
186     r.a1 = tcg_temp_new();
187     tcg_gen_mov_tl(r.a1, a1);
188 
189     return r;
190 }
191 
192 static void cond_prep(DisasCond *cond)
193 {
194     if (cond->a1_is_0) {
195         cond->a1_is_0 = false;
196         cond->a1 = tcg_const_tl(0);
197     }
198 }
199 
200 static void cond_free(DisasCond *cond)
201 {
202     switch (cond->c) {
203     default:
204         if (!cond->a0_is_n) {
205             tcg_temp_free(cond->a0);
206         }
207         if (!cond->a1_is_0) {
208             tcg_temp_free(cond->a1);
209         }
210         cond->a0_is_n = false;
211         cond->a1_is_0 = false;
212         TCGV_UNUSED(cond->a0);
213         TCGV_UNUSED(cond->a1);
214         /* fallthru */
215     case TCG_COND_ALWAYS:
216         cond->c = TCG_COND_NEVER;
217         break;
218     case TCG_COND_NEVER:
219         break;
220     }
221 }
222 
223 static TCGv get_temp(DisasContext *ctx)
224 {
225     unsigned i = ctx->ntemps++;
226     g_assert(i < ARRAY_SIZE(ctx->temps));
227     return ctx->temps[i] = tcg_temp_new();
228 }
229 
230 static TCGv load_const(DisasContext *ctx, target_long v)
231 {
232     TCGv t = get_temp(ctx);
233     tcg_gen_movi_tl(t, v);
234     return t;
235 }
236 
237 static TCGv load_gpr(DisasContext *ctx, unsigned reg)
238 {
239     if (reg == 0) {
240         TCGv t = get_temp(ctx);
241         tcg_gen_movi_tl(t, 0);
242         return t;
243     } else {
244         return cpu_gr[reg];
245     }
246 }
247 
248 static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
249 {
250     if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
251         return get_temp(ctx);
252     } else {
253         return cpu_gr[reg];
254     }
255 }
256 
257 static void save_or_nullify(DisasContext *ctx, TCGv dest, TCGv t)
258 {
259     if (ctx->null_cond.c != TCG_COND_NEVER) {
260         cond_prep(&ctx->null_cond);
261         tcg_gen_movcond_tl(ctx->null_cond.c, dest, ctx->null_cond.a0,
262                            ctx->null_cond.a1, dest, t);
263     } else {
264         tcg_gen_mov_tl(dest, t);
265     }
266 }
267 
268 static void save_gpr(DisasContext *ctx, unsigned reg, TCGv t)
269 {
270     if (reg != 0) {
271         save_or_nullify(ctx, cpu_gr[reg], t);
272     }
273 }
274 
275 #ifdef HOST_WORDS_BIGENDIAN
276 # define HI_OFS  0
277 # define LO_OFS  4
278 #else
279 # define HI_OFS  4
280 # define LO_OFS  0
281 #endif
282 
283 static TCGv_i32 load_frw_i32(unsigned rt)
284 {
285     TCGv_i32 ret = tcg_temp_new_i32();
286     tcg_gen_ld_i32(ret, cpu_env,
287                    offsetof(CPUHPPAState, fr[rt & 31])
288                    + (rt & 32 ? LO_OFS : HI_OFS));
289     return ret;
290 }
291 
292 static TCGv_i32 load_frw0_i32(unsigned rt)
293 {
294     if (rt == 0) {
295         return tcg_const_i32(0);
296     } else {
297         return load_frw_i32(rt);
298     }
299 }
300 
301 static TCGv_i64 load_frw0_i64(unsigned rt)
302 {
303     if (rt == 0) {
304         return tcg_const_i64(0);
305     } else {
306         TCGv_i64 ret = tcg_temp_new_i64();
307         tcg_gen_ld32u_i64(ret, cpu_env,
308                           offsetof(CPUHPPAState, fr[rt & 31])
309                           + (rt & 32 ? LO_OFS : HI_OFS));
310         return ret;
311     }
312 }
313 
314 static void save_frw_i32(unsigned rt, TCGv_i32 val)
315 {
316     tcg_gen_st_i32(val, cpu_env,
317                    offsetof(CPUHPPAState, fr[rt & 31])
318                    + (rt & 32 ? LO_OFS : HI_OFS));
319 }
320 
321 #undef HI_OFS
322 #undef LO_OFS
323 
324 static TCGv_i64 load_frd(unsigned rt)
325 {
326     TCGv_i64 ret = tcg_temp_new_i64();
327     tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt]));
328     return ret;
329 }
330 
331 static TCGv_i64 load_frd0(unsigned rt)
332 {
333     if (rt == 0) {
334         return tcg_const_i64(0);
335     } else {
336         return load_frd(rt);
337     }
338 }
339 
340 static void save_frd(unsigned rt, TCGv_i64 val)
341 {
342     tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
343 }
344 
345 /* Skip over the implementation of an insn that has been nullified.
346    Use this when the insn is too complex for a conditional move.  */
347 static void nullify_over(DisasContext *ctx)
348 {
349     if (ctx->null_cond.c != TCG_COND_NEVER) {
350         /* The always condition should have been handled in the main loop.  */
351         assert(ctx->null_cond.c != TCG_COND_ALWAYS);
352 
353         ctx->null_lab = gen_new_label();
354         cond_prep(&ctx->null_cond);
355 
356         /* If we're using PSW[N], copy it to a temp because... */
357         if (ctx->null_cond.a0_is_n) {
358             ctx->null_cond.a0_is_n = false;
359             ctx->null_cond.a0 = tcg_temp_new();
360             tcg_gen_mov_tl(ctx->null_cond.a0, cpu_psw_n);
361         }
362         /* ... we clear it before branching over the implementation,
363            so that (1) it's clear after nullifying this insn and
364            (2) if this insn nullifies the next, PSW[N] is valid.  */
365         if (ctx->psw_n_nonzero) {
366             ctx->psw_n_nonzero = false;
367             tcg_gen_movi_tl(cpu_psw_n, 0);
368         }
369 
370         tcg_gen_brcond_tl(ctx->null_cond.c, ctx->null_cond.a0,
371                           ctx->null_cond.a1, ctx->null_lab);
372         cond_free(&ctx->null_cond);
373     }
374 }
375 
376 /* Save the current nullification state to PSW[N].  */
377 static void nullify_save(DisasContext *ctx)
378 {
379     if (ctx->null_cond.c == TCG_COND_NEVER) {
380         if (ctx->psw_n_nonzero) {
381             tcg_gen_movi_tl(cpu_psw_n, 0);
382         }
383         return;
384     }
385     if (!ctx->null_cond.a0_is_n) {
386         cond_prep(&ctx->null_cond);
387         tcg_gen_setcond_tl(ctx->null_cond.c, cpu_psw_n,
388                            ctx->null_cond.a0, ctx->null_cond.a1);
389         ctx->psw_n_nonzero = true;
390     }
391     cond_free(&ctx->null_cond);
392 }
393 
394 /* Set a PSW[N] to X.  The intention is that this is used immediately
395    before a goto_tb/exit_tb, so that there is no fallthru path to other
396    code within the TB.  Therefore we do not update psw_n_nonzero.  */
397 static void nullify_set(DisasContext *ctx, bool x)
398 {
399     if (ctx->psw_n_nonzero || x) {
400         tcg_gen_movi_tl(cpu_psw_n, x);
401     }
402 }
403 
404 /* Mark the end of an instruction that may have been nullified.
405    This is the pair to nullify_over.  */
406 static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
407 {
408     TCGLabel *null_lab = ctx->null_lab;
409 
410     if (likely(null_lab == NULL)) {
411         /* The current insn wasn't conditional or handled the condition
412            applied to it without a branch, so the (new) setting of
413            NULL_COND can be applied directly to the next insn.  */
414         return status;
415     }
416     ctx->null_lab = NULL;
417 
418     if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
419         /* The next instruction will be unconditional,
420            and NULL_COND already reflects that.  */
421         gen_set_label(null_lab);
422     } else {
423         /* The insn that we just executed is itself nullifying the next
424            instruction.  Store the condition in the PSW[N] global.
425            We asserted PSW[N] = 0 in nullify_over, so that after the
426            label we have the proper value in place.  */
427         nullify_save(ctx);
428         gen_set_label(null_lab);
429         ctx->null_cond = cond_make_n();
430     }
431 
432     assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED);
433     if (status == DISAS_NORETURN) {
434         status = DISAS_NEXT;
435     }
436     return status;
437 }
438 
439 static void copy_iaoq_entry(TCGv dest, target_ulong ival, TCGv vval)
440 {
441     if (unlikely(ival == -1)) {
442         tcg_gen_mov_tl(dest, vval);
443     } else {
444         tcg_gen_movi_tl(dest, ival);
445     }
446 }
447 
448 static inline target_ulong iaoq_dest(DisasContext *ctx, target_long disp)
449 {
450     return ctx->iaoq_f + disp + 8;
451 }
452 
453 static void gen_excp_1(int exception)
454 {
455     TCGv_i32 t = tcg_const_i32(exception);
456     gen_helper_excp(cpu_env, t);
457     tcg_temp_free_i32(t);
458 }
459 
460 static DisasJumpType gen_excp(DisasContext *ctx, int exception)
461 {
462     copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
463     copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
464     nullify_save(ctx);
465     gen_excp_1(exception);
466     return DISAS_NORETURN;
467 }
468 
469 static DisasJumpType gen_illegal(DisasContext *ctx)
470 {
471     nullify_over(ctx);
472     return nullify_end(ctx, gen_excp(ctx, EXCP_SIGILL));
473 }
474 
475 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
476 {
477     /* Suppress goto_tb in the case of single-steping and IO.  */
478     if ((ctx->base.tb->cflags & CF_LAST_IO) || ctx->base.singlestep_enabled) {
479         return false;
480     }
481     return true;
482 }
483 
484 /* If the next insn is to be nullified, and it's on the same page,
485    and we're not attempting to set a breakpoint on it, then we can
486    totally skip the nullified insn.  This avoids creating and
487    executing a TB that merely branches to the next TB.  */
488 static bool use_nullify_skip(DisasContext *ctx)
489 {
490     return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
491             && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
492 }
493 
494 static void gen_goto_tb(DisasContext *ctx, int which,
495                         target_ulong f, target_ulong b)
496 {
497     if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
498         tcg_gen_goto_tb(which);
499         tcg_gen_movi_tl(cpu_iaoq_f, f);
500         tcg_gen_movi_tl(cpu_iaoq_b, b);
501         tcg_gen_exit_tb((uintptr_t)ctx->base.tb + which);
502     } else {
503         copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
504         copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
505         if (ctx->base.singlestep_enabled) {
506             gen_excp_1(EXCP_DEBUG);
507         } else {
508             tcg_gen_lookup_and_goto_ptr();
509         }
510     }
511 }
512 
513 /* PA has a habit of taking the LSB of a field and using that as the sign,
514    with the rest of the field becoming the least significant bits.  */
515 static target_long low_sextract(uint32_t val, int pos, int len)
516 {
517     target_ulong x = -(target_ulong)extract32(val, pos, 1);
518     x = (x << (len - 1)) | extract32(val, pos + 1, len - 1);
519     return x;
520 }
521 
522 static unsigned assemble_rt64(uint32_t insn)
523 {
524     unsigned r1 = extract32(insn, 6, 1);
525     unsigned r0 = extract32(insn, 0, 5);
526     return r1 * 32 + r0;
527 }
528 
529 static unsigned assemble_ra64(uint32_t insn)
530 {
531     unsigned r1 = extract32(insn, 7, 1);
532     unsigned r0 = extract32(insn, 21, 5);
533     return r1 * 32 + r0;
534 }
535 
536 static unsigned assemble_rb64(uint32_t insn)
537 {
538     unsigned r1 = extract32(insn, 12, 1);
539     unsigned r0 = extract32(insn, 16, 5);
540     return r1 * 32 + r0;
541 }
542 
543 static unsigned assemble_rc64(uint32_t insn)
544 {
545     unsigned r2 = extract32(insn, 8, 1);
546     unsigned r1 = extract32(insn, 13, 3);
547     unsigned r0 = extract32(insn, 9, 2);
548     return r2 * 32 + r1 * 4 + r0;
549 }
550 
551 static target_long assemble_12(uint32_t insn)
552 {
553     target_ulong x = -(target_ulong)(insn & 1);
554     x = (x <<  1) | extract32(insn, 2, 1);
555     x = (x << 10) | extract32(insn, 3, 10);
556     return x;
557 }
558 
559 static target_long assemble_16(uint32_t insn)
560 {
561     /* Take the name from PA2.0, which produces a 16-bit number
562        only with wide mode; otherwise a 14-bit number.  Since we don't
563        implement wide mode, this is always the 14-bit number.  */
564     return low_sextract(insn, 0, 14);
565 }
566 
567 static target_long assemble_16a(uint32_t insn)
568 {
569     /* Take the name from PA2.0, which produces a 14-bit shifted number
570        only with wide mode; otherwise a 12-bit shifted number.  Since we
571        don't implement wide mode, this is always the 12-bit number.  */
572     target_ulong x = -(target_ulong)(insn & 1);
573     x = (x << 11) | extract32(insn, 2, 11);
574     return x << 2;
575 }
576 
577 static target_long assemble_17(uint32_t insn)
578 {
579     target_ulong x = -(target_ulong)(insn & 1);
580     x = (x <<  5) | extract32(insn, 16, 5);
581     x = (x <<  1) | extract32(insn, 2, 1);
582     x = (x << 10) | extract32(insn, 3, 10);
583     return x << 2;
584 }
585 
586 static target_long assemble_21(uint32_t insn)
587 {
588     target_ulong x = -(target_ulong)(insn & 1);
589     x = (x << 11) | extract32(insn, 1, 11);
590     x = (x <<  2) | extract32(insn, 14, 2);
591     x = (x <<  5) | extract32(insn, 16, 5);
592     x = (x <<  2) | extract32(insn, 12, 2);
593     return x << 11;
594 }
595 
596 static target_long assemble_22(uint32_t insn)
597 {
598     target_ulong x = -(target_ulong)(insn & 1);
599     x = (x << 10) | extract32(insn, 16, 10);
600     x = (x <<  1) | extract32(insn, 2, 1);
601     x = (x << 10) | extract32(insn, 3, 10);
602     return x << 2;
603 }
604 
605 /* The parisc documentation describes only the general interpretation of
606    the conditions, without describing their exact implementation.  The
607    interpretations do not stand up well when considering ADD,C and SUB,B.
608    However, considering the Addition, Subtraction and Logical conditions
609    as a whole it would appear that these relations are similar to what
610    a traditional NZCV set of flags would produce.  */
611 
612 static DisasCond do_cond(unsigned cf, TCGv res, TCGv cb_msb, TCGv sv)
613 {
614     DisasCond cond;
615     TCGv tmp;
616 
617     switch (cf >> 1) {
618     case 0: /* Never / TR */
619         cond = cond_make_f();
620         break;
621     case 1: /* = / <>        (Z / !Z) */
622         cond = cond_make_0(TCG_COND_EQ, res);
623         break;
624     case 2: /* < / >=        (N / !N) */
625         cond = cond_make_0(TCG_COND_LT, res);
626         break;
627     case 3: /* <= / >        (N | Z / !N & !Z) */
628         cond = cond_make_0(TCG_COND_LE, res);
629         break;
630     case 4: /* NUV / UV      (!C / C) */
631         cond = cond_make_0(TCG_COND_EQ, cb_msb);
632         break;
633     case 5: /* ZNV / VNZ     (!C | Z / C & !Z) */
634         tmp = tcg_temp_new();
635         tcg_gen_neg_tl(tmp, cb_msb);
636         tcg_gen_and_tl(tmp, tmp, res);
637         cond = cond_make_0(TCG_COND_EQ, tmp);
638         tcg_temp_free(tmp);
639         break;
640     case 6: /* SV / NSV      (V / !V) */
641         cond = cond_make_0(TCG_COND_LT, sv);
642         break;
643     case 7: /* OD / EV */
644         tmp = tcg_temp_new();
645         tcg_gen_andi_tl(tmp, res, 1);
646         cond = cond_make_0(TCG_COND_NE, tmp);
647         tcg_temp_free(tmp);
648         break;
649     default:
650         g_assert_not_reached();
651     }
652     if (cf & 1) {
653         cond.c = tcg_invert_cond(cond.c);
654     }
655 
656     return cond;
657 }
658 
659 /* Similar, but for the special case of subtraction without borrow, we
660    can use the inputs directly.  This can allow other computation to be
661    deleted as unused.  */
662 
663 static DisasCond do_sub_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2, TCGv sv)
664 {
665     DisasCond cond;
666 
667     switch (cf >> 1) {
668     case 1: /* = / <> */
669         cond = cond_make(TCG_COND_EQ, in1, in2);
670         break;
671     case 2: /* < / >= */
672         cond = cond_make(TCG_COND_LT, in1, in2);
673         break;
674     case 3: /* <= / > */
675         cond = cond_make(TCG_COND_LE, in1, in2);
676         break;
677     case 4: /* << / >>= */
678         cond = cond_make(TCG_COND_LTU, in1, in2);
679         break;
680     case 5: /* <<= / >> */
681         cond = cond_make(TCG_COND_LEU, in1, in2);
682         break;
683     default:
684         return do_cond(cf, res, sv, sv);
685     }
686     if (cf & 1) {
687         cond.c = tcg_invert_cond(cond.c);
688     }
689 
690     return cond;
691 }
692 
693 /* Similar, but for logicals, where the carry and overflow bits are not
694    computed, and use of them is undefined.  */
695 
696 static DisasCond do_log_cond(unsigned cf, TCGv res)
697 {
698     switch (cf >> 1) {
699     case 4: case 5: case 6:
700         cf &= 1;
701         break;
702     }
703     return do_cond(cf, res, res, res);
704 }
705 
706 /* Similar, but for shift/extract/deposit conditions.  */
707 
708 static DisasCond do_sed_cond(unsigned orig, TCGv res)
709 {
710     unsigned c, f;
711 
712     /* Convert the compressed condition codes to standard.
713        0-2 are the same as logicals (nv,<,<=), while 3 is OD.
714        4-7 are the reverse of 0-3.  */
715     c = orig & 3;
716     if (c == 3) {
717         c = 7;
718     }
719     f = (orig & 4) / 4;
720 
721     return do_log_cond(c * 2 + f, res);
722 }
723 
724 /* Similar, but for unit conditions.  */
725 
726 static DisasCond do_unit_cond(unsigned cf, TCGv res, TCGv in1, TCGv in2)
727 {
728     DisasCond cond;
729     TCGv tmp, cb;
730 
731     TCGV_UNUSED(cb);
732     if (cf & 8) {
733         /* Since we want to test lots of carry-out bits all at once, do not
734          * do our normal thing and compute carry-in of bit B+1 since that
735          * leaves us with carry bits spread across two words.
736          */
737         cb = tcg_temp_new();
738         tmp = tcg_temp_new();
739         tcg_gen_or_tl(cb, in1, in2);
740         tcg_gen_and_tl(tmp, in1, in2);
741         tcg_gen_andc_tl(cb, cb, res);
742         tcg_gen_or_tl(cb, cb, tmp);
743         tcg_temp_free(tmp);
744     }
745 
746     switch (cf >> 1) {
747     case 0: /* never / TR */
748     case 1: /* undefined */
749     case 5: /* undefined */
750         cond = cond_make_f();
751         break;
752 
753     case 2: /* SBZ / NBZ */
754         /* See hasless(v,1) from
755          * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
756          */
757         tmp = tcg_temp_new();
758         tcg_gen_subi_tl(tmp, res, 0x01010101u);
759         tcg_gen_andc_tl(tmp, tmp, res);
760         tcg_gen_andi_tl(tmp, tmp, 0x80808080u);
761         cond = cond_make_0(TCG_COND_NE, tmp);
762         tcg_temp_free(tmp);
763         break;
764 
765     case 3: /* SHZ / NHZ */
766         tmp = tcg_temp_new();
767         tcg_gen_subi_tl(tmp, res, 0x00010001u);
768         tcg_gen_andc_tl(tmp, tmp, res);
769         tcg_gen_andi_tl(tmp, tmp, 0x80008000u);
770         cond = cond_make_0(TCG_COND_NE, tmp);
771         tcg_temp_free(tmp);
772         break;
773 
774     case 4: /* SDC / NDC */
775         tcg_gen_andi_tl(cb, cb, 0x88888888u);
776         cond = cond_make_0(TCG_COND_NE, cb);
777         break;
778 
779     case 6: /* SBC / NBC */
780         tcg_gen_andi_tl(cb, cb, 0x80808080u);
781         cond = cond_make_0(TCG_COND_NE, cb);
782         break;
783 
784     case 7: /* SHC / NHC */
785         tcg_gen_andi_tl(cb, cb, 0x80008000u);
786         cond = cond_make_0(TCG_COND_NE, cb);
787         break;
788 
789     default:
790         g_assert_not_reached();
791     }
792     if (cf & 8) {
793         tcg_temp_free(cb);
794     }
795     if (cf & 1) {
796         cond.c = tcg_invert_cond(cond.c);
797     }
798 
799     return cond;
800 }
801 
802 /* Compute signed overflow for addition.  */
803 static TCGv do_add_sv(DisasContext *ctx, TCGv res, TCGv in1, TCGv in2)
804 {
805     TCGv sv = get_temp(ctx);
806     TCGv tmp = tcg_temp_new();
807 
808     tcg_gen_xor_tl(sv, res, in1);
809     tcg_gen_xor_tl(tmp, in1, in2);
810     tcg_gen_andc_tl(sv, sv, tmp);
811     tcg_temp_free(tmp);
812 
813     return sv;
814 }
815 
816 /* Compute signed overflow for subtraction.  */
817 static TCGv do_sub_sv(DisasContext *ctx, TCGv res, TCGv in1, TCGv in2)
818 {
819     TCGv sv = get_temp(ctx);
820     TCGv tmp = tcg_temp_new();
821 
822     tcg_gen_xor_tl(sv, res, in1);
823     tcg_gen_xor_tl(tmp, in1, in2);
824     tcg_gen_and_tl(sv, sv, tmp);
825     tcg_temp_free(tmp);
826 
827     return sv;
828 }
829 
830 static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
831                             unsigned shift, bool is_l, bool is_tsv, bool is_tc,
832                             bool is_c, unsigned cf)
833 {
834     TCGv dest, cb, cb_msb, sv, tmp;
835     unsigned c = cf >> 1;
836     DisasCond cond;
837 
838     dest = tcg_temp_new();
839     TCGV_UNUSED(cb);
840     TCGV_UNUSED(cb_msb);
841 
842     if (shift) {
843         tmp = get_temp(ctx);
844         tcg_gen_shli_tl(tmp, in1, shift);
845         in1 = tmp;
846     }
847 
848     if (!is_l || c == 4 || c == 5) {
849         TCGv zero = tcg_const_tl(0);
850         cb_msb = get_temp(ctx);
851         tcg_gen_add2_tl(dest, cb_msb, in1, zero, in2, zero);
852         if (is_c) {
853             tcg_gen_add2_tl(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
854         }
855         tcg_temp_free(zero);
856         if (!is_l) {
857             cb = get_temp(ctx);
858             tcg_gen_xor_tl(cb, in1, in2);
859             tcg_gen_xor_tl(cb, cb, dest);
860         }
861     } else {
862         tcg_gen_add_tl(dest, in1, in2);
863         if (is_c) {
864             tcg_gen_add_tl(dest, dest, cpu_psw_cb_msb);
865         }
866     }
867 
868     /* Compute signed overflow if required.  */
869     TCGV_UNUSED(sv);
870     if (is_tsv || c == 6) {
871         sv = do_add_sv(ctx, dest, in1, in2);
872         if (is_tsv) {
873             /* ??? Need to include overflow from shift.  */
874             gen_helper_tsv(cpu_env, sv);
875         }
876     }
877 
878     /* Emit any conditional trap before any writeback.  */
879     cond = do_cond(cf, dest, cb_msb, sv);
880     if (is_tc) {
881         cond_prep(&cond);
882         tmp = tcg_temp_new();
883         tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1);
884         gen_helper_tcond(cpu_env, tmp);
885         tcg_temp_free(tmp);
886     }
887 
888     /* Write back the result.  */
889     if (!is_l) {
890         save_or_nullify(ctx, cpu_psw_cb, cb);
891         save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
892     }
893     save_gpr(ctx, rt, dest);
894     tcg_temp_free(dest);
895 
896     /* Install the new nullification.  */
897     cond_free(&ctx->null_cond);
898     ctx->null_cond = cond;
899     return DISAS_NEXT;
900 }
901 
902 static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
903                             bool is_tsv, bool is_b, bool is_tc, unsigned cf)
904 {
905     TCGv dest, sv, cb, cb_msb, zero, tmp;
906     unsigned c = cf >> 1;
907     DisasCond cond;
908 
909     dest = tcg_temp_new();
910     cb = tcg_temp_new();
911     cb_msb = tcg_temp_new();
912 
913     zero = tcg_const_tl(0);
914     if (is_b) {
915         /* DEST,C = IN1 + ~IN2 + C.  */
916         tcg_gen_not_tl(cb, in2);
917         tcg_gen_add2_tl(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
918         tcg_gen_add2_tl(dest, cb_msb, dest, cb_msb, cb, zero);
919         tcg_gen_xor_tl(cb, cb, in1);
920         tcg_gen_xor_tl(cb, cb, dest);
921     } else {
922         /* DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
923            operations by seeding the high word with 1 and subtracting.  */
924         tcg_gen_movi_tl(cb_msb, 1);
925         tcg_gen_sub2_tl(dest, cb_msb, in1, cb_msb, in2, zero);
926         tcg_gen_eqv_tl(cb, in1, in2);
927         tcg_gen_xor_tl(cb, cb, dest);
928     }
929     tcg_temp_free(zero);
930 
931     /* Compute signed overflow if required.  */
932     TCGV_UNUSED(sv);
933     if (is_tsv || c == 6) {
934         sv = do_sub_sv(ctx, dest, in1, in2);
935         if (is_tsv) {
936             gen_helper_tsv(cpu_env, sv);
937         }
938     }
939 
940     /* Compute the condition.  We cannot use the special case for borrow.  */
941     if (!is_b) {
942         cond = do_sub_cond(cf, dest, in1, in2, sv);
943     } else {
944         cond = do_cond(cf, dest, cb_msb, sv);
945     }
946 
947     /* Emit any conditional trap before any writeback.  */
948     if (is_tc) {
949         cond_prep(&cond);
950         tmp = tcg_temp_new();
951         tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1);
952         gen_helper_tcond(cpu_env, tmp);
953         tcg_temp_free(tmp);
954     }
955 
956     /* Write back the result.  */
957     save_or_nullify(ctx, cpu_psw_cb, cb);
958     save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
959     save_gpr(ctx, rt, dest);
960     tcg_temp_free(dest);
961 
962     /* Install the new nullification.  */
963     cond_free(&ctx->null_cond);
964     ctx->null_cond = cond;
965     return DISAS_NEXT;
966 }
967 
968 static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv in1,
969                                TCGv in2, unsigned cf)
970 {
971     TCGv dest, sv;
972     DisasCond cond;
973 
974     dest = tcg_temp_new();
975     tcg_gen_sub_tl(dest, in1, in2);
976 
977     /* Compute signed overflow if required.  */
978     TCGV_UNUSED(sv);
979     if ((cf >> 1) == 6) {
980         sv = do_sub_sv(ctx, dest, in1, in2);
981     }
982 
983     /* Form the condition for the compare.  */
984     cond = do_sub_cond(cf, dest, in1, in2, sv);
985 
986     /* Clear.  */
987     tcg_gen_movi_tl(dest, 0);
988     save_gpr(ctx, rt, dest);
989     tcg_temp_free(dest);
990 
991     /* Install the new nullification.  */
992     cond_free(&ctx->null_cond);
993     ctx->null_cond = cond;
994     return DISAS_NEXT;
995 }
996 
997 static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv in1, TCGv in2,
998                             unsigned cf, void (*fn)(TCGv, TCGv, TCGv))
999 {
1000     TCGv dest = dest_gpr(ctx, rt);
1001 
1002     /* Perform the operation, and writeback.  */
1003     fn(dest, in1, in2);
1004     save_gpr(ctx, rt, dest);
1005 
1006     /* Install the new nullification.  */
1007     cond_free(&ctx->null_cond);
1008     if (cf) {
1009         ctx->null_cond = do_log_cond(cf, dest);
1010     }
1011     return DISAS_NEXT;
1012 }
1013 
1014 static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv in1,
1015                              TCGv in2, unsigned cf, bool is_tc,
1016                              void (*fn)(TCGv, TCGv, TCGv))
1017 {
1018     TCGv dest;
1019     DisasCond cond;
1020 
1021     if (cf == 0) {
1022         dest = dest_gpr(ctx, rt);
1023         fn(dest, in1, in2);
1024         save_gpr(ctx, rt, dest);
1025         cond_free(&ctx->null_cond);
1026     } else {
1027         dest = tcg_temp_new();
1028         fn(dest, in1, in2);
1029 
1030         cond = do_unit_cond(cf, dest, in1, in2);
1031 
1032         if (is_tc) {
1033             TCGv tmp = tcg_temp_new();
1034             cond_prep(&cond);
1035             tcg_gen_setcond_tl(cond.c, tmp, cond.a0, cond.a1);
1036             gen_helper_tcond(cpu_env, tmp);
1037             tcg_temp_free(tmp);
1038         }
1039         save_gpr(ctx, rt, dest);
1040 
1041         cond_free(&ctx->null_cond);
1042         ctx->null_cond = cond;
1043     }
1044     return DISAS_NEXT;
1045 }
1046 
1047 /* Emit a memory load.  The modify parameter should be
1048  * < 0 for pre-modify,
1049  * > 0 for post-modify,
1050  * = 0 for no base register update.
1051  */
1052 static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1053                        unsigned rx, int scale, target_long disp,
1054                        int modify, TCGMemOp mop)
1055 {
1056     TCGv addr, base;
1057 
1058     /* Caller uses nullify_over/nullify_end.  */
1059     assert(ctx->null_cond.c == TCG_COND_NEVER);
1060 
1061     addr = tcg_temp_new();
1062     base = load_gpr(ctx, rb);
1063 
1064     /* Note that RX is mutually exclusive with DISP.  */
1065     if (rx) {
1066         tcg_gen_shli_tl(addr, cpu_gr[rx], scale);
1067         tcg_gen_add_tl(addr, addr, base);
1068     } else {
1069         tcg_gen_addi_tl(addr, base, disp);
1070     }
1071 
1072     if (modify == 0) {
1073         tcg_gen_qemu_ld_i32(dest, addr, MMU_USER_IDX, mop);
1074     } else {
1075         tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base),
1076                             MMU_USER_IDX, mop);
1077         save_gpr(ctx, rb, addr);
1078     }
1079     tcg_temp_free(addr);
1080 }
1081 
1082 static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1083                        unsigned rx, int scale, target_long disp,
1084                        int modify, TCGMemOp mop)
1085 {
1086     TCGv addr, base;
1087 
1088     /* Caller uses nullify_over/nullify_end.  */
1089     assert(ctx->null_cond.c == TCG_COND_NEVER);
1090 
1091     addr = tcg_temp_new();
1092     base = load_gpr(ctx, rb);
1093 
1094     /* Note that RX is mutually exclusive with DISP.  */
1095     if (rx) {
1096         tcg_gen_shli_tl(addr, cpu_gr[rx], scale);
1097         tcg_gen_add_tl(addr, addr, base);
1098     } else {
1099         tcg_gen_addi_tl(addr, base, disp);
1100     }
1101 
1102     if (modify == 0) {
1103         tcg_gen_qemu_ld_i64(dest, addr, MMU_USER_IDX, mop);
1104     } else {
1105         tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base),
1106                             MMU_USER_IDX, mop);
1107         save_gpr(ctx, rb, addr);
1108     }
1109     tcg_temp_free(addr);
1110 }
1111 
1112 static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1113                         unsigned rx, int scale, target_long disp,
1114                         int modify, TCGMemOp mop)
1115 {
1116     TCGv addr, base;
1117 
1118     /* Caller uses nullify_over/nullify_end.  */
1119     assert(ctx->null_cond.c == TCG_COND_NEVER);
1120 
1121     addr = tcg_temp_new();
1122     base = load_gpr(ctx, rb);
1123 
1124     /* Note that RX is mutually exclusive with DISP.  */
1125     if (rx) {
1126         tcg_gen_shli_tl(addr, cpu_gr[rx], scale);
1127         tcg_gen_add_tl(addr, addr, base);
1128     } else {
1129         tcg_gen_addi_tl(addr, base, disp);
1130     }
1131 
1132     tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop);
1133 
1134     if (modify != 0) {
1135         save_gpr(ctx, rb, addr);
1136     }
1137     tcg_temp_free(addr);
1138 }
1139 
1140 static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1141                         unsigned rx, int scale, target_long disp,
1142                         int modify, TCGMemOp mop)
1143 {
1144     TCGv addr, base;
1145 
1146     /* Caller uses nullify_over/nullify_end.  */
1147     assert(ctx->null_cond.c == TCG_COND_NEVER);
1148 
1149     addr = tcg_temp_new();
1150     base = load_gpr(ctx, rb);
1151 
1152     /* Note that RX is mutually exclusive with DISP.  */
1153     if (rx) {
1154         tcg_gen_shli_tl(addr, cpu_gr[rx], scale);
1155         tcg_gen_add_tl(addr, addr, base);
1156     } else {
1157         tcg_gen_addi_tl(addr, base, disp);
1158     }
1159 
1160     tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop);
1161 
1162     if (modify != 0) {
1163         save_gpr(ctx, rb, addr);
1164     }
1165     tcg_temp_free(addr);
1166 }
1167 
1168 #if TARGET_LONG_BITS == 64
1169 #define do_load_tl  do_load_64
1170 #define do_store_tl do_store_64
1171 #else
1172 #define do_load_tl  do_load_32
1173 #define do_store_tl do_store_32
1174 #endif
1175 
1176 static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1177                              unsigned rx, int scale, target_long disp,
1178                              int modify, TCGMemOp mop)
1179 {
1180     TCGv dest;
1181 
1182     nullify_over(ctx);
1183 
1184     if (modify == 0) {
1185         /* No base register update.  */
1186         dest = dest_gpr(ctx, rt);
1187     } else {
1188         /* Make sure if RT == RB, we see the result of the load.  */
1189         dest = get_temp(ctx);
1190     }
1191     do_load_tl(ctx, dest, rb, rx, scale, disp, modify, mop);
1192     save_gpr(ctx, rt, dest);
1193 
1194     return nullify_end(ctx, DISAS_NEXT);
1195 }
1196 
1197 static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1198                                unsigned rx, int scale, target_long disp,
1199                                int modify)
1200 {
1201     TCGv_i32 tmp;
1202 
1203     nullify_over(ctx);
1204 
1205     tmp = tcg_temp_new_i32();
1206     do_load_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL);
1207     save_frw_i32(rt, tmp);
1208     tcg_temp_free_i32(tmp);
1209 
1210     if (rt == 0) {
1211         gen_helper_loaded_fr0(cpu_env);
1212     }
1213 
1214     return nullify_end(ctx, DISAS_NEXT);
1215 }
1216 
1217 static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1218                                unsigned rx, int scale, target_long disp,
1219                                int modify)
1220 {
1221     TCGv_i64 tmp;
1222 
1223     nullify_over(ctx);
1224 
1225     tmp = tcg_temp_new_i64();
1226     do_load_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ);
1227     save_frd(rt, tmp);
1228     tcg_temp_free_i64(tmp);
1229 
1230     if (rt == 0) {
1231         gen_helper_loaded_fr0(cpu_env);
1232     }
1233 
1234     return nullify_end(ctx, DISAS_NEXT);
1235 }
1236 
1237 static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1238                               target_long disp, int modify, TCGMemOp mop)
1239 {
1240     nullify_over(ctx);
1241     do_store_tl(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop);
1242     return nullify_end(ctx, DISAS_NEXT);
1243 }
1244 
1245 static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1246                                 unsigned rx, int scale, target_long disp,
1247                                 int modify)
1248 {
1249     TCGv_i32 tmp;
1250 
1251     nullify_over(ctx);
1252 
1253     tmp = load_frw_i32(rt);
1254     do_store_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL);
1255     tcg_temp_free_i32(tmp);
1256 
1257     return nullify_end(ctx, DISAS_NEXT);
1258 }
1259 
1260 static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1261                                 unsigned rx, int scale, target_long disp,
1262                                 int modify)
1263 {
1264     TCGv_i64 tmp;
1265 
1266     nullify_over(ctx);
1267 
1268     tmp = load_frd(rt);
1269     do_store_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ);
1270     tcg_temp_free_i64(tmp);
1271 
1272     return nullify_end(ctx, DISAS_NEXT);
1273 }
1274 
1275 static DisasJumpType do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1276                                 void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1277 {
1278     TCGv_i32 tmp;
1279 
1280     nullify_over(ctx);
1281     tmp = load_frw0_i32(ra);
1282 
1283     func(tmp, cpu_env, tmp);
1284 
1285     save_frw_i32(rt, tmp);
1286     tcg_temp_free_i32(tmp);
1287     return nullify_end(ctx, DISAS_NEXT);
1288 }
1289 
1290 static DisasJumpType do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1291                                 void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1292 {
1293     TCGv_i32 dst;
1294     TCGv_i64 src;
1295 
1296     nullify_over(ctx);
1297     src = load_frd(ra);
1298     dst = tcg_temp_new_i32();
1299 
1300     func(dst, cpu_env, src);
1301 
1302     tcg_temp_free_i64(src);
1303     save_frw_i32(rt, dst);
1304     tcg_temp_free_i32(dst);
1305     return nullify_end(ctx, DISAS_NEXT);
1306 }
1307 
1308 static DisasJumpType do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1309                                 void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1310 {
1311     TCGv_i64 tmp;
1312 
1313     nullify_over(ctx);
1314     tmp = load_frd0(ra);
1315 
1316     func(tmp, cpu_env, tmp);
1317 
1318     save_frd(rt, tmp);
1319     tcg_temp_free_i64(tmp);
1320     return nullify_end(ctx, DISAS_NEXT);
1321 }
1322 
1323 static DisasJumpType do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1324                                 void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1325 {
1326     TCGv_i32 src;
1327     TCGv_i64 dst;
1328 
1329     nullify_over(ctx);
1330     src = load_frw0_i32(ra);
1331     dst = tcg_temp_new_i64();
1332 
1333     func(dst, cpu_env, src);
1334 
1335     tcg_temp_free_i32(src);
1336     save_frd(rt, dst);
1337     tcg_temp_free_i64(dst);
1338     return nullify_end(ctx, DISAS_NEXT);
1339 }
1340 
1341 static DisasJumpType do_fop_weww(DisasContext *ctx, unsigned rt,
1342                                  unsigned ra, unsigned rb,
1343                                  void (*func)(TCGv_i32, TCGv_env,
1344                                               TCGv_i32, TCGv_i32))
1345 {
1346     TCGv_i32 a, b;
1347 
1348     nullify_over(ctx);
1349     a = load_frw0_i32(ra);
1350     b = load_frw0_i32(rb);
1351 
1352     func(a, cpu_env, a, b);
1353 
1354     tcg_temp_free_i32(b);
1355     save_frw_i32(rt, a);
1356     tcg_temp_free_i32(a);
1357     return nullify_end(ctx, DISAS_NEXT);
1358 }
1359 
1360 static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt,
1361                                  unsigned ra, unsigned rb,
1362                                  void (*func)(TCGv_i64, TCGv_env,
1363                                               TCGv_i64, TCGv_i64))
1364 {
1365     TCGv_i64 a, b;
1366 
1367     nullify_over(ctx);
1368     a = load_frd0(ra);
1369     b = load_frd0(rb);
1370 
1371     func(a, cpu_env, a, b);
1372 
1373     tcg_temp_free_i64(b);
1374     save_frd(rt, a);
1375     tcg_temp_free_i64(a);
1376     return nullify_end(ctx, DISAS_NEXT);
1377 }
1378 
1379 /* Emit an unconditional branch to a direct target, which may or may not
1380    have already had nullification handled.  */
1381 static DisasJumpType do_dbranch(DisasContext *ctx, target_ulong dest,
1382                                 unsigned link, bool is_n)
1383 {
1384     if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1385         if (link != 0) {
1386             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1387         }
1388         ctx->iaoq_n = dest;
1389         if (is_n) {
1390             ctx->null_cond.c = TCG_COND_ALWAYS;
1391         }
1392         return DISAS_NEXT;
1393     } else {
1394         nullify_over(ctx);
1395 
1396         if (link != 0) {
1397             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1398         }
1399 
1400         if (is_n && use_nullify_skip(ctx)) {
1401             nullify_set(ctx, 0);
1402             gen_goto_tb(ctx, 0, dest, dest + 4);
1403         } else {
1404             nullify_set(ctx, is_n);
1405             gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
1406         }
1407 
1408         nullify_end(ctx, DISAS_NEXT);
1409 
1410         nullify_set(ctx, 0);
1411         gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1412         return DISAS_NORETURN;
1413     }
1414 }
1415 
1416 /* Emit a conditional branch to a direct target.  If the branch itself
1417    is nullified, we should have already used nullify_over.  */
1418 static DisasJumpType do_cbranch(DisasContext *ctx, target_long disp, bool is_n,
1419                                 DisasCond *cond)
1420 {
1421     target_ulong dest = iaoq_dest(ctx, disp);
1422     TCGLabel *taken = NULL;
1423     TCGCond c = cond->c;
1424     bool n;
1425 
1426     assert(ctx->null_cond.c == TCG_COND_NEVER);
1427 
1428     /* Handle TRUE and NEVER as direct branches.  */
1429     if (c == TCG_COND_ALWAYS) {
1430         return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
1431     }
1432     if (c == TCG_COND_NEVER) {
1433         return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
1434     }
1435 
1436     taken = gen_new_label();
1437     cond_prep(cond);
1438     tcg_gen_brcond_tl(c, cond->a0, cond->a1, taken);
1439     cond_free(cond);
1440 
1441     /* Not taken: Condition not satisfied; nullify on backward branches. */
1442     n = is_n && disp < 0;
1443     if (n && use_nullify_skip(ctx)) {
1444         nullify_set(ctx, 0);
1445         gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
1446     } else {
1447         if (!n && ctx->null_lab) {
1448             gen_set_label(ctx->null_lab);
1449             ctx->null_lab = NULL;
1450         }
1451         nullify_set(ctx, n);
1452         gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
1453     }
1454 
1455     gen_set_label(taken);
1456 
1457     /* Taken: Condition satisfied; nullify on forward branches.  */
1458     n = is_n && disp >= 0;
1459     if (n && use_nullify_skip(ctx)) {
1460         nullify_set(ctx, 0);
1461         gen_goto_tb(ctx, 1, dest, dest + 4);
1462     } else {
1463         nullify_set(ctx, n);
1464         gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
1465     }
1466 
1467     /* Not taken: the branch itself was nullified.  */
1468     if (ctx->null_lab) {
1469         gen_set_label(ctx->null_lab);
1470         ctx->null_lab = NULL;
1471         return DISAS_IAQ_N_STALE;
1472     } else {
1473         return DISAS_NORETURN;
1474     }
1475 }
1476 
1477 /* Emit an unconditional branch to an indirect target.  This handles
1478    nullification of the branch itself.  */
1479 static DisasJumpType do_ibranch(DisasContext *ctx, TCGv dest,
1480                                 unsigned link, bool is_n)
1481 {
1482     TCGv a0, a1, next, tmp;
1483     TCGCond c;
1484 
1485     assert(ctx->null_lab == NULL);
1486 
1487     if (ctx->null_cond.c == TCG_COND_NEVER) {
1488         if (link != 0) {
1489             copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1490         }
1491         next = get_temp(ctx);
1492         tcg_gen_mov_tl(next, dest);
1493         ctx->iaoq_n = -1;
1494         ctx->iaoq_n_var = next;
1495         if (is_n) {
1496             ctx->null_cond.c = TCG_COND_ALWAYS;
1497         }
1498     } else if (is_n && use_nullify_skip(ctx)) {
1499         /* The (conditional) branch, B, nullifies the next insn, N,
1500            and we're allowed to skip execution N (no single-step or
1501            tracepoint in effect).  Since the goto_ptr that we must use
1502            for the indirect branch consumes no special resources, we
1503            can (conditionally) skip B and continue execution.  */
1504         /* The use_nullify_skip test implies we have a known control path.  */
1505         tcg_debug_assert(ctx->iaoq_b != -1);
1506         tcg_debug_assert(ctx->iaoq_n != -1);
1507 
1508         /* We do have to handle the non-local temporary, DEST, before
1509            branching.  Since IOAQ_F is not really live at this point, we
1510            can simply store DEST optimistically.  Similarly with IAOQ_B.  */
1511         tcg_gen_mov_tl(cpu_iaoq_f, dest);
1512         tcg_gen_addi_tl(cpu_iaoq_b, dest, 4);
1513 
1514         nullify_over(ctx);
1515         if (link != 0) {
1516             tcg_gen_movi_tl(cpu_gr[link], ctx->iaoq_n);
1517         }
1518         tcg_gen_lookup_and_goto_ptr();
1519         return nullify_end(ctx, DISAS_NEXT);
1520     } else {
1521         cond_prep(&ctx->null_cond);
1522         c = ctx->null_cond.c;
1523         a0 = ctx->null_cond.a0;
1524         a1 = ctx->null_cond.a1;
1525 
1526         tmp = tcg_temp_new();
1527         next = get_temp(ctx);
1528 
1529         copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1530         tcg_gen_movcond_tl(c, next, a0, a1, tmp, dest);
1531         ctx->iaoq_n = -1;
1532         ctx->iaoq_n_var = next;
1533 
1534         if (link != 0) {
1535             tcg_gen_movcond_tl(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1536         }
1537 
1538         if (is_n) {
1539             /* The branch nullifies the next insn, which means the state of N
1540                after the branch is the inverse of the state of N that applied
1541                to the branch.  */
1542             tcg_gen_setcond_tl(tcg_invert_cond(c), cpu_psw_n, a0, a1);
1543             cond_free(&ctx->null_cond);
1544             ctx->null_cond = cond_make_n();
1545             ctx->psw_n_nonzero = true;
1546         } else {
1547             cond_free(&ctx->null_cond);
1548         }
1549     }
1550 
1551     return DISAS_NEXT;
1552 }
1553 
1554 /* On Linux, page zero is normally marked execute only + gateway.
1555    Therefore normal read or write is supposed to fail, but specific
1556    offsets have kernel code mapped to raise permissions to implement
1557    system calls.  Handling this via an explicit check here, rather
1558    in than the "be disp(sr2,r0)" instruction that probably sent us
1559    here, is the easiest way to handle the branch delay slot on the
1560    aforementioned BE.  */
1561 static DisasJumpType do_page_zero(DisasContext *ctx)
1562 {
1563     /* If by some means we get here with PSW[N]=1, that implies that
1564        the B,GATE instruction would be skipped, and we'd fault on the
1565        next insn within the privilaged page.  */
1566     switch (ctx->null_cond.c) {
1567     case TCG_COND_NEVER:
1568         break;
1569     case TCG_COND_ALWAYS:
1570         tcg_gen_movi_tl(cpu_psw_n, 0);
1571         goto do_sigill;
1572     default:
1573         /* Since this is always the first (and only) insn within the
1574            TB, we should know the state of PSW[N] from TB->FLAGS.  */
1575         g_assert_not_reached();
1576     }
1577 
1578     /* Check that we didn't arrive here via some means that allowed
1579        non-sequential instruction execution.  Normally the PSW[B] bit
1580        detects this by disallowing the B,GATE instruction to execute
1581        under such conditions.  */
1582     if (ctx->iaoq_b != ctx->iaoq_f + 4) {
1583         goto do_sigill;
1584     }
1585 
1586     switch (ctx->iaoq_f) {
1587     case 0x00: /* Null pointer call */
1588         gen_excp_1(EXCP_SIGSEGV);
1589         return DISAS_NORETURN;
1590 
1591     case 0xb0: /* LWS */
1592         gen_excp_1(EXCP_SYSCALL_LWS);
1593         return DISAS_NORETURN;
1594 
1595     case 0xe0: /* SET_THREAD_POINTER */
1596         tcg_gen_mov_tl(cpu_cr27, cpu_gr[26]);
1597         tcg_gen_mov_tl(cpu_iaoq_f, cpu_gr[31]);
1598         tcg_gen_addi_tl(cpu_iaoq_b, cpu_iaoq_f, 4);
1599         return DISAS_IAQ_N_UPDATED;
1600 
1601     case 0x100: /* SYSCALL */
1602         gen_excp_1(EXCP_SYSCALL);
1603         return DISAS_NORETURN;
1604 
1605     default:
1606     do_sigill:
1607         gen_excp_1(EXCP_SIGILL);
1608         return DISAS_NORETURN;
1609     }
1610 }
1611 
1612 static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
1613                                const DisasInsn *di)
1614 {
1615     cond_free(&ctx->null_cond);
1616     return DISAS_NEXT;
1617 }
1618 
1619 static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
1620                                  const DisasInsn *di)
1621 {
1622     nullify_over(ctx);
1623     return nullify_end(ctx, gen_excp(ctx, EXCP_DEBUG));
1624 }
1625 
1626 static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn,
1627                                 const DisasInsn *di)
1628 {
1629     /* No point in nullifying the memory barrier.  */
1630     tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
1631 
1632     cond_free(&ctx->null_cond);
1633     return DISAS_NEXT;
1634 }
1635 
1636 static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn,
1637                                 const DisasInsn *di)
1638 {
1639     unsigned rt = extract32(insn, 0, 5);
1640     TCGv tmp = dest_gpr(ctx, rt);
1641     tcg_gen_movi_tl(tmp, ctx->iaoq_f);
1642     save_gpr(ctx, rt, tmp);
1643 
1644     cond_free(&ctx->null_cond);
1645     return DISAS_NEXT;
1646 }
1647 
1648 static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn,
1649                                 const DisasInsn *di)
1650 {
1651     unsigned rt = extract32(insn, 0, 5);
1652     TCGv tmp = dest_gpr(ctx, rt);
1653 
1654     /* ??? We don't implement space registers.  */
1655     tcg_gen_movi_tl(tmp, 0);
1656     save_gpr(ctx, rt, tmp);
1657 
1658     cond_free(&ctx->null_cond);
1659     return DISAS_NEXT;
1660 }
1661 
1662 static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn,
1663                                  const DisasInsn *di)
1664 {
1665     unsigned rt = extract32(insn, 0, 5);
1666     unsigned ctl = extract32(insn, 21, 5);
1667     TCGv tmp;
1668 
1669     switch (ctl) {
1670     case 11: /* SAR */
1671 #ifdef TARGET_HPPA64
1672         if (extract32(insn, 14, 1) == 0) {
1673             /* MFSAR without ,W masks low 5 bits.  */
1674             tmp = dest_gpr(ctx, rt);
1675             tcg_gen_andi_tl(tmp, cpu_sar, 31);
1676             save_gpr(ctx, rt, tmp);
1677             break;
1678         }
1679 #endif
1680         save_gpr(ctx, rt, cpu_sar);
1681         break;
1682     case 16: /* Interval Timer */
1683         tmp = dest_gpr(ctx, rt);
1684         tcg_gen_movi_tl(tmp, 0); /* FIXME */
1685         save_gpr(ctx, rt, tmp);
1686         break;
1687     case 26:
1688         save_gpr(ctx, rt, cpu_cr26);
1689         break;
1690     case 27:
1691         save_gpr(ctx, rt, cpu_cr27);
1692         break;
1693     default:
1694         /* All other control registers are privileged.  */
1695         return gen_illegal(ctx);
1696     }
1697 
1698     cond_free(&ctx->null_cond);
1699     return DISAS_NEXT;
1700 }
1701 
1702 static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn,
1703                                  const DisasInsn *di)
1704 {
1705     unsigned rin = extract32(insn, 16, 5);
1706     unsigned ctl = extract32(insn, 21, 5);
1707     TCGv tmp;
1708 
1709     if (ctl == 11) { /* SAR */
1710         tmp = tcg_temp_new();
1711         tcg_gen_andi_tl(tmp, load_gpr(ctx, rin), TARGET_LONG_BITS - 1);
1712         save_or_nullify(ctx, cpu_sar, tmp);
1713         tcg_temp_free(tmp);
1714     } else {
1715         /* All other control registers are privileged or read-only.  */
1716         return gen_illegal(ctx);
1717     }
1718 
1719     cond_free(&ctx->null_cond);
1720     return DISAS_NEXT;
1721 }
1722 
1723 static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn,
1724                                    const DisasInsn *di)
1725 {
1726     unsigned rin = extract32(insn, 16, 5);
1727     TCGv tmp = tcg_temp_new();
1728 
1729     tcg_gen_not_tl(tmp, load_gpr(ctx, rin));
1730     tcg_gen_andi_tl(tmp, tmp, TARGET_LONG_BITS - 1);
1731     save_or_nullify(ctx, cpu_sar, tmp);
1732     tcg_temp_free(tmp);
1733 
1734     cond_free(&ctx->null_cond);
1735     return DISAS_NEXT;
1736 }
1737 
1738 static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn,
1739                                  const DisasInsn *di)
1740 {
1741     unsigned rt = extract32(insn, 0, 5);
1742     TCGv dest = dest_gpr(ctx, rt);
1743 
1744     /* Since we don't implement space registers, this returns zero.  */
1745     tcg_gen_movi_tl(dest, 0);
1746     save_gpr(ctx, rt, dest);
1747 
1748     cond_free(&ctx->null_cond);
1749     return DISAS_NEXT;
1750 }
1751 
1752 static const DisasInsn table_system[] = {
1753     { 0x00000000u, 0xfc001fe0u, trans_break },
1754     /* We don't implement space register, so MTSP is a nop.  */
1755     { 0x00001820u, 0xffe01fffu, trans_nop },
1756     { 0x00001840u, 0xfc00ffffu, trans_mtctl },
1757     { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm },
1758     { 0x000014a0u, 0xffffffe0u, trans_mfia },
1759     { 0x000004a0u, 0xffff1fe0u, trans_mfsp },
1760     { 0x000008a0u, 0xfc1fffe0u, trans_mfctl },
1761     { 0x00000400u, 0xffffffffu, trans_sync },
1762     { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid },
1763 };
1764 
1765 static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn,
1766                                         const DisasInsn *di)
1767 {
1768     unsigned rb = extract32(insn, 21, 5);
1769     unsigned rx = extract32(insn, 16, 5);
1770     TCGv dest = dest_gpr(ctx, rb);
1771     TCGv src1 = load_gpr(ctx, rb);
1772     TCGv src2 = load_gpr(ctx, rx);
1773 
1774     /* The only thing we need to do is the base register modification.  */
1775     tcg_gen_add_tl(dest, src1, src2);
1776     save_gpr(ctx, rb, dest);
1777 
1778     cond_free(&ctx->null_cond);
1779     return DISAS_NEXT;
1780 }
1781 
1782 static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn,
1783                                  const DisasInsn *di)
1784 {
1785     unsigned rt = extract32(insn, 0, 5);
1786     unsigned rb = extract32(insn, 21, 5);
1787     unsigned is_write = extract32(insn, 6, 1);
1788     TCGv dest;
1789 
1790     nullify_over(ctx);
1791 
1792     /* ??? Do something with priv level operand.  */
1793     dest = dest_gpr(ctx, rt);
1794     if (is_write) {
1795         gen_helper_probe_w(dest, load_gpr(ctx, rb));
1796     } else {
1797         gen_helper_probe_r(dest, load_gpr(ctx, rb));
1798     }
1799     save_gpr(ctx, rt, dest);
1800     return nullify_end(ctx, DISAS_NEXT);
1801 }
1802 
1803 static const DisasInsn table_mem_mgmt[] = {
1804     { 0x04003280u, 0xfc003fffu, trans_nop },          /* fdc, disp */
1805     { 0x04001280u, 0xfc003fffu, trans_nop },          /* fdc, index */
1806     { 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */
1807     { 0x040012c0u, 0xfc003fffu, trans_nop },          /* fdce */
1808     { 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */
1809     { 0x04000280u, 0xfc001fffu, trans_nop },          /* fic 0a */
1810     { 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */
1811     { 0x040013c0u, 0xfc003fffu, trans_nop },          /* fic 4f */
1812     { 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */
1813     { 0x040002c0u, 0xfc001fffu, trans_nop },          /* fice */
1814     { 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */
1815     { 0x04002700u, 0xfc003fffu, trans_nop },          /* pdc */
1816     { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */
1817     { 0x04001180u, 0xfc003fa0u, trans_probe },        /* probe */
1818     { 0x04003180u, 0xfc003fa0u, trans_probe },        /* probei */
1819 };
1820 
1821 static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn,
1822                                const DisasInsn *di)
1823 {
1824     unsigned r2 = extract32(insn, 21, 5);
1825     unsigned r1 = extract32(insn, 16, 5);
1826     unsigned cf = extract32(insn, 12, 4);
1827     unsigned ext = extract32(insn, 8, 4);
1828     unsigned shift = extract32(insn, 6, 2);
1829     unsigned rt = extract32(insn,  0, 5);
1830     TCGv tcg_r1, tcg_r2;
1831     bool is_c = false;
1832     bool is_l = false;
1833     bool is_tc = false;
1834     bool is_tsv = false;
1835     DisasJumpType ret;
1836 
1837     switch (ext) {
1838     case 0x6: /* ADD, SHLADD */
1839         break;
1840     case 0xa: /* ADD,L, SHLADD,L */
1841         is_l = true;
1842         break;
1843     case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
1844         is_tsv = true;
1845         break;
1846     case 0x7: /* ADD,C */
1847         is_c = true;
1848         break;
1849     case 0xf: /* ADD,C,TSV */
1850         is_c = is_tsv = true;
1851         break;
1852     default:
1853         return gen_illegal(ctx);
1854     }
1855 
1856     if (cf) {
1857         nullify_over(ctx);
1858     }
1859     tcg_r1 = load_gpr(ctx, r1);
1860     tcg_r2 = load_gpr(ctx, r2);
1861     ret = do_add(ctx, rt, tcg_r1, tcg_r2, shift, is_l, is_tsv, is_tc, is_c, cf);
1862     return nullify_end(ctx, ret);
1863 }
1864 
1865 static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn,
1866                                const DisasInsn *di)
1867 {
1868     unsigned r2 = extract32(insn, 21, 5);
1869     unsigned r1 = extract32(insn, 16, 5);
1870     unsigned cf = extract32(insn, 12, 4);
1871     unsigned ext = extract32(insn, 6, 6);
1872     unsigned rt = extract32(insn,  0, 5);
1873     TCGv tcg_r1, tcg_r2;
1874     bool is_b = false;
1875     bool is_tc = false;
1876     bool is_tsv = false;
1877     DisasJumpType ret;
1878 
1879     switch (ext) {
1880     case 0x10: /* SUB */
1881         break;
1882     case 0x30: /* SUB,TSV */
1883         is_tsv = true;
1884         break;
1885     case 0x14: /* SUB,B */
1886         is_b = true;
1887         break;
1888     case 0x34: /* SUB,B,TSV */
1889         is_b = is_tsv = true;
1890         break;
1891     case 0x13: /* SUB,TC */
1892         is_tc = true;
1893         break;
1894     case 0x33: /* SUB,TSV,TC */
1895         is_tc = is_tsv = true;
1896         break;
1897     default:
1898         return gen_illegal(ctx);
1899     }
1900 
1901     if (cf) {
1902         nullify_over(ctx);
1903     }
1904     tcg_r1 = load_gpr(ctx, r1);
1905     tcg_r2 = load_gpr(ctx, r2);
1906     ret = do_sub(ctx, rt, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, cf);
1907     return nullify_end(ctx, ret);
1908 }
1909 
1910 static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn,
1911                                const DisasInsn *di)
1912 {
1913     unsigned r2 = extract32(insn, 21, 5);
1914     unsigned r1 = extract32(insn, 16, 5);
1915     unsigned cf = extract32(insn, 12, 4);
1916     unsigned rt = extract32(insn,  0, 5);
1917     TCGv tcg_r1, tcg_r2;
1918     DisasJumpType ret;
1919 
1920     if (cf) {
1921         nullify_over(ctx);
1922     }
1923     tcg_r1 = load_gpr(ctx, r1);
1924     tcg_r2 = load_gpr(ctx, r2);
1925     ret = do_log(ctx, rt, tcg_r1, tcg_r2, cf, di->f.ttt);
1926     return nullify_end(ctx, ret);
1927 }
1928 
1929 /* OR r,0,t -> COPY (according to gas) */
1930 static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn,
1931                                 const DisasInsn *di)
1932 {
1933     unsigned r1 = extract32(insn, 16, 5);
1934     unsigned rt = extract32(insn,  0, 5);
1935 
1936     if (r1 == 0) {
1937         TCGv dest = dest_gpr(ctx, rt);
1938         tcg_gen_movi_tl(dest, 0);
1939         save_gpr(ctx, rt, dest);
1940     } else {
1941         save_gpr(ctx, rt, cpu_gr[r1]);
1942     }
1943     cond_free(&ctx->null_cond);
1944     return DISAS_NEXT;
1945 }
1946 
1947 static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn,
1948                                   const DisasInsn *di)
1949 {
1950     unsigned r2 = extract32(insn, 21, 5);
1951     unsigned r1 = extract32(insn, 16, 5);
1952     unsigned cf = extract32(insn, 12, 4);
1953     unsigned rt = extract32(insn,  0, 5);
1954     TCGv tcg_r1, tcg_r2;
1955     DisasJumpType ret;
1956 
1957     if (cf) {
1958         nullify_over(ctx);
1959     }
1960     tcg_r1 = load_gpr(ctx, r1);
1961     tcg_r2 = load_gpr(ctx, r2);
1962     ret = do_cmpclr(ctx, rt, tcg_r1, tcg_r2, cf);
1963     return nullify_end(ctx, ret);
1964 }
1965 
1966 static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn,
1967                                 const DisasInsn *di)
1968 {
1969     unsigned r2 = extract32(insn, 21, 5);
1970     unsigned r1 = extract32(insn, 16, 5);
1971     unsigned cf = extract32(insn, 12, 4);
1972     unsigned rt = extract32(insn,  0, 5);
1973     TCGv tcg_r1, tcg_r2;
1974     DisasJumpType ret;
1975 
1976     if (cf) {
1977         nullify_over(ctx);
1978     }
1979     tcg_r1 = load_gpr(ctx, r1);
1980     tcg_r2 = load_gpr(ctx, r2);
1981     ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_tl);
1982     return nullify_end(ctx, ret);
1983 }
1984 
1985 static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn,
1986                                   const DisasInsn *di)
1987 {
1988     unsigned r2 = extract32(insn, 21, 5);
1989     unsigned r1 = extract32(insn, 16, 5);
1990     unsigned cf = extract32(insn, 12, 4);
1991     unsigned is_tc = extract32(insn, 6, 1);
1992     unsigned rt = extract32(insn,  0, 5);
1993     TCGv tcg_r1, tcg_r2, tmp;
1994     DisasJumpType ret;
1995 
1996     if (cf) {
1997         nullify_over(ctx);
1998     }
1999     tcg_r1 = load_gpr(ctx, r1);
2000     tcg_r2 = load_gpr(ctx, r2);
2001     tmp = get_temp(ctx);
2002     tcg_gen_not_tl(tmp, tcg_r2);
2003     ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_tl);
2004     return nullify_end(ctx, ret);
2005 }
2006 
2007 static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn,
2008                                 const DisasInsn *di)
2009 {
2010     unsigned r2 = extract32(insn, 21, 5);
2011     unsigned cf = extract32(insn, 12, 4);
2012     unsigned is_i = extract32(insn, 6, 1);
2013     unsigned rt = extract32(insn,  0, 5);
2014     TCGv tmp;
2015     DisasJumpType ret;
2016 
2017     nullify_over(ctx);
2018 
2019     tmp = get_temp(ctx);
2020     tcg_gen_shri_tl(tmp, cpu_psw_cb, 3);
2021     if (!is_i) {
2022         tcg_gen_not_tl(tmp, tmp);
2023     }
2024     tcg_gen_andi_tl(tmp, tmp, 0x11111111);
2025     tcg_gen_muli_tl(tmp, tmp, 6);
2026     ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false,
2027                   is_i ? tcg_gen_add_tl : tcg_gen_sub_tl);
2028 
2029     return nullify_end(ctx, ret);
2030 }
2031 
2032 static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn,
2033                               const DisasInsn *di)
2034 {
2035     unsigned r2 = extract32(insn, 21, 5);
2036     unsigned r1 = extract32(insn, 16, 5);
2037     unsigned cf = extract32(insn, 12, 4);
2038     unsigned rt = extract32(insn,  0, 5);
2039     TCGv dest, add1, add2, addc, zero, in1, in2;
2040 
2041     nullify_over(ctx);
2042 
2043     in1 = load_gpr(ctx, r1);
2044     in2 = load_gpr(ctx, r2);
2045 
2046     add1 = tcg_temp_new();
2047     add2 = tcg_temp_new();
2048     addc = tcg_temp_new();
2049     dest = tcg_temp_new();
2050     zero = tcg_const_tl(0);
2051 
2052     /* Form R1 << 1 | PSW[CB]{8}.  */
2053     tcg_gen_add_tl(add1, in1, in1);
2054     tcg_gen_add_tl(add1, add1, cpu_psw_cb_msb);
2055 
2056     /* Add or subtract R2, depending on PSW[V].  Proper computation of
2057        carry{8} requires that we subtract via + ~R2 + 1, as described in
2058        the manual.  By extracting and masking V, we can produce the
2059        proper inputs to the addition without movcond.  */
2060     tcg_gen_sari_tl(addc, cpu_psw_v, TARGET_LONG_BITS - 1);
2061     tcg_gen_xor_tl(add2, in2, addc);
2062     tcg_gen_andi_tl(addc, addc, 1);
2063     /* ??? This is only correct for 32-bit.  */
2064     tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
2065     tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
2066 
2067     tcg_temp_free(addc);
2068     tcg_temp_free(zero);
2069 
2070     /* Write back the result register.  */
2071     save_gpr(ctx, rt, dest);
2072 
2073     /* Write back PSW[CB].  */
2074     tcg_gen_xor_tl(cpu_psw_cb, add1, add2);
2075     tcg_gen_xor_tl(cpu_psw_cb, cpu_psw_cb, dest);
2076 
2077     /* Write back PSW[V] for the division step.  */
2078     tcg_gen_neg_tl(cpu_psw_v, cpu_psw_cb_msb);
2079     tcg_gen_xor_tl(cpu_psw_v, cpu_psw_v, in2);
2080 
2081     /* Install the new nullification.  */
2082     if (cf) {
2083         TCGv sv;
2084         TCGV_UNUSED(sv);
2085         if (cf >> 1 == 6) {
2086             /* ??? The lshift is supposed to contribute to overflow.  */
2087             sv = do_add_sv(ctx, dest, add1, add2);
2088         }
2089         ctx->null_cond = do_cond(cf, dest, cpu_psw_cb_msb, sv);
2090     }
2091 
2092     tcg_temp_free(add1);
2093     tcg_temp_free(add2);
2094     tcg_temp_free(dest);
2095 
2096     return nullify_end(ctx, DISAS_NEXT);
2097 }
2098 
2099 static const DisasInsn table_arith_log[] = {
2100     { 0x08000240u, 0xfc00ffffu, trans_nop },  /* or x,y,0 */
2101     { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */
2102     { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_tl },
2103     { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_tl },
2104     { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_tl },
2105     { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_tl },
2106     { 0x08000880u, 0xfc000fe0u, trans_cmpclr },
2107     { 0x08000380u, 0xfc000fe0u, trans_uxor },
2108     { 0x08000980u, 0xfc000fa0u, trans_uaddcm },
2109     { 0x08000b80u, 0xfc1f0fa0u, trans_dcor },
2110     { 0x08000440u, 0xfc000fe0u, trans_ds },
2111     { 0x08000700u, 0xfc0007e0u, trans_add }, /* add */
2112     { 0x08000400u, 0xfc0006e0u, trans_sub }, /* sub; sub,b; sub,tsv */
2113     { 0x080004c0u, 0xfc0007e0u, trans_sub }, /* sub,tc; sub,tsv,tc */
2114     { 0x08000200u, 0xfc000320u, trans_add }, /* shladd */
2115 };
2116 
2117 static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn)
2118 {
2119     target_long im = low_sextract(insn, 0, 11);
2120     unsigned e1 = extract32(insn, 11, 1);
2121     unsigned cf = extract32(insn, 12, 4);
2122     unsigned rt = extract32(insn, 16, 5);
2123     unsigned r2 = extract32(insn, 21, 5);
2124     unsigned o1 = extract32(insn, 26, 1);
2125     TCGv tcg_im, tcg_r2;
2126     DisasJumpType ret;
2127 
2128     if (cf) {
2129         nullify_over(ctx);
2130     }
2131 
2132     tcg_im = load_const(ctx, im);
2133     tcg_r2 = load_gpr(ctx, r2);
2134     ret = do_add(ctx, rt, tcg_im, tcg_r2, 0, false, e1, !o1, false, cf);
2135 
2136     return nullify_end(ctx, ret);
2137 }
2138 
2139 static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn)
2140 {
2141     target_long im = low_sextract(insn, 0, 11);
2142     unsigned e1 = extract32(insn, 11, 1);
2143     unsigned cf = extract32(insn, 12, 4);
2144     unsigned rt = extract32(insn, 16, 5);
2145     unsigned r2 = extract32(insn, 21, 5);
2146     TCGv tcg_im, tcg_r2;
2147     DisasJumpType ret;
2148 
2149     if (cf) {
2150         nullify_over(ctx);
2151     }
2152 
2153     tcg_im = load_const(ctx, im);
2154     tcg_r2 = load_gpr(ctx, r2);
2155     ret = do_sub(ctx, rt, tcg_im, tcg_r2, e1, false, false, cf);
2156 
2157     return nullify_end(ctx, ret);
2158 }
2159 
2160 static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn)
2161 {
2162     target_long im = low_sextract(insn, 0, 11);
2163     unsigned cf = extract32(insn, 12, 4);
2164     unsigned rt = extract32(insn, 16, 5);
2165     unsigned r2 = extract32(insn, 21, 5);
2166     TCGv tcg_im, tcg_r2;
2167     DisasJumpType ret;
2168 
2169     if (cf) {
2170         nullify_over(ctx);
2171     }
2172 
2173     tcg_im = load_const(ctx, im);
2174     tcg_r2 = load_gpr(ctx, r2);
2175     ret = do_cmpclr(ctx, rt, tcg_im, tcg_r2, cf);
2176 
2177     return nullify_end(ctx, ret);
2178 }
2179 
2180 static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn,
2181                                     const DisasInsn *di)
2182 {
2183     unsigned rt = extract32(insn, 0, 5);
2184     unsigned m = extract32(insn, 5, 1);
2185     unsigned sz = extract32(insn, 6, 2);
2186     unsigned a = extract32(insn, 13, 1);
2187     int disp = low_sextract(insn, 16, 5);
2188     unsigned rb = extract32(insn, 21, 5);
2189     int modify = (m ? (a ? -1 : 1) : 0);
2190     TCGMemOp mop = MO_TE | sz;
2191 
2192     return do_load(ctx, rt, rb, 0, 0, disp, modify, mop);
2193 }
2194 
2195 static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn,
2196                                     const DisasInsn *di)
2197 {
2198     unsigned rt = extract32(insn, 0, 5);
2199     unsigned m = extract32(insn, 5, 1);
2200     unsigned sz = extract32(insn, 6, 2);
2201     unsigned u = extract32(insn, 13, 1);
2202     unsigned rx = extract32(insn, 16, 5);
2203     unsigned rb = extract32(insn, 21, 5);
2204     TCGMemOp mop = MO_TE | sz;
2205 
2206     return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, m, mop);
2207 }
2208 
2209 static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn,
2210                                     const DisasInsn *di)
2211 {
2212     int disp = low_sextract(insn, 0, 5);
2213     unsigned m = extract32(insn, 5, 1);
2214     unsigned sz = extract32(insn, 6, 2);
2215     unsigned a = extract32(insn, 13, 1);
2216     unsigned rr = extract32(insn, 16, 5);
2217     unsigned rb = extract32(insn, 21, 5);
2218     int modify = (m ? (a ? -1 : 1) : 0);
2219     TCGMemOp mop = MO_TE | sz;
2220 
2221     return do_store(ctx, rr, rb, disp, modify, mop);
2222 }
2223 
2224 static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn,
2225                                 const DisasInsn *di)
2226 {
2227     unsigned rt = extract32(insn, 0, 5);
2228     unsigned m = extract32(insn, 5, 1);
2229     unsigned i = extract32(insn, 12, 1);
2230     unsigned au = extract32(insn, 13, 1);
2231     unsigned rx = extract32(insn, 16, 5);
2232     unsigned rb = extract32(insn, 21, 5);
2233     TCGMemOp mop = MO_TEUL | MO_ALIGN_16;
2234     TCGv zero, addr, base, dest;
2235     int modify, disp = 0, scale = 0;
2236 
2237     nullify_over(ctx);
2238 
2239     /* ??? Share more code with do_load and do_load_{32,64}.  */
2240 
2241     if (i) {
2242         modify = (m ? (au ? -1 : 1) : 0);
2243         disp = low_sextract(rx, 0, 5);
2244         rx = 0;
2245     } else {
2246         modify = m;
2247         if (au) {
2248             scale = mop & MO_SIZE;
2249         }
2250     }
2251     if (modify) {
2252         /* Base register modification.  Make sure if RT == RB, we see
2253            the result of the load.  */
2254         dest = get_temp(ctx);
2255     } else {
2256         dest = dest_gpr(ctx, rt);
2257     }
2258 
2259     addr = tcg_temp_new();
2260     base = load_gpr(ctx, rb);
2261     if (rx) {
2262         tcg_gen_shli_tl(addr, cpu_gr[rx], scale);
2263         tcg_gen_add_tl(addr, addr, base);
2264     } else {
2265         tcg_gen_addi_tl(addr, base, disp);
2266     }
2267 
2268     zero = tcg_const_tl(0);
2269     tcg_gen_atomic_xchg_tl(dest, (modify <= 0 ? addr : base),
2270                            zero, MMU_USER_IDX, mop);
2271     if (modify) {
2272         save_gpr(ctx, rb, addr);
2273     }
2274     save_gpr(ctx, rt, dest);
2275 
2276     return nullify_end(ctx, DISAS_NEXT);
2277 }
2278 
2279 static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn,
2280                                 const DisasInsn *di)
2281 {
2282     target_long disp = low_sextract(insn, 0, 5);
2283     unsigned m = extract32(insn, 5, 1);
2284     unsigned a = extract32(insn, 13, 1);
2285     unsigned rt = extract32(insn, 16, 5);
2286     unsigned rb = extract32(insn, 21, 5);
2287     TCGv addr, val;
2288 
2289     nullify_over(ctx);
2290 
2291     addr = tcg_temp_new();
2292     if (m || disp == 0) {
2293         tcg_gen_mov_tl(addr, load_gpr(ctx, rb));
2294     } else {
2295         tcg_gen_addi_tl(addr, load_gpr(ctx, rb), disp);
2296     }
2297     val = load_gpr(ctx, rt);
2298 
2299     if (a) {
2300         gen_helper_stby_e(cpu_env, addr, val);
2301     } else {
2302         gen_helper_stby_b(cpu_env, addr, val);
2303     }
2304 
2305     if (m) {
2306         tcg_gen_addi_tl(addr, addr, disp);
2307         tcg_gen_andi_tl(addr, addr, ~3);
2308         save_gpr(ctx, rb, addr);
2309     }
2310     tcg_temp_free(addr);
2311 
2312     return nullify_end(ctx, DISAS_NEXT);
2313 }
2314 
2315 static const DisasInsn table_index_mem[] = {
2316     { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */
2317     { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */
2318     { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */
2319     { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
2320     { 0x0c001300u, 0xfc0013c0, trans_stby },
2321 };
2322 
2323 static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn)
2324 {
2325     unsigned rt = extract32(insn, 21, 5);
2326     target_long i = assemble_21(insn);
2327     TCGv tcg_rt = dest_gpr(ctx, rt);
2328 
2329     tcg_gen_movi_tl(tcg_rt, i);
2330     save_gpr(ctx, rt, tcg_rt);
2331     cond_free(&ctx->null_cond);
2332 
2333     return DISAS_NEXT;
2334 }
2335 
2336 static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn)
2337 {
2338     unsigned rt = extract32(insn, 21, 5);
2339     target_long i = assemble_21(insn);
2340     TCGv tcg_rt = load_gpr(ctx, rt);
2341     TCGv tcg_r1 = dest_gpr(ctx, 1);
2342 
2343     tcg_gen_addi_tl(tcg_r1, tcg_rt, i);
2344     save_gpr(ctx, 1, tcg_r1);
2345     cond_free(&ctx->null_cond);
2346 
2347     return DISAS_NEXT;
2348 }
2349 
2350 static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn)
2351 {
2352     unsigned rb = extract32(insn, 21, 5);
2353     unsigned rt = extract32(insn, 16, 5);
2354     target_long i = assemble_16(insn);
2355     TCGv tcg_rt = dest_gpr(ctx, rt);
2356 
2357     /* Special case rb == 0, for the LDI pseudo-op.
2358        The COPY pseudo-op is handled for free within tcg_gen_addi_tl.  */
2359     if (rb == 0) {
2360         tcg_gen_movi_tl(tcg_rt, i);
2361     } else {
2362         tcg_gen_addi_tl(tcg_rt, cpu_gr[rb], i);
2363     }
2364     save_gpr(ctx, rt, tcg_rt);
2365     cond_free(&ctx->null_cond);
2366 
2367     return DISAS_NEXT;
2368 }
2369 
2370 static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn,
2371                                 bool is_mod, TCGMemOp mop)
2372 {
2373     unsigned rb = extract32(insn, 21, 5);
2374     unsigned rt = extract32(insn, 16, 5);
2375     target_long i = assemble_16(insn);
2376 
2377     return do_load(ctx, rt, rb, 0, 0, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
2378 }
2379 
2380 static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn)
2381 {
2382     unsigned rb = extract32(insn, 21, 5);
2383     unsigned rt = extract32(insn, 16, 5);
2384     target_long i = assemble_16a(insn);
2385     unsigned ext2 = extract32(insn, 1, 2);
2386 
2387     switch (ext2) {
2388     case 0:
2389     case 1:
2390         /* FLDW without modification.  */
2391         return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0);
2392     case 2:
2393         /* LDW with modification.  Note that the sign of I selects
2394            post-dec vs pre-inc.  */
2395         return do_load(ctx, rt, rb, 0, 0, i, (i < 0 ? 1 : -1), MO_TEUL);
2396     default:
2397         return gen_illegal(ctx);
2398     }
2399 }
2400 
2401 static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn)
2402 {
2403     target_long i = assemble_16a(insn);
2404     unsigned t1 = extract32(insn, 1, 1);
2405     unsigned a = extract32(insn, 2, 1);
2406     unsigned t0 = extract32(insn, 16, 5);
2407     unsigned rb = extract32(insn, 21, 5);
2408 
2409     /* FLDW with modification.  */
2410     return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1));
2411 }
2412 
2413 static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn,
2414                                  bool is_mod, TCGMemOp mop)
2415 {
2416     unsigned rb = extract32(insn, 21, 5);
2417     unsigned rt = extract32(insn, 16, 5);
2418     target_long i = assemble_16(insn);
2419 
2420     return do_store(ctx, rt, rb, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
2421 }
2422 
2423 static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn)
2424 {
2425     unsigned rb = extract32(insn, 21, 5);
2426     unsigned rt = extract32(insn, 16, 5);
2427     target_long i = assemble_16a(insn);
2428     unsigned ext2 = extract32(insn, 1, 2);
2429 
2430     switch (ext2) {
2431     case 0:
2432     case 1:
2433         /* FSTW without modification.  */
2434         return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0);
2435     case 2:
2436         /* LDW with modification.  */
2437         return do_store(ctx, rt, rb, i, (i < 0 ? 1 : -1), MO_TEUL);
2438     default:
2439         return gen_illegal(ctx);
2440     }
2441 }
2442 
2443 static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn)
2444 {
2445     target_long i = assemble_16a(insn);
2446     unsigned t1 = extract32(insn, 1, 1);
2447     unsigned a = extract32(insn, 2, 1);
2448     unsigned t0 = extract32(insn, 16, 5);
2449     unsigned rb = extract32(insn, 21, 5);
2450 
2451     /* FSTW with modification.  */
2452     return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1));
2453 }
2454 
2455 static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn)
2456 {
2457     unsigned t0 = extract32(insn, 0, 5);
2458     unsigned m = extract32(insn, 5, 1);
2459     unsigned t1 = extract32(insn, 6, 1);
2460     unsigned ext3 = extract32(insn, 7, 3);
2461     /* unsigned cc = extract32(insn, 10, 2); */
2462     unsigned i = extract32(insn, 12, 1);
2463     unsigned ua = extract32(insn, 13, 1);
2464     unsigned rx = extract32(insn, 16, 5);
2465     unsigned rb = extract32(insn, 21, 5);
2466     unsigned rt = t1 * 32 + t0;
2467     int modify = (m ? (ua ? -1 : 1) : 0);
2468     int disp, scale;
2469 
2470     if (i == 0) {
2471         scale = (ua ? 2 : 0);
2472         disp = 0;
2473         modify = m;
2474     } else {
2475         disp = low_sextract(rx, 0, 5);
2476         scale = 0;
2477         rx = 0;
2478         modify = (m ? (ua ? -1 : 1) : 0);
2479     }
2480 
2481     switch (ext3) {
2482     case 0: /* FLDW */
2483         return do_floadw(ctx, rt, rb, rx, scale, disp, modify);
2484     case 4: /* FSTW */
2485         return do_fstorew(ctx, rt, rb, rx, scale, disp, modify);
2486     }
2487     return gen_illegal(ctx);
2488 }
2489 
2490 static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn)
2491 {
2492     unsigned rt = extract32(insn, 0, 5);
2493     unsigned m = extract32(insn, 5, 1);
2494     unsigned ext4 = extract32(insn, 6, 4);
2495     /* unsigned cc = extract32(insn, 10, 2); */
2496     unsigned i = extract32(insn, 12, 1);
2497     unsigned ua = extract32(insn, 13, 1);
2498     unsigned rx = extract32(insn, 16, 5);
2499     unsigned rb = extract32(insn, 21, 5);
2500     int modify = (m ? (ua ? -1 : 1) : 0);
2501     int disp, scale;
2502 
2503     if (i == 0) {
2504         scale = (ua ? 3 : 0);
2505         disp = 0;
2506         modify = m;
2507     } else {
2508         disp = low_sextract(rx, 0, 5);
2509         scale = 0;
2510         rx = 0;
2511         modify = (m ? (ua ? -1 : 1) : 0);
2512     }
2513 
2514     switch (ext4) {
2515     case 0: /* FLDD */
2516         return do_floadd(ctx, rt, rb, rx, scale, disp, modify);
2517     case 8: /* FSTD */
2518         return do_fstored(ctx, rt, rb, rx, scale, disp, modify);
2519     default:
2520         return gen_illegal(ctx);
2521     }
2522 }
2523 
2524 static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn,
2525                                 bool is_true, bool is_imm, bool is_dw)
2526 {
2527     target_long disp = assemble_12(insn) * 4;
2528     unsigned n = extract32(insn, 1, 1);
2529     unsigned c = extract32(insn, 13, 3);
2530     unsigned r = extract32(insn, 21, 5);
2531     unsigned cf = c * 2 + !is_true;
2532     TCGv dest, in1, in2, sv;
2533     DisasCond cond;
2534 
2535     nullify_over(ctx);
2536 
2537     if (is_imm) {
2538         in1 = load_const(ctx, low_sextract(insn, 16, 5));
2539     } else {
2540         in1 = load_gpr(ctx, extract32(insn, 16, 5));
2541     }
2542     in2 = load_gpr(ctx, r);
2543     dest = get_temp(ctx);
2544 
2545     tcg_gen_sub_tl(dest, in1, in2);
2546 
2547     TCGV_UNUSED(sv);
2548     if (c == 6) {
2549         sv = do_sub_sv(ctx, dest, in1, in2);
2550     }
2551 
2552     cond = do_sub_cond(cf, dest, in1, in2, sv);
2553     return do_cbranch(ctx, disp, n, &cond);
2554 }
2555 
2556 static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn,
2557                                 bool is_true, bool is_imm)
2558 {
2559     target_long disp = assemble_12(insn) * 4;
2560     unsigned n = extract32(insn, 1, 1);
2561     unsigned c = extract32(insn, 13, 3);
2562     unsigned r = extract32(insn, 21, 5);
2563     unsigned cf = c * 2 + !is_true;
2564     TCGv dest, in1, in2, sv, cb_msb;
2565     DisasCond cond;
2566 
2567     nullify_over(ctx);
2568 
2569     if (is_imm) {
2570         in1 = load_const(ctx, low_sextract(insn, 16, 5));
2571     } else {
2572         in1 = load_gpr(ctx, extract32(insn, 16, 5));
2573     }
2574     in2 = load_gpr(ctx, r);
2575     dest = dest_gpr(ctx, r);
2576     TCGV_UNUSED(sv);
2577     TCGV_UNUSED(cb_msb);
2578 
2579     switch (c) {
2580     default:
2581         tcg_gen_add_tl(dest, in1, in2);
2582         break;
2583     case 4: case 5:
2584         cb_msb = get_temp(ctx);
2585         tcg_gen_movi_tl(cb_msb, 0);
2586         tcg_gen_add2_tl(dest, cb_msb, in1, cb_msb, in2, cb_msb);
2587         break;
2588     case 6:
2589         tcg_gen_add_tl(dest, in1, in2);
2590         sv = do_add_sv(ctx, dest, in1, in2);
2591         break;
2592     }
2593 
2594     cond = do_cond(cf, dest, cb_msb, sv);
2595     return do_cbranch(ctx, disp, n, &cond);
2596 }
2597 
2598 static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn)
2599 {
2600     target_long disp = assemble_12(insn) * 4;
2601     unsigned n = extract32(insn, 1, 1);
2602     unsigned c = extract32(insn, 15, 1);
2603     unsigned r = extract32(insn, 16, 5);
2604     unsigned p = extract32(insn, 21, 5);
2605     unsigned i = extract32(insn, 26, 1);
2606     TCGv tmp, tcg_r;
2607     DisasCond cond;
2608 
2609     nullify_over(ctx);
2610 
2611     tmp = tcg_temp_new();
2612     tcg_r = load_gpr(ctx, r);
2613     if (i) {
2614         tcg_gen_shli_tl(tmp, tcg_r, p);
2615     } else {
2616         tcg_gen_shl_tl(tmp, tcg_r, cpu_sar);
2617     }
2618 
2619     cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp);
2620     tcg_temp_free(tmp);
2621     return do_cbranch(ctx, disp, n, &cond);
2622 }
2623 
2624 static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm)
2625 {
2626     target_long disp = assemble_12(insn) * 4;
2627     unsigned n = extract32(insn, 1, 1);
2628     unsigned c = extract32(insn, 13, 3);
2629     unsigned t = extract32(insn, 16, 5);
2630     unsigned r = extract32(insn, 21, 5);
2631     TCGv dest;
2632     DisasCond cond;
2633 
2634     nullify_over(ctx);
2635 
2636     dest = dest_gpr(ctx, r);
2637     if (is_imm) {
2638         tcg_gen_movi_tl(dest, low_sextract(t, 0, 5));
2639     } else if (t == 0) {
2640         tcg_gen_movi_tl(dest, 0);
2641     } else {
2642         tcg_gen_mov_tl(dest, cpu_gr[t]);
2643     }
2644 
2645     cond = do_sed_cond(c, dest);
2646     return do_cbranch(ctx, disp, n, &cond);
2647 }
2648 
2649 static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn,
2650                                     const DisasInsn *di)
2651 {
2652     unsigned rt = extract32(insn, 0, 5);
2653     unsigned c = extract32(insn, 13, 3);
2654     unsigned r1 = extract32(insn, 16, 5);
2655     unsigned r2 = extract32(insn, 21, 5);
2656     TCGv dest;
2657 
2658     if (c) {
2659         nullify_over(ctx);
2660     }
2661 
2662     dest = dest_gpr(ctx, rt);
2663     if (r1 == 0) {
2664         tcg_gen_ext32u_tl(dest, load_gpr(ctx, r2));
2665         tcg_gen_shr_tl(dest, dest, cpu_sar);
2666     } else if (r1 == r2) {
2667         TCGv_i32 t32 = tcg_temp_new_i32();
2668         tcg_gen_trunc_tl_i32(t32, load_gpr(ctx, r2));
2669         tcg_gen_rotr_i32(t32, t32, cpu_sar);
2670         tcg_gen_extu_i32_tl(dest, t32);
2671         tcg_temp_free_i32(t32);
2672     } else {
2673         TCGv_i64 t = tcg_temp_new_i64();
2674         TCGv_i64 s = tcg_temp_new_i64();
2675 
2676         tcg_gen_concat_tl_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1));
2677         tcg_gen_extu_tl_i64(s, cpu_sar);
2678         tcg_gen_shr_i64(t, t, s);
2679         tcg_gen_trunc_i64_tl(dest, t);
2680 
2681         tcg_temp_free_i64(t);
2682         tcg_temp_free_i64(s);
2683     }
2684     save_gpr(ctx, rt, dest);
2685 
2686     /* Install the new nullification.  */
2687     cond_free(&ctx->null_cond);
2688     if (c) {
2689         ctx->null_cond = do_sed_cond(c, dest);
2690     }
2691     return nullify_end(ctx, DISAS_NEXT);
2692 }
2693 
2694 static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn,
2695                                      const DisasInsn *di)
2696 {
2697     unsigned rt = extract32(insn, 0, 5);
2698     unsigned cpos = extract32(insn, 5, 5);
2699     unsigned c = extract32(insn, 13, 3);
2700     unsigned r1 = extract32(insn, 16, 5);
2701     unsigned r2 = extract32(insn, 21, 5);
2702     unsigned sa = 31 - cpos;
2703     TCGv dest, t2;
2704 
2705     if (c) {
2706         nullify_over(ctx);
2707     }
2708 
2709     dest = dest_gpr(ctx, rt);
2710     t2 = load_gpr(ctx, r2);
2711     if (r1 == r2) {
2712         TCGv_i32 t32 = tcg_temp_new_i32();
2713         tcg_gen_trunc_tl_i32(t32, t2);
2714         tcg_gen_rotri_i32(t32, t32, sa);
2715         tcg_gen_extu_i32_tl(dest, t32);
2716         tcg_temp_free_i32(t32);
2717     } else if (r1 == 0) {
2718         tcg_gen_extract_tl(dest, t2, sa, 32 - sa);
2719     } else {
2720         TCGv t0 = tcg_temp_new();
2721         tcg_gen_extract_tl(t0, t2, sa, 32 - sa);
2722         tcg_gen_deposit_tl(dest, t0, cpu_gr[r1], 32 - sa, sa);
2723         tcg_temp_free(t0);
2724     }
2725     save_gpr(ctx, rt, dest);
2726 
2727     /* Install the new nullification.  */
2728     cond_free(&ctx->null_cond);
2729     if (c) {
2730         ctx->null_cond = do_sed_cond(c, dest);
2731     }
2732     return nullify_end(ctx, DISAS_NEXT);
2733 }
2734 
2735 static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn,
2736                                      const DisasInsn *di)
2737 {
2738     unsigned clen = extract32(insn, 0, 5);
2739     unsigned is_se = extract32(insn, 10, 1);
2740     unsigned c = extract32(insn, 13, 3);
2741     unsigned rt = extract32(insn, 16, 5);
2742     unsigned rr = extract32(insn, 21, 5);
2743     unsigned len = 32 - clen;
2744     TCGv dest, src, tmp;
2745 
2746     if (c) {
2747         nullify_over(ctx);
2748     }
2749 
2750     dest = dest_gpr(ctx, rt);
2751     src = load_gpr(ctx, rr);
2752     tmp = tcg_temp_new();
2753 
2754     /* Recall that SAR is using big-endian bit numbering.  */
2755     tcg_gen_xori_tl(tmp, cpu_sar, TARGET_LONG_BITS - 1);
2756     if (is_se) {
2757         tcg_gen_sar_tl(dest, src, tmp);
2758         tcg_gen_sextract_tl(dest, dest, 0, len);
2759     } else {
2760         tcg_gen_shr_tl(dest, src, tmp);
2761         tcg_gen_extract_tl(dest, dest, 0, len);
2762     }
2763     tcg_temp_free(tmp);
2764     save_gpr(ctx, rt, dest);
2765 
2766     /* Install the new nullification.  */
2767     cond_free(&ctx->null_cond);
2768     if (c) {
2769         ctx->null_cond = do_sed_cond(c, dest);
2770     }
2771     return nullify_end(ctx, DISAS_NEXT);
2772 }
2773 
2774 static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn,
2775                                      const DisasInsn *di)
2776 {
2777     unsigned clen = extract32(insn, 0, 5);
2778     unsigned pos = extract32(insn, 5, 5);
2779     unsigned is_se = extract32(insn, 10, 1);
2780     unsigned c = extract32(insn, 13, 3);
2781     unsigned rt = extract32(insn, 16, 5);
2782     unsigned rr = extract32(insn, 21, 5);
2783     unsigned len = 32 - clen;
2784     unsigned cpos = 31 - pos;
2785     TCGv dest, src;
2786 
2787     if (c) {
2788         nullify_over(ctx);
2789     }
2790 
2791     dest = dest_gpr(ctx, rt);
2792     src = load_gpr(ctx, rr);
2793     if (is_se) {
2794         tcg_gen_sextract_tl(dest, src, cpos, len);
2795     } else {
2796         tcg_gen_extract_tl(dest, src, cpos, len);
2797     }
2798     save_gpr(ctx, rt, dest);
2799 
2800     /* Install the new nullification.  */
2801     cond_free(&ctx->null_cond);
2802     if (c) {
2803         ctx->null_cond = do_sed_cond(c, dest);
2804     }
2805     return nullify_end(ctx, DISAS_NEXT);
2806 }
2807 
2808 static const DisasInsn table_sh_ex[] = {
2809     { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar },
2810     { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm },
2811     { 0xd0001000u, 0xfc001be0u, trans_extrw_sar },
2812     { 0xd0001800u, 0xfc001800u, trans_extrw_imm },
2813 };
2814 
2815 static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn,
2816                                       const DisasInsn *di)
2817 {
2818     unsigned clen = extract32(insn, 0, 5);
2819     unsigned cpos = extract32(insn, 5, 5);
2820     unsigned nz = extract32(insn, 10, 1);
2821     unsigned c = extract32(insn, 13, 3);
2822     target_long val = low_sextract(insn, 16, 5);
2823     unsigned rt = extract32(insn, 21, 5);
2824     unsigned len = 32 - clen;
2825     target_long mask0, mask1;
2826     TCGv dest;
2827 
2828     if (c) {
2829         nullify_over(ctx);
2830     }
2831     if (cpos + len > 32) {
2832         len = 32 - cpos;
2833     }
2834 
2835     dest = dest_gpr(ctx, rt);
2836     mask0 = deposit64(0, cpos, len, val);
2837     mask1 = deposit64(-1, cpos, len, val);
2838 
2839     if (nz) {
2840         TCGv src = load_gpr(ctx, rt);
2841         if (mask1 != -1) {
2842             tcg_gen_andi_tl(dest, src, mask1);
2843             src = dest;
2844         }
2845         tcg_gen_ori_tl(dest, src, mask0);
2846     } else {
2847         tcg_gen_movi_tl(dest, mask0);
2848     }
2849     save_gpr(ctx, rt, dest);
2850 
2851     /* Install the new nullification.  */
2852     cond_free(&ctx->null_cond);
2853     if (c) {
2854         ctx->null_cond = do_sed_cond(c, dest);
2855     }
2856     return nullify_end(ctx, DISAS_NEXT);
2857 }
2858 
2859 static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn,
2860                                     const DisasInsn *di)
2861 {
2862     unsigned clen = extract32(insn, 0, 5);
2863     unsigned cpos = extract32(insn, 5, 5);
2864     unsigned nz = extract32(insn, 10, 1);
2865     unsigned c = extract32(insn, 13, 3);
2866     unsigned rr = extract32(insn, 16, 5);
2867     unsigned rt = extract32(insn, 21, 5);
2868     unsigned rs = nz ? rt : 0;
2869     unsigned len = 32 - clen;
2870     TCGv dest, val;
2871 
2872     if (c) {
2873         nullify_over(ctx);
2874     }
2875     if (cpos + len > 32) {
2876         len = 32 - cpos;
2877     }
2878 
2879     dest = dest_gpr(ctx, rt);
2880     val = load_gpr(ctx, rr);
2881     if (rs == 0) {
2882         tcg_gen_deposit_z_tl(dest, val, cpos, len);
2883     } else {
2884         tcg_gen_deposit_tl(dest, cpu_gr[rs], val, cpos, len);
2885     }
2886     save_gpr(ctx, rt, dest);
2887 
2888     /* Install the new nullification.  */
2889     cond_free(&ctx->null_cond);
2890     if (c) {
2891         ctx->null_cond = do_sed_cond(c, dest);
2892     }
2893     return nullify_end(ctx, DISAS_NEXT);
2894 }
2895 
2896 static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn,
2897                                     const DisasInsn *di)
2898 {
2899     unsigned clen = extract32(insn, 0, 5);
2900     unsigned nz = extract32(insn, 10, 1);
2901     unsigned i = extract32(insn, 12, 1);
2902     unsigned c = extract32(insn, 13, 3);
2903     unsigned rt = extract32(insn, 21, 5);
2904     unsigned rs = nz ? rt : 0;
2905     unsigned len = 32 - clen;
2906     TCGv val, mask, tmp, shift, dest;
2907     unsigned msb = 1U << (len - 1);
2908 
2909     if (c) {
2910         nullify_over(ctx);
2911     }
2912 
2913     if (i) {
2914         val = load_const(ctx, low_sextract(insn, 16, 5));
2915     } else {
2916         val = load_gpr(ctx, extract32(insn, 16, 5));
2917     }
2918     dest = dest_gpr(ctx, rt);
2919     shift = tcg_temp_new();
2920     tmp = tcg_temp_new();
2921 
2922     /* Convert big-endian bit numbering in SAR to left-shift.  */
2923     tcg_gen_xori_tl(shift, cpu_sar, TARGET_LONG_BITS - 1);
2924 
2925     mask = tcg_const_tl(msb + (msb - 1));
2926     tcg_gen_and_tl(tmp, val, mask);
2927     if (rs) {
2928         tcg_gen_shl_tl(mask, mask, shift);
2929         tcg_gen_shl_tl(tmp, tmp, shift);
2930         tcg_gen_andc_tl(dest, cpu_gr[rs], mask);
2931         tcg_gen_or_tl(dest, dest, tmp);
2932     } else {
2933         tcg_gen_shl_tl(dest, tmp, shift);
2934     }
2935     tcg_temp_free(shift);
2936     tcg_temp_free(mask);
2937     tcg_temp_free(tmp);
2938     save_gpr(ctx, rt, dest);
2939 
2940     /* Install the new nullification.  */
2941     cond_free(&ctx->null_cond);
2942     if (c) {
2943         ctx->null_cond = do_sed_cond(c, dest);
2944     }
2945     return nullify_end(ctx, DISAS_NEXT);
2946 }
2947 
2948 static const DisasInsn table_depw[] = {
2949     { 0xd4000000u, 0xfc000be0u, trans_depw_sar },
2950     { 0xd4000800u, 0xfc001800u, trans_depw_imm },
2951     { 0xd4001800u, 0xfc001800u, trans_depw_imm_c },
2952 };
2953 
2954 static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l)
2955 {
2956     unsigned n = extract32(insn, 1, 1);
2957     unsigned b = extract32(insn, 21, 5);
2958     target_long disp = assemble_17(insn);
2959 
2960     /* unsigned s = low_uextract(insn, 13, 3); */
2961     /* ??? It seems like there should be a good way of using
2962        "be disp(sr2, r0)", the canonical gateway entry mechanism
2963        to our advantage.  But that appears to be inconvenient to
2964        manage along side branch delay slots.  Therefore we handle
2965        entry into the gateway page via absolute address.  */
2966 
2967     /* Since we don't implement spaces, just branch.  Do notice the special
2968        case of "be disp(*,r0)" using a direct branch to disp, so that we can
2969        goto_tb to the TB containing the syscall.  */
2970     if (b == 0) {
2971         return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
2972     } else {
2973         TCGv tmp = get_temp(ctx);
2974         tcg_gen_addi_tl(tmp, load_gpr(ctx, b), disp);
2975         return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
2976     }
2977 }
2978 
2979 static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
2980                               const DisasInsn *di)
2981 {
2982     unsigned n = extract32(insn, 1, 1);
2983     unsigned link = extract32(insn, 21, 5);
2984     target_long disp = assemble_17(insn);
2985 
2986     return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
2987 }
2988 
2989 static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
2990                                    const DisasInsn *di)
2991 {
2992     unsigned n = extract32(insn, 1, 1);
2993     target_long disp = assemble_22(insn);
2994 
2995     return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n);
2996 }
2997 
2998 static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn,
2999                                const DisasInsn *di)
3000 {
3001     unsigned n = extract32(insn, 1, 1);
3002     unsigned rx = extract32(insn, 16, 5);
3003     unsigned link = extract32(insn, 21, 5);
3004     TCGv tmp = get_temp(ctx);
3005 
3006     tcg_gen_shli_tl(tmp, load_gpr(ctx, rx), 3);
3007     tcg_gen_addi_tl(tmp, tmp, ctx->iaoq_f + 8);
3008     return do_ibranch(ctx, tmp, link, n);
3009 }
3010 
3011 static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn,
3012                               const DisasInsn *di)
3013 {
3014     unsigned n = extract32(insn, 1, 1);
3015     unsigned rx = extract32(insn, 16, 5);
3016     unsigned rb = extract32(insn, 21, 5);
3017     TCGv dest;
3018 
3019     if (rx == 0) {
3020         dest = load_gpr(ctx, rb);
3021     } else {
3022         dest = get_temp(ctx);
3023         tcg_gen_shli_tl(dest, load_gpr(ctx, rx), 3);
3024         tcg_gen_add_tl(dest, dest, load_gpr(ctx, rb));
3025     }
3026     return do_ibranch(ctx, dest, 0, n);
3027 }
3028 
3029 static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn,
3030                                const DisasInsn *di)
3031 {
3032     unsigned n = extract32(insn, 1, 1);
3033     unsigned rb = extract32(insn, 21, 5);
3034     unsigned link = extract32(insn, 13, 1) ? 2 : 0;
3035 
3036     return do_ibranch(ctx, load_gpr(ctx, rb), link, n);
3037 }
3038 
3039 static const DisasInsn table_branch[] = {
3040     { 0xe8000000u, 0xfc006000u, trans_bl }, /* B,L and B,L,PUSH */
3041     { 0xe800a000u, 0xfc00e000u, trans_bl_long },
3042     { 0xe8004000u, 0xfc00fffdu, trans_blr },
3043     { 0xe800c000u, 0xfc00fffdu, trans_bv },
3044     { 0xe800d000u, 0xfc00dffcu, trans_bve },
3045 };
3046 
3047 static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
3048                                       const DisasInsn *di)
3049 {
3050     unsigned rt = extract32(insn, 0, 5);
3051     unsigned ra = extract32(insn, 21, 5);
3052     return do_fop_wew(ctx, rt, ra, di->f.wew);
3053 }
3054 
3055 static DisasJumpType trans_fop_wew_0e(DisasContext *ctx, uint32_t insn,
3056                                       const DisasInsn *di)
3057 {
3058     unsigned rt = assemble_rt64(insn);
3059     unsigned ra = assemble_ra64(insn);
3060     return do_fop_wew(ctx, rt, ra, di->f.wew);
3061 }
3062 
3063 static DisasJumpType trans_fop_ded(DisasContext *ctx, uint32_t insn,
3064                                    const DisasInsn *di)
3065 {
3066     unsigned rt = extract32(insn, 0, 5);
3067     unsigned ra = extract32(insn, 21, 5);
3068     return do_fop_ded(ctx, rt, ra, di->f.ded);
3069 }
3070 
3071 static DisasJumpType trans_fop_wed_0c(DisasContext *ctx, uint32_t insn,
3072                                       const DisasInsn *di)
3073 {
3074     unsigned rt = extract32(insn, 0, 5);
3075     unsigned ra = extract32(insn, 21, 5);
3076     return do_fop_wed(ctx, rt, ra, di->f.wed);
3077 }
3078 
3079 static DisasJumpType trans_fop_wed_0e(DisasContext *ctx, uint32_t insn,
3080                                       const DisasInsn *di)
3081 {
3082     unsigned rt = assemble_rt64(insn);
3083     unsigned ra = extract32(insn, 21, 5);
3084     return do_fop_wed(ctx, rt, ra, di->f.wed);
3085 }
3086 
3087 static DisasJumpType trans_fop_dew_0c(DisasContext *ctx, uint32_t insn,
3088                                       const DisasInsn *di)
3089 {
3090     unsigned rt = extract32(insn, 0, 5);
3091     unsigned ra = extract32(insn, 21, 5);
3092     return do_fop_dew(ctx, rt, ra, di->f.dew);
3093 }
3094 
3095 static DisasJumpType trans_fop_dew_0e(DisasContext *ctx, uint32_t insn,
3096                                       const DisasInsn *di)
3097 {
3098     unsigned rt = extract32(insn, 0, 5);
3099     unsigned ra = assemble_ra64(insn);
3100     return do_fop_dew(ctx, rt, ra, di->f.dew);
3101 }
3102 
3103 static DisasJumpType trans_fop_weww_0c(DisasContext *ctx, uint32_t insn,
3104                                        const DisasInsn *di)
3105 {
3106     unsigned rt = extract32(insn, 0, 5);
3107     unsigned rb = extract32(insn, 16, 5);
3108     unsigned ra = extract32(insn, 21, 5);
3109     return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
3110 }
3111 
3112 static DisasJumpType trans_fop_weww_0e(DisasContext *ctx, uint32_t insn,
3113                                        const DisasInsn *di)
3114 {
3115     unsigned rt = assemble_rt64(insn);
3116     unsigned rb = assemble_rb64(insn);
3117     unsigned ra = assemble_ra64(insn);
3118     return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
3119 }
3120 
3121 static DisasJumpType trans_fop_dedd(DisasContext *ctx, uint32_t insn,
3122                                     const DisasInsn *di)
3123 {
3124     unsigned rt = extract32(insn, 0, 5);
3125     unsigned rb = extract32(insn, 16, 5);
3126     unsigned ra = extract32(insn, 21, 5);
3127     return do_fop_dedd(ctx, rt, ra, rb, di->f.dedd);
3128 }
3129 
3130 static void gen_fcpy_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3131 {
3132     tcg_gen_mov_i32(dst, src);
3133 }
3134 
3135 static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3136 {
3137     tcg_gen_mov_i64(dst, src);
3138 }
3139 
3140 static void gen_fabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3141 {
3142     tcg_gen_andi_i32(dst, src, INT32_MAX);
3143 }
3144 
3145 static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3146 {
3147     tcg_gen_andi_i64(dst, src, INT64_MAX);
3148 }
3149 
3150 static void gen_fneg_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3151 {
3152     tcg_gen_xori_i32(dst, src, INT32_MIN);
3153 }
3154 
3155 static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3156 {
3157     tcg_gen_xori_i64(dst, src, INT64_MIN);
3158 }
3159 
3160 static void gen_fnegabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3161 {
3162     tcg_gen_ori_i32(dst, src, INT32_MIN);
3163 }
3164 
3165 static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3166 {
3167     tcg_gen_ori_i64(dst, src, INT64_MIN);
3168 }
3169 
3170 static DisasJumpType do_fcmp_s(DisasContext *ctx, unsigned ra, unsigned rb,
3171                                unsigned y, unsigned c)
3172 {
3173     TCGv_i32 ta, tb, tc, ty;
3174 
3175     nullify_over(ctx);
3176 
3177     ta = load_frw0_i32(ra);
3178     tb = load_frw0_i32(rb);
3179     ty = tcg_const_i32(y);
3180     tc = tcg_const_i32(c);
3181 
3182     gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
3183 
3184     tcg_temp_free_i32(ta);
3185     tcg_temp_free_i32(tb);
3186     tcg_temp_free_i32(ty);
3187     tcg_temp_free_i32(tc);
3188 
3189     return nullify_end(ctx, DISAS_NEXT);
3190 }
3191 
3192 static DisasJumpType trans_fcmp_s_0c(DisasContext *ctx, uint32_t insn,
3193                                      const DisasInsn *di)
3194 {
3195     unsigned c = extract32(insn, 0, 5);
3196     unsigned y = extract32(insn, 13, 3);
3197     unsigned rb = extract32(insn, 16, 5);
3198     unsigned ra = extract32(insn, 21, 5);
3199     return do_fcmp_s(ctx, ra, rb, y, c);
3200 }
3201 
3202 static DisasJumpType trans_fcmp_s_0e(DisasContext *ctx, uint32_t insn,
3203                                      const DisasInsn *di)
3204 {
3205     unsigned c = extract32(insn, 0, 5);
3206     unsigned y = extract32(insn, 13, 3);
3207     unsigned rb = assemble_rb64(insn);
3208     unsigned ra = assemble_ra64(insn);
3209     return do_fcmp_s(ctx, ra, rb, y, c);
3210 }
3211 
3212 static DisasJumpType trans_fcmp_d(DisasContext *ctx, uint32_t insn,
3213                                   const DisasInsn *di)
3214 {
3215     unsigned c = extract32(insn, 0, 5);
3216     unsigned y = extract32(insn, 13, 3);
3217     unsigned rb = extract32(insn, 16, 5);
3218     unsigned ra = extract32(insn, 21, 5);
3219     TCGv_i64 ta, tb;
3220     TCGv_i32 tc, ty;
3221 
3222     nullify_over(ctx);
3223 
3224     ta = load_frd0(ra);
3225     tb = load_frd0(rb);
3226     ty = tcg_const_i32(y);
3227     tc = tcg_const_i32(c);
3228 
3229     gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
3230 
3231     tcg_temp_free_i64(ta);
3232     tcg_temp_free_i64(tb);
3233     tcg_temp_free_i32(ty);
3234     tcg_temp_free_i32(tc);
3235 
3236     return nullify_end(ctx, DISAS_NEXT);
3237 }
3238 
3239 static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn,
3240                                    const DisasInsn *di)
3241 {
3242     unsigned y = extract32(insn, 13, 3);
3243     unsigned cbit = (y ^ 1) - 1;
3244     TCGv t;
3245 
3246     nullify_over(ctx);
3247 
3248     t = tcg_temp_new();
3249     tcg_gen_ld32u_tl(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3250     tcg_gen_extract_tl(t, t, 21 - cbit, 1);
3251     ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3252     tcg_temp_free(t);
3253 
3254     return nullify_end(ctx, DISAS_NEXT);
3255 }
3256 
3257 static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn,
3258                                    const DisasInsn *di)
3259 {
3260     unsigned c = extract32(insn, 0, 5);
3261     int mask;
3262     bool inv = false;
3263     TCGv t;
3264 
3265     nullify_over(ctx);
3266 
3267     t = tcg_temp_new();
3268     tcg_gen_ld32u_tl(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3269 
3270     switch (c) {
3271     case 0: /* simple */
3272         tcg_gen_andi_tl(t, t, 0x4000000);
3273         ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3274         goto done;
3275     case 2: /* rej */
3276         inv = true;
3277         /* fallthru */
3278     case 1: /* acc */
3279         mask = 0x43ff800;
3280         break;
3281     case 6: /* rej8 */
3282         inv = true;
3283         /* fallthru */
3284     case 5: /* acc8 */
3285         mask = 0x43f8000;
3286         break;
3287     case 9: /* acc6 */
3288         mask = 0x43e0000;
3289         break;
3290     case 13: /* acc4 */
3291         mask = 0x4380000;
3292         break;
3293     case 17: /* acc2 */
3294         mask = 0x4200000;
3295         break;
3296     default:
3297         return gen_illegal(ctx);
3298     }
3299     if (inv) {
3300         TCGv c = load_const(ctx, mask);
3301         tcg_gen_or_tl(t, t, c);
3302         ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
3303     } else {
3304         tcg_gen_andi_tl(t, t, mask);
3305         ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
3306     }
3307  done:
3308     return nullify_end(ctx, DISAS_NEXT);
3309 }
3310 
3311 static DisasJumpType trans_xmpyu(DisasContext *ctx, uint32_t insn,
3312                                  const DisasInsn *di)
3313 {
3314     unsigned rt = extract32(insn, 0, 5);
3315     unsigned rb = assemble_rb64(insn);
3316     unsigned ra = assemble_ra64(insn);
3317     TCGv_i64 a, b;
3318 
3319     nullify_over(ctx);
3320 
3321     a = load_frw0_i64(ra);
3322     b = load_frw0_i64(rb);
3323     tcg_gen_mul_i64(a, a, b);
3324     save_frd(rt, a);
3325     tcg_temp_free_i64(a);
3326     tcg_temp_free_i64(b);
3327 
3328     return nullify_end(ctx, DISAS_NEXT);
3329 }
3330 
3331 #define FOP_DED  trans_fop_ded, .f.ded
3332 #define FOP_DEDD trans_fop_dedd, .f.dedd
3333 
3334 #define FOP_WEW  trans_fop_wew_0c, .f.wew
3335 #define FOP_DEW  trans_fop_dew_0c, .f.dew
3336 #define FOP_WED  trans_fop_wed_0c, .f.wed
3337 #define FOP_WEWW trans_fop_weww_0c, .f.weww
3338 
3339 static const DisasInsn table_float_0c[] = {
3340     /* floating point class zero */
3341     { 0x30004000, 0xfc1fffe0, FOP_WEW = gen_fcpy_s },
3342     { 0x30006000, 0xfc1fffe0, FOP_WEW = gen_fabs_s },
3343     { 0x30008000, 0xfc1fffe0, FOP_WEW = gen_helper_fsqrt_s },
3344     { 0x3000a000, 0xfc1fffe0, FOP_WEW = gen_helper_frnd_s },
3345     { 0x3000c000, 0xfc1fffe0, FOP_WEW = gen_fneg_s },
3346     { 0x3000e000, 0xfc1fffe0, FOP_WEW = gen_fnegabs_s },
3347 
3348     { 0x30004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
3349     { 0x30006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
3350     { 0x30008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
3351     { 0x3000a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
3352     { 0x3000c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
3353     { 0x3000e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
3354 
3355     /* floating point class three */
3356     { 0x30000600, 0xfc00ffe0, FOP_WEWW = gen_helper_fadd_s },
3357     { 0x30002600, 0xfc00ffe0, FOP_WEWW = gen_helper_fsub_s },
3358     { 0x30004600, 0xfc00ffe0, FOP_WEWW = gen_helper_fmpy_s },
3359     { 0x30006600, 0xfc00ffe0, FOP_WEWW = gen_helper_fdiv_s },
3360 
3361     { 0x30000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
3362     { 0x30002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
3363     { 0x30004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
3364     { 0x30006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
3365 
3366     /* floating point class one */
3367     /* float/float */
3368     { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s },
3369     { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d },
3370     /* int/float */
3371     { 0x30008200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_w_s },
3372     { 0x30008a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_dw_s },
3373     { 0x3000a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_w_d },
3374     { 0x3000aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
3375     /* float/int */
3376     { 0x30010200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_w },
3377     { 0x30010a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_w },
3378     { 0x30012200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_dw },
3379     { 0x30012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
3380     /* float/int truncate */
3381     { 0x30018200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_w },
3382     { 0x30018a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_w },
3383     { 0x3001a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_dw },
3384     { 0x3001aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
3385     /* uint/float */
3386     { 0x30028200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_uw_s },
3387     { 0x30028a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_udw_s },
3388     { 0x3002a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_uw_d },
3389     { 0x3002aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
3390     /* float/uint */
3391     { 0x30030200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_uw },
3392     { 0x30030a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_uw },
3393     { 0x30032200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_udw },
3394     { 0x30032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
3395     /* float/uint truncate */
3396     { 0x30038200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_uw },
3397     { 0x30038a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_uw },
3398     { 0x3003a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_udw },
3399     { 0x3003aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
3400 
3401     /* floating point class two */
3402     { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c },
3403     { 0x30000c00, 0xfc001fe0, trans_fcmp_d },
3404     { 0x30002420, 0xffffffe0, trans_ftest_q },
3405     { 0x30000420, 0xffff1fff, trans_ftest_t },
3406 
3407     /* FID.  Note that ra == rt == 0, which via fcpy puts 0 into fr0.
3408        This is machine/revision == 0, which is reserved for simulator.  */
3409     { 0x30000000, 0xffffffff, FOP_WEW = gen_fcpy_s },
3410 };
3411 
3412 #undef FOP_WEW
3413 #undef FOP_DEW
3414 #undef FOP_WED
3415 #undef FOP_WEWW
3416 #define FOP_WEW  trans_fop_wew_0e, .f.wew
3417 #define FOP_DEW  trans_fop_dew_0e, .f.dew
3418 #define FOP_WED  trans_fop_wed_0e, .f.wed
3419 #define FOP_WEWW trans_fop_weww_0e, .f.weww
3420 
3421 static const DisasInsn table_float_0e[] = {
3422     /* floating point class zero */
3423     { 0x38004000, 0xfc1fff20, FOP_WEW = gen_fcpy_s },
3424     { 0x38006000, 0xfc1fff20, FOP_WEW = gen_fabs_s },
3425     { 0x38008000, 0xfc1fff20, FOP_WEW = gen_helper_fsqrt_s },
3426     { 0x3800a000, 0xfc1fff20, FOP_WEW = gen_helper_frnd_s },
3427     { 0x3800c000, 0xfc1fff20, FOP_WEW = gen_fneg_s },
3428     { 0x3800e000, 0xfc1fff20, FOP_WEW = gen_fnegabs_s },
3429 
3430     { 0x38004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
3431     { 0x38006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
3432     { 0x38008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
3433     { 0x3800a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
3434     { 0x3800c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
3435     { 0x3800e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
3436 
3437     /* floating point class three */
3438     { 0x38000600, 0xfc00ef20, FOP_WEWW = gen_helper_fadd_s },
3439     { 0x38002600, 0xfc00ef20, FOP_WEWW = gen_helper_fsub_s },
3440     { 0x38004600, 0xfc00ef20, FOP_WEWW = gen_helper_fmpy_s },
3441     { 0x38006600, 0xfc00ef20, FOP_WEWW = gen_helper_fdiv_s },
3442 
3443     { 0x38000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
3444     { 0x38002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
3445     { 0x38004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
3446     { 0x38006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
3447 
3448     { 0x38004700, 0xfc00ef60, trans_xmpyu },
3449 
3450     /* floating point class one */
3451     /* float/float */
3452     { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
3453     { 0x38002200, 0xfc1fffc0, FOP_DEW = gen_helper_fcnv_s_d },
3454     /* int/float */
3455     { 0x38008200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_w_s },
3456     { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s },
3457     { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d },
3458     { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
3459     /* float/int */
3460     { 0x38010200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_w },
3461     { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w },
3462     { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw },
3463     { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
3464     /* float/int truncate */
3465     { 0x38018200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_w },
3466     { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w },
3467     { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw },
3468     { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
3469     /* uint/float */
3470     { 0x38028200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_uw_s },
3471     { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s },
3472     { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d },
3473     { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
3474     /* float/uint */
3475     { 0x38030200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_uw },
3476     { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw },
3477     { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw },
3478     { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
3479     /* float/uint truncate */
3480     { 0x38038200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_uw },
3481     { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw },
3482     { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw },
3483     { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
3484 
3485     /* floating point class two */
3486     { 0x38000400, 0xfc000f60, trans_fcmp_s_0e },
3487     { 0x38000c00, 0xfc001fe0, trans_fcmp_d },
3488 };
3489 
3490 #undef FOP_WEW
3491 #undef FOP_DEW
3492 #undef FOP_WED
3493 #undef FOP_WEWW
3494 #undef FOP_DED
3495 #undef FOP_DEDD
3496 
3497 /* Convert the fmpyadd single-precision register encodings to standard.  */
3498 static inline int fmpyadd_s_reg(unsigned r)
3499 {
3500     return (r & 16) * 2 + 16 + (r & 15);
3501 }
3502 
3503 static DisasJumpType trans_fmpyadd(DisasContext *ctx,
3504                                    uint32_t insn, bool is_sub)
3505 {
3506     unsigned tm = extract32(insn, 0, 5);
3507     unsigned f = extract32(insn, 5, 1);
3508     unsigned ra = extract32(insn, 6, 5);
3509     unsigned ta = extract32(insn, 11, 5);
3510     unsigned rm2 = extract32(insn, 16, 5);
3511     unsigned rm1 = extract32(insn, 21, 5);
3512 
3513     nullify_over(ctx);
3514 
3515     /* Independent multiply & add/sub, with undefined behaviour
3516        if outputs overlap inputs.  */
3517     if (f == 0) {
3518         tm = fmpyadd_s_reg(tm);
3519         ra = fmpyadd_s_reg(ra);
3520         ta = fmpyadd_s_reg(ta);
3521         rm2 = fmpyadd_s_reg(rm2);
3522         rm1 = fmpyadd_s_reg(rm1);
3523         do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
3524         do_fop_weww(ctx, ta, ta, ra,
3525                     is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
3526     } else {
3527         do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d);
3528         do_fop_dedd(ctx, ta, ta, ra,
3529                     is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
3530     }
3531 
3532     return nullify_end(ctx, DISAS_NEXT);
3533 }
3534 
3535 static DisasJumpType trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn,
3536                                       const DisasInsn *di)
3537 {
3538     unsigned rt = assemble_rt64(insn);
3539     unsigned neg = extract32(insn, 5, 1);
3540     unsigned rm1 = assemble_ra64(insn);
3541     unsigned rm2 = assemble_rb64(insn);
3542     unsigned ra3 = assemble_rc64(insn);
3543     TCGv_i32 a, b, c;
3544 
3545     nullify_over(ctx);
3546     a = load_frw0_i32(rm1);
3547     b = load_frw0_i32(rm2);
3548     c = load_frw0_i32(ra3);
3549 
3550     if (neg) {
3551         gen_helper_fmpynfadd_s(a, cpu_env, a, b, c);
3552     } else {
3553         gen_helper_fmpyfadd_s(a, cpu_env, a, b, c);
3554     }
3555 
3556     tcg_temp_free_i32(b);
3557     tcg_temp_free_i32(c);
3558     save_frw_i32(rt, a);
3559     tcg_temp_free_i32(a);
3560     return nullify_end(ctx, DISAS_NEXT);
3561 }
3562 
3563 static DisasJumpType trans_fmpyfadd_d(DisasContext *ctx, uint32_t insn,
3564                                       const DisasInsn *di)
3565 {
3566     unsigned rt = extract32(insn, 0, 5);
3567     unsigned neg = extract32(insn, 5, 1);
3568     unsigned rm1 = extract32(insn, 21, 5);
3569     unsigned rm2 = extract32(insn, 16, 5);
3570     unsigned ra3 = assemble_rc64(insn);
3571     TCGv_i64 a, b, c;
3572 
3573     nullify_over(ctx);
3574     a = load_frd0(rm1);
3575     b = load_frd0(rm2);
3576     c = load_frd0(ra3);
3577 
3578     if (neg) {
3579         gen_helper_fmpynfadd_d(a, cpu_env, a, b, c);
3580     } else {
3581         gen_helper_fmpyfadd_d(a, cpu_env, a, b, c);
3582     }
3583 
3584     tcg_temp_free_i64(b);
3585     tcg_temp_free_i64(c);
3586     save_frd(rt, a);
3587     tcg_temp_free_i64(a);
3588     return nullify_end(ctx, DISAS_NEXT);
3589 }
3590 
3591 static const DisasInsn table_fp_fused[] = {
3592     { 0xb8000000u, 0xfc000800u, trans_fmpyfadd_s },
3593     { 0xb8000800u, 0xfc0019c0u, trans_fmpyfadd_d }
3594 };
3595 
3596 static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn,
3597                                          const DisasInsn table[], size_t n)
3598 {
3599     size_t i;
3600     for (i = 0; i < n; ++i) {
3601         if ((insn & table[i].mask) == table[i].insn) {
3602             return table[i].trans(ctx, insn, &table[i]);
3603         }
3604     }
3605     return gen_illegal(ctx);
3606 }
3607 
3608 #define translate_table(ctx, insn, table) \
3609     translate_table_int(ctx, insn, table, ARRAY_SIZE(table))
3610 
3611 static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
3612 {
3613     uint32_t opc = extract32(insn, 26, 6);
3614 
3615     switch (opc) {
3616     case 0x00: /* system op */
3617         return translate_table(ctx, insn, table_system);
3618     case 0x01:
3619         return translate_table(ctx, insn, table_mem_mgmt);
3620     case 0x02:
3621         return translate_table(ctx, insn, table_arith_log);
3622     case 0x03:
3623         return translate_table(ctx, insn, table_index_mem);
3624     case 0x06:
3625         return trans_fmpyadd(ctx, insn, false);
3626     case 0x08:
3627         return trans_ldil(ctx, insn);
3628     case 0x09:
3629         return trans_copr_w(ctx, insn);
3630     case 0x0A:
3631         return trans_addil(ctx, insn);
3632     case 0x0B:
3633         return trans_copr_dw(ctx, insn);
3634     case 0x0C:
3635         return translate_table(ctx, insn, table_float_0c);
3636     case 0x0D:
3637         return trans_ldo(ctx, insn);
3638     case 0x0E:
3639         return translate_table(ctx, insn, table_float_0e);
3640 
3641     case 0x10:
3642         return trans_load(ctx, insn, false, MO_UB);
3643     case 0x11:
3644         return trans_load(ctx, insn, false, MO_TEUW);
3645     case 0x12:
3646         return trans_load(ctx, insn, false, MO_TEUL);
3647     case 0x13:
3648         return trans_load(ctx, insn, true, MO_TEUL);
3649     case 0x16:
3650         return trans_fload_mod(ctx, insn);
3651     case 0x17:
3652         return trans_load_w(ctx, insn);
3653     case 0x18:
3654         return trans_store(ctx, insn, false, MO_UB);
3655     case 0x19:
3656         return trans_store(ctx, insn, false, MO_TEUW);
3657     case 0x1A:
3658         return trans_store(ctx, insn, false, MO_TEUL);
3659     case 0x1B:
3660         return trans_store(ctx, insn, true, MO_TEUL);
3661     case 0x1E:
3662         return trans_fstore_mod(ctx, insn);
3663     case 0x1F:
3664         return trans_store_w(ctx, insn);
3665 
3666     case 0x20:
3667         return trans_cmpb(ctx, insn, true, false, false);
3668     case 0x21:
3669         return trans_cmpb(ctx, insn, true, true, false);
3670     case 0x22:
3671         return trans_cmpb(ctx, insn, false, false, false);
3672     case 0x23:
3673         return trans_cmpb(ctx, insn, false, true, false);
3674     case 0x24:
3675         return trans_cmpiclr(ctx, insn);
3676     case 0x25:
3677         return trans_subi(ctx, insn);
3678     case 0x26:
3679         return trans_fmpyadd(ctx, insn, true);
3680     case 0x27:
3681         return trans_cmpb(ctx, insn, true, false, true);
3682     case 0x28:
3683         return trans_addb(ctx, insn, true, false);
3684     case 0x29:
3685         return trans_addb(ctx, insn, true, true);
3686     case 0x2A:
3687         return trans_addb(ctx, insn, false, false);
3688     case 0x2B:
3689         return trans_addb(ctx, insn, false, true);
3690     case 0x2C:
3691     case 0x2D:
3692         return trans_addi(ctx, insn);
3693     case 0x2E:
3694         return translate_table(ctx, insn, table_fp_fused);
3695     case 0x2F:
3696         return trans_cmpb(ctx, insn, false, false, true);
3697 
3698     case 0x30:
3699     case 0x31:
3700         return trans_bb(ctx, insn);
3701     case 0x32:
3702         return trans_movb(ctx, insn, false);
3703     case 0x33:
3704         return trans_movb(ctx, insn, true);
3705     case 0x34:
3706         return translate_table(ctx, insn, table_sh_ex);
3707     case 0x35:
3708         return translate_table(ctx, insn, table_depw);
3709     case 0x38:
3710         return trans_be(ctx, insn, false);
3711     case 0x39:
3712         return trans_be(ctx, insn, true);
3713     case 0x3A:
3714         return translate_table(ctx, insn, table_branch);
3715 
3716     case 0x04: /* spopn */
3717     case 0x05: /* diag */
3718     case 0x0F: /* product specific */
3719         break;
3720 
3721     case 0x07: /* unassigned */
3722     case 0x15: /* unassigned */
3723     case 0x1D: /* unassigned */
3724     case 0x37: /* unassigned */
3725     case 0x3F: /* unassigned */
3726     default:
3727         break;
3728     }
3729     return gen_illegal(ctx);
3730 }
3731 
3732 static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
3733                                       CPUState *cs, int max_insns)
3734 {
3735     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3736     TranslationBlock *tb = ctx->base.tb;
3737     int i, bound;
3738 
3739     ctx->cs = cs;
3740     ctx->iaoq_f = tb->pc;
3741     ctx->iaoq_b = tb->cs_base;
3742     ctx->iaoq_n = -1;
3743     TCGV_UNUSED(ctx->iaoq_n_var);
3744 
3745     ctx->ntemps = 0;
3746     for (i = 0; i < ARRAY_SIZE(ctx->temps); ++i) {
3747         TCGV_UNUSED(ctx->temps[i]);
3748     }
3749 
3750     bound = -(tb->pc | TARGET_PAGE_MASK) / 4;
3751     return MIN(max_insns, bound);
3752 }
3753 
3754 static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
3755 {
3756     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3757 
3758     /* Seed the nullification status from PSW[N], as shown in TB->FLAGS.  */
3759     ctx->null_cond = cond_make_f();
3760     ctx->psw_n_nonzero = false;
3761     if (ctx->base.tb->flags & 1) {
3762         ctx->null_cond.c = TCG_COND_ALWAYS;
3763         ctx->psw_n_nonzero = true;
3764     }
3765     ctx->null_lab = NULL;
3766 }
3767 
3768 static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
3769 {
3770     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3771 
3772     tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
3773 }
3774 
3775 static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
3776                                       const CPUBreakpoint *bp)
3777 {
3778     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3779 
3780     ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG);
3781     ctx->base.pc_next = ctx->iaoq_f + 4;
3782     return true;
3783 }
3784 
3785 static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
3786 {
3787     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3788     CPUHPPAState *env = cs->env_ptr;
3789     DisasJumpType ret;
3790     int i, n;
3791 
3792     /* Execute one insn.  */
3793     if (ctx->iaoq_f < TARGET_PAGE_SIZE) {
3794         ret = do_page_zero(ctx);
3795         assert(ret != DISAS_NEXT);
3796     } else {
3797         /* Always fetch the insn, even if nullified, so that we check
3798            the page permissions for execute.  */
3799         uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f);
3800 
3801         /* Set up the IA queue for the next insn.
3802            This will be overwritten by a branch.  */
3803         if (ctx->iaoq_b == -1) {
3804             ctx->iaoq_n = -1;
3805             ctx->iaoq_n_var = get_temp(ctx);
3806             tcg_gen_addi_tl(ctx->iaoq_n_var, cpu_iaoq_b, 4);
3807         } else {
3808             ctx->iaoq_n = ctx->iaoq_b + 4;
3809             TCGV_UNUSED(ctx->iaoq_n_var);
3810         }
3811 
3812         if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
3813             ctx->null_cond.c = TCG_COND_NEVER;
3814             ret = DISAS_NEXT;
3815         } else {
3816             ret = translate_one(ctx, insn);
3817             assert(ctx->null_lab == NULL);
3818         }
3819     }
3820 
3821     /* Free any temporaries allocated.  */
3822     for (i = 0, n = ctx->ntemps; i < n; ++i) {
3823         tcg_temp_free(ctx->temps[i]);
3824         TCGV_UNUSED(ctx->temps[i]);
3825     }
3826     ctx->ntemps = 0;
3827 
3828     /* Advance the insn queue.  */
3829     /* ??? The non-linear instruction restriction is purely due to
3830        the debugging dump.  Otherwise we *could* follow unconditional
3831        branches within the same page.  */
3832     if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
3833         if (ctx->null_cond.c == TCG_COND_NEVER
3834             || ctx->null_cond.c == TCG_COND_ALWAYS) {
3835             nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
3836             gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
3837             ret = DISAS_NORETURN;
3838         } else {
3839             ret = DISAS_IAQ_N_STALE;
3840        }
3841     }
3842     ctx->iaoq_f = ctx->iaoq_b;
3843     ctx->iaoq_b = ctx->iaoq_n;
3844     ctx->base.is_jmp = ret;
3845 
3846     if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) {
3847         return;
3848     }
3849     if (ctx->iaoq_f == -1) {
3850         tcg_gen_mov_tl(cpu_iaoq_f, cpu_iaoq_b);
3851         copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
3852         nullify_save(ctx);
3853         ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
3854     } else if (ctx->iaoq_b == -1) {
3855         tcg_gen_mov_tl(cpu_iaoq_b, ctx->iaoq_n_var);
3856     }
3857 }
3858 
3859 static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
3860 {
3861     DisasContext *ctx = container_of(dcbase, DisasContext, base);
3862 
3863     switch (ctx->base.is_jmp) {
3864     case DISAS_NORETURN:
3865         break;
3866     case DISAS_TOO_MANY:
3867     case DISAS_IAQ_N_STALE:
3868         copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
3869         copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
3870         nullify_save(ctx);
3871         /* FALLTHRU */
3872     case DISAS_IAQ_N_UPDATED:
3873         if (ctx->base.singlestep_enabled) {
3874             gen_excp_1(EXCP_DEBUG);
3875         } else {
3876             tcg_gen_lookup_and_goto_ptr();
3877         }
3878         break;
3879     default:
3880         g_assert_not_reached();
3881     }
3882 
3883     /* We don't actually use this during normal translation,
3884        but we should interact with the generic main loop.  */
3885     ctx->base.pc_next = ctx->base.tb->pc + 4 * ctx->base.num_insns;
3886 }
3887 
3888 static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
3889 {
3890     TranslationBlock *tb = dcbase->tb;
3891 
3892     switch (tb->pc) {
3893     case 0x00:
3894         qemu_log("IN:\n0x00000000:  (null)\n");
3895         break;
3896     case 0xb0:
3897         qemu_log("IN:\n0x000000b0:  light-weight-syscall\n");
3898         break;
3899     case 0xe0:
3900         qemu_log("IN:\n0x000000e0:  set-thread-pointer-syscall\n");
3901         break;
3902     case 0x100:
3903         qemu_log("IN:\n0x00000100:  syscall\n");
3904         break;
3905     default:
3906         qemu_log("IN: %s\n", lookup_symbol(tb->pc));
3907         log_target_disas(cs, tb->pc, tb->size, 1);
3908         break;
3909     }
3910 }
3911 
3912 static const TranslatorOps hppa_tr_ops = {
3913     .init_disas_context = hppa_tr_init_disas_context,
3914     .tb_start           = hppa_tr_tb_start,
3915     .insn_start         = hppa_tr_insn_start,
3916     .breakpoint_check   = hppa_tr_breakpoint_check,
3917     .translate_insn     = hppa_tr_translate_insn,
3918     .tb_stop            = hppa_tr_tb_stop,
3919     .disas_log          = hppa_tr_disas_log,
3920 };
3921 
3922 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
3923 
3924 {
3925     DisasContext ctx;
3926     translator_loop(&hppa_tr_ops, &ctx.base, cs, tb);
3927 }
3928 
3929 void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
3930                           target_ulong *data)
3931 {
3932     env->iaoq_f = data[0];
3933     if (data[1] != -1) {
3934         env->iaoq_b = data[1];
3935     }
3936     /* Since we were executing the instruction at IAOQ_F, and took some
3937        sort of action that provoked the cpu_restore_state, we can infer
3938        that the instruction was not nullified.  */
3939     env->psw_n = 0;
3940 }
3941