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