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