xref: /qemu/target/openrisc/translate.c (revision 8816f70b)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  * OpenRISC translation
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5fcf5ef2aSThomas Huth  *                         Feng Gao <gf91597@gmail.com>
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
10fcf5ef2aSThomas Huth  * version 2 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15fcf5ef2aSThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth 
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "cpu.h"
23fcf5ef2aSThomas Huth #include "exec/exec-all.h"
24fcf5ef2aSThomas Huth #include "disas/disas.h"
25fcf5ef2aSThomas Huth #include "tcg-op.h"
26fcf5ef2aSThomas Huth #include "qemu-common.h"
27fcf5ef2aSThomas Huth #include "qemu/log.h"
28fcf5ef2aSThomas Huth #include "qemu/bitops.h"
29fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h"
3077fc6f5eSLluís Vilanova #include "exec/translator.h"
31fcf5ef2aSThomas Huth 
32fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
33fcf5ef2aSThomas Huth #include "exec/helper-gen.h"
347de9729fSRichard Henderson #include "exec/gen-icount.h"
35fcf5ef2aSThomas Huth 
36fcf5ef2aSThomas Huth #include "trace-tcg.h"
37fcf5ef2aSThomas Huth #include "exec/log.h"
38fcf5ef2aSThomas Huth 
39111ece51SRichard Henderson #define LOG_DIS(str, ...) \
401ffa4bceSEmilio G. Cota     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->base.pc_next,    \
411ffa4bceSEmilio G. Cota                   ## __VA_ARGS__)
42fcf5ef2aSThomas Huth 
4377fc6f5eSLluís Vilanova /* is_jmp field values */
4477fc6f5eSLluís Vilanova #define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
4577fc6f5eSLluís Vilanova #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
4677fc6f5eSLluís Vilanova #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
4777fc6f5eSLluís Vilanova 
48fcf5ef2aSThomas Huth typedef struct DisasContext {
491ffa4bceSEmilio G. Cota     DisasContextBase base;
50fcf5ef2aSThomas Huth     uint32_t mem_idx;
51a01deb36SRichard Henderson     uint32_t tb_flags;
52fcf5ef2aSThomas Huth     uint32_t delayed_branch;
53fcf5ef2aSThomas Huth } DisasContext;
54fcf5ef2aSThomas Huth 
557de9729fSRichard Henderson /* Include the auto-generated decoder.  */
567de9729fSRichard Henderson #include "decode.inc.c"
577de9729fSRichard Henderson 
58fcf5ef2aSThomas Huth static TCGv cpu_sr;
59fcf5ef2aSThomas Huth static TCGv cpu_R[32];
606597c28dSRichard Henderson static TCGv cpu_R0;
61fcf5ef2aSThomas Huth static TCGv cpu_pc;
62fcf5ef2aSThomas Huth static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
63fcf5ef2aSThomas Huth static TCGv cpu_ppc;
6484775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
6597458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
6697458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
67930c3d00SRichard Henderson static TCGv cpu_lock_addr;
68930c3d00SRichard Henderson static TCGv cpu_lock_value;
69fcf5ef2aSThomas Huth static TCGv_i32 fpcsr;
706f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
71a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
72fcf5ef2aSThomas Huth 
73fcf5ef2aSThomas Huth void openrisc_translate_init(void)
74fcf5ef2aSThomas Huth {
75fcf5ef2aSThomas Huth     static const char * const regnames[] = {
76fcf5ef2aSThomas Huth         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77fcf5ef2aSThomas Huth         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
78fcf5ef2aSThomas Huth         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
79fcf5ef2aSThomas Huth         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
80fcf5ef2aSThomas Huth     };
81fcf5ef2aSThomas Huth     int i;
82fcf5ef2aSThomas Huth 
83fcf5ef2aSThomas Huth     cpu_sr = tcg_global_mem_new(cpu_env,
84fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, sr), "sr");
85a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
86a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
87a01deb36SRichard Henderson                                        "dflag");
88fcf5ef2aSThomas Huth     cpu_pc = tcg_global_mem_new(cpu_env,
89fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, pc), "pc");
90fcf5ef2aSThomas Huth     cpu_ppc = tcg_global_mem_new(cpu_env,
91fcf5ef2aSThomas Huth                                  offsetof(CPUOpenRISCState, ppc), "ppc");
92fcf5ef2aSThomas Huth     jmp_pc = tcg_global_mem_new(cpu_env,
93fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
9484775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
9584775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
9697458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
9797458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
9897458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
9997458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
100930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
101930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
102930c3d00SRichard Henderson                                        "lock_addr");
103930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
104930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
105930c3d00SRichard Henderson                                         "lock_value");
106fcf5ef2aSThomas Huth     fpcsr = tcg_global_mem_new_i32(cpu_env,
107fcf5ef2aSThomas Huth                                    offsetof(CPUOpenRISCState, fpcsr),
108fcf5ef2aSThomas Huth                                    "fpcsr");
1096f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1106f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1116f7332baSRichard Henderson                                      "mac");
112fcf5ef2aSThomas Huth     for (i = 0; i < 32; i++) {
113fcf5ef2aSThomas Huth         cpu_R[i] = tcg_global_mem_new(cpu_env,
114d89e71e8SStafford Horne                                       offsetof(CPUOpenRISCState,
115d89e71e8SStafford Horne                                                shadow_gpr[0][i]),
116fcf5ef2aSThomas Huth                                       regnames[i]);
117fcf5ef2aSThomas Huth     }
1186597c28dSRichard Henderson     cpu_R0 = cpu_R[0];
119fcf5ef2aSThomas Huth }
120fcf5ef2aSThomas Huth 
121fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, unsigned int excp)
122fcf5ef2aSThomas Huth {
123fcf5ef2aSThomas Huth     TCGv_i32 tmp = tcg_const_i32(excp);
124fcf5ef2aSThomas Huth     gen_helper_exception(cpu_env, tmp);
125fcf5ef2aSThomas Huth     tcg_temp_free_i32(tmp);
126fcf5ef2aSThomas Huth }
127fcf5ef2aSThomas Huth 
128fcf5ef2aSThomas Huth static void gen_illegal_exception(DisasContext *dc)
129fcf5ef2aSThomas Huth {
1301ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
131fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_ILLEGAL);
1321ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
133fcf5ef2aSThomas Huth }
134fcf5ef2aSThomas Huth 
135fcf5ef2aSThomas Huth /* not used yet, open it when we need or64.  */
136fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64
137fcf5ef2aSThomas Huth static void check_ob64s(DisasContext *dc)
138fcf5ef2aSThomas Huth {
139fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OB64S)) {
140fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
141fcf5ef2aSThomas Huth     }
142fcf5ef2aSThomas Huth }
143fcf5ef2aSThomas Huth 
144fcf5ef2aSThomas Huth static void check_of64s(DisasContext *dc)
145fcf5ef2aSThomas Huth {
146fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OF64S)) {
147fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
148fcf5ef2aSThomas Huth     }
149fcf5ef2aSThomas Huth }
150fcf5ef2aSThomas Huth 
151fcf5ef2aSThomas Huth static void check_ov64s(DisasContext *dc)
152fcf5ef2aSThomas Huth {
153fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OV64S)) {
154fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
155fcf5ef2aSThomas Huth     }
156fcf5ef2aSThomas Huth }
157fcf5ef2aSThomas Huth #endif*/
158fcf5ef2aSThomas Huth 
1596597c28dSRichard Henderson /* We're about to write to REG.  On the off-chance that the user is
1606597c28dSRichard Henderson    writing to R0, re-instate the architectural register.  */
1616597c28dSRichard Henderson #define check_r0_write(reg)             \
1626597c28dSRichard Henderson     do {                                \
1636597c28dSRichard Henderson         if (unlikely(reg == 0)) {       \
1646597c28dSRichard Henderson             cpu_R[0] = cpu_R0;          \
1656597c28dSRichard Henderson         }                               \
1666597c28dSRichard Henderson     } while (0)
1676597c28dSRichard Henderson 
168fcf5ef2aSThomas Huth static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
169fcf5ef2aSThomas Huth {
1701ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
171fcf5ef2aSThomas Huth         return false;
172fcf5ef2aSThomas Huth     }
173fcf5ef2aSThomas Huth 
174fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
1751ffa4bceSEmilio G. Cota     return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
176fcf5ef2aSThomas Huth #else
177fcf5ef2aSThomas Huth     return true;
178fcf5ef2aSThomas Huth #endif
179fcf5ef2aSThomas Huth }
180fcf5ef2aSThomas Huth 
181fcf5ef2aSThomas Huth static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
182fcf5ef2aSThomas Huth {
183fcf5ef2aSThomas Huth     if (use_goto_tb(dc, dest)) {
184fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, dest);
185fcf5ef2aSThomas Huth         tcg_gen_goto_tb(n);
1861ffa4bceSEmilio G. Cota         tcg_gen_exit_tb((uintptr_t)dc->base.tb + n);
187fcf5ef2aSThomas Huth     } else {
188fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, dest);
1891ffa4bceSEmilio G. Cota         if (dc->base.singlestep_enabled) {
190fcf5ef2aSThomas Huth             gen_exception(dc, EXCP_DEBUG);
191fcf5ef2aSThomas Huth         }
192fcf5ef2aSThomas Huth         tcg_gen_exit_tb(0);
193fcf5ef2aSThomas Huth     }
194fcf5ef2aSThomas Huth }
195fcf5ef2aSThomas Huth 
19697458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1979ecaa27eSRichard Henderson {
1980c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
19997458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
2009ecaa27eSRichard Henderson     }
2010c53d734SRichard Henderson }
2029ecaa27eSRichard Henderson 
20397458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
2049ecaa27eSRichard Henderson {
2050c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
20697458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
2079ecaa27eSRichard Henderson     }
2080c53d734SRichard Henderson }
2099ecaa27eSRichard Henderson 
21097458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
2119ecaa27eSRichard Henderson {
2120c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
21397458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
2149ecaa27eSRichard Henderson     }
2150c53d734SRichard Henderson }
2169ecaa27eSRichard Henderson 
2179ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2189ecaa27eSRichard Henderson {
2199ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2209ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2219ecaa27eSRichard Henderson 
22297458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
22397458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2249ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22597458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2269ecaa27eSRichard Henderson     tcg_temp_free(t0);
2279ecaa27eSRichard Henderson 
2289ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2299ecaa27eSRichard Henderson     tcg_temp_free(res);
2309ecaa27eSRichard Henderson 
23197458071SRichard Henderson     gen_ove_cyov(dc);
2329ecaa27eSRichard Henderson }
2339ecaa27eSRichard Henderson 
2349ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2359ecaa27eSRichard Henderson {
2369ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2379ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2389ecaa27eSRichard Henderson 
23997458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
24097458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
24197458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2429ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
24397458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2449ecaa27eSRichard Henderson     tcg_temp_free(t0);
2459ecaa27eSRichard Henderson 
2469ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2479ecaa27eSRichard Henderson     tcg_temp_free(res);
2489ecaa27eSRichard Henderson 
24997458071SRichard Henderson     gen_ove_cyov(dc);
2509ecaa27eSRichard Henderson }
2519ecaa27eSRichard Henderson 
2529ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2539ecaa27eSRichard Henderson {
2549ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2559ecaa27eSRichard Henderson 
2569ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
25797458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
25897458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
25997458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
26097458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2619ecaa27eSRichard Henderson 
2629ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2639ecaa27eSRichard Henderson     tcg_temp_free(res);
2649ecaa27eSRichard Henderson 
26597458071SRichard Henderson     gen_ove_cyov(dc);
2669ecaa27eSRichard Henderson }
2679ecaa27eSRichard Henderson 
2689ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2699ecaa27eSRichard Henderson {
2709ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2719ecaa27eSRichard Henderson 
27297458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2739ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
27497458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2759ecaa27eSRichard Henderson     tcg_temp_free(t0);
2769ecaa27eSRichard Henderson 
27797458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
27897458071SRichard Henderson     gen_ove_ov(dc);
2799ecaa27eSRichard Henderson }
2809ecaa27eSRichard Henderson 
2819ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2829ecaa27eSRichard Henderson {
28397458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
28497458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2859ecaa27eSRichard Henderson 
28697458071SRichard Henderson     gen_ove_cy(dc);
2879ecaa27eSRichard Henderson }
2889ecaa27eSRichard Henderson 
2899ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2909ecaa27eSRichard Henderson {
2919ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2929ecaa27eSRichard Henderson 
29397458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2949ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2959ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
29697458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2979ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2989ecaa27eSRichard Henderson     tcg_temp_free(t0);
2999ecaa27eSRichard Henderson 
30097458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
30197458071SRichard Henderson     gen_ove_ov(dc);
3029ecaa27eSRichard Henderson }
3039ecaa27eSRichard Henderson 
3049ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3059ecaa27eSRichard Henderson {
3069ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3079ecaa27eSRichard Henderson 
30897458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
3099ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3109ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
31197458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
3129ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
3139ecaa27eSRichard Henderson     tcg_temp_free(t0);
3149ecaa27eSRichard Henderson 
31597458071SRichard Henderson     gen_ove_cy(dc);
3169ecaa27eSRichard Henderson }
317fcf5ef2aSThomas Huth 
318cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
319cc5de49eSRichard Henderson {
320cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
321cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
322cc5de49eSRichard Henderson 
323cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
324cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
325cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
326cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
327cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
328cc5de49eSRichard Henderson     } else {
329cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
330cc5de49eSRichard Henderson 
331cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
332cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
333cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
334cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
335cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
336cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
337cc5de49eSRichard Henderson 
338cc5de49eSRichard Henderson         gen_ove_ov(dc);
339cc5de49eSRichard Henderson     }
340cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
341cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
342cc5de49eSRichard Henderson }
343cc5de49eSRichard Henderson 
344cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
345cc5de49eSRichard Henderson {
346cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
347cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
348cc5de49eSRichard Henderson 
349cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
350cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
351cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
352cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
353cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
354cc5de49eSRichard Henderson     } else {
355cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
356cc5de49eSRichard Henderson 
357cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
358cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
359cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
360cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
361cc5de49eSRichard Henderson 
362cc5de49eSRichard Henderson         gen_ove_cy(dc);
363cc5de49eSRichard Henderson     }
364cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
365cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
366cc5de49eSRichard Henderson }
367cc5de49eSRichard Henderson 
3686f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3696f7332baSRichard Henderson {
3706f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3716f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3726f7332baSRichard Henderson 
3736f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3746f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3756f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3766f7332baSRichard Henderson 
3776f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3786f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3796f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3806f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3816f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3826f7332baSRichard Henderson     tcg_temp_free_i64(t2);
3836f7332baSRichard Henderson 
3846f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3856f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3866f7332baSRichard Henderson #else
3876f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3886f7332baSRichard Henderson #endif
3896f7332baSRichard Henderson     tcg_temp_free_i64(t1);
3906f7332baSRichard Henderson 
3916f7332baSRichard Henderson     gen_ove_ov(dc);
3926f7332baSRichard Henderson }
3936f7332baSRichard Henderson 
394cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
395cc5de49eSRichard Henderson {
396cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
397cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
398cc5de49eSRichard Henderson 
399cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
400cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
401cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
402cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
403cc5de49eSRichard Henderson 
404cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
405cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
406cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
407cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
408cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
409cc5de49eSRichard Henderson 
410cc5de49eSRichard Henderson     gen_ove_cy(dc);
411cc5de49eSRichard Henderson }
412cc5de49eSRichard Henderson 
4136f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
4146f7332baSRichard Henderson {
4156f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4166f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4176f7332baSRichard Henderson 
4186f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4196f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4206f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4216f7332baSRichard Henderson 
4226f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4236f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4246f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4256f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4266f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4276f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4286f7332baSRichard Henderson 
4296f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4306f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4316f7332baSRichard Henderson #else
4326f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4336f7332baSRichard Henderson #endif
4346f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4356f7332baSRichard Henderson 
4366f7332baSRichard Henderson     gen_ove_ov(dc);
4376f7332baSRichard Henderson }
4386f7332baSRichard Henderson 
439cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
440cc5de49eSRichard Henderson {
441cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
442cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
443cc5de49eSRichard Henderson 
444cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
445cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
446cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
447cc5de49eSRichard Henderson 
448cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
449cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
450cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
451cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
452cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
453cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
454cc5de49eSRichard Henderson 
455cc5de49eSRichard Henderson     gen_ove_cy(dc);
456cc5de49eSRichard Henderson }
457cc5de49eSRichard Henderson 
458fcf5ef2aSThomas Huth static void dec_calc(DisasContext *dc, uint32_t insn)
459fcf5ef2aSThomas Huth {
460fcf5ef2aSThomas Huth     uint32_t op0, op1, op2;
461fcf5ef2aSThomas Huth     uint32_t ra, rb, rd;
462fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 4);
463fcf5ef2aSThomas Huth     op1 = extract32(insn, 8, 2);
464fcf5ef2aSThomas Huth     op2 = extract32(insn, 6, 2);
465fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
466fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
467fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
468fcf5ef2aSThomas Huth 
469fcf5ef2aSThomas Huth     switch (op1) {
470cf2ae442SRichard Henderson     case 0:
471cf2ae442SRichard Henderson         switch (op0) {
472cf2ae442SRichard Henderson         case 0x0: /* l.add */
473fcf5ef2aSThomas Huth             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
4749ecaa27eSRichard Henderson             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
475cf2ae442SRichard Henderson             return;
476fcf5ef2aSThomas Huth 
477cf2ae442SRichard Henderson         case 0x1: /* l.addc */
478fcf5ef2aSThomas Huth             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
4799ecaa27eSRichard Henderson             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
480cf2ae442SRichard Henderson             return;
481fcf5ef2aSThomas Huth 
482cf2ae442SRichard Henderson         case 0x2: /* l.sub */
483fcf5ef2aSThomas Huth             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
4849ecaa27eSRichard Henderson             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
485cf2ae442SRichard Henderson             return;
486fcf5ef2aSThomas Huth 
487cf2ae442SRichard Henderson         case 0x3: /* l.and */
488fcf5ef2aSThomas Huth             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
489fcf5ef2aSThomas Huth             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
490cf2ae442SRichard Henderson             return;
491fcf5ef2aSThomas Huth 
492cf2ae442SRichard Henderson         case 0x4: /* l.or */
493fcf5ef2aSThomas Huth             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
494fcf5ef2aSThomas Huth             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
495cf2ae442SRichard Henderson             return;
496fcf5ef2aSThomas Huth 
497cf2ae442SRichard Henderson         case 0x5: /* l.xor */
498fcf5ef2aSThomas Huth             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
499fcf5ef2aSThomas Huth             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
500cf2ae442SRichard Henderson             return;
501cf2ae442SRichard Henderson 
502cf2ae442SRichard Henderson         case 0x8:
503cf2ae442SRichard Henderson             switch (op2) {
504cf2ae442SRichard Henderson             case 0: /* l.sll */
505cf2ae442SRichard Henderson                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
506cf2ae442SRichard Henderson                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
507cf2ae442SRichard Henderson                 return;
508cf2ae442SRichard Henderson             case 1: /* l.srl */
509cf2ae442SRichard Henderson                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
510cf2ae442SRichard Henderson                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
511cf2ae442SRichard Henderson                 return;
512cf2ae442SRichard Henderson             case 2: /* l.sra */
513cf2ae442SRichard Henderson                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
514cf2ae442SRichard Henderson                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
515cf2ae442SRichard Henderson                 return;
516cf2ae442SRichard Henderson             case 3: /* l.ror */
517cf2ae442SRichard Henderson                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
518cf2ae442SRichard Henderson                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
519cf2ae442SRichard Henderson                 return;
520fcf5ef2aSThomas Huth             }
521fcf5ef2aSThomas Huth             break;
522fcf5ef2aSThomas Huth 
523cf2ae442SRichard Henderson         case 0xc:
524cf2ae442SRichard Henderson             switch (op2) {
525cf2ae442SRichard Henderson             case 0: /* l.exths */
526cf2ae442SRichard Henderson                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
527cf2ae442SRichard Henderson                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
528cf2ae442SRichard Henderson                 return;
529cf2ae442SRichard Henderson             case 1: /* l.extbs */
530cf2ae442SRichard Henderson                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
531cf2ae442SRichard Henderson                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
532cf2ae442SRichard Henderson                 return;
533cf2ae442SRichard Henderson             case 2: /* l.exthz */
534cf2ae442SRichard Henderson                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
535cf2ae442SRichard Henderson                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
536cf2ae442SRichard Henderson                 return;
537cf2ae442SRichard Henderson             case 3: /* l.extbz */
538cf2ae442SRichard Henderson                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
539cf2ae442SRichard Henderson                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
540cf2ae442SRichard Henderson                 return;
541fcf5ef2aSThomas Huth             }
542fcf5ef2aSThomas Huth             break;
543fcf5ef2aSThomas Huth 
544cf2ae442SRichard Henderson         case 0xd:
545cf2ae442SRichard Henderson             switch (op2) {
546cf2ae442SRichard Henderson             case 0: /* l.extws */
547cf2ae442SRichard Henderson                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
548cf2ae442SRichard Henderson                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
549cf2ae442SRichard Henderson                 return;
550cf2ae442SRichard Henderson             case 1: /* l.extwz */
551cf2ae442SRichard Henderson                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
552cf2ae442SRichard Henderson                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
553cf2ae442SRichard Henderson                 return;
554fcf5ef2aSThomas Huth             }
555fcf5ef2aSThomas Huth             break;
556fcf5ef2aSThomas Huth 
557cf2ae442SRichard Henderson         case 0xe: /* l.cmov */
558fcf5ef2aSThomas Huth             LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
559fcf5ef2aSThomas Huth             {
560784696d1SRichard Henderson                 TCGv zero = tcg_const_tl(0);
561784696d1SRichard Henderson                 tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero,
562784696d1SRichard Henderson                                    cpu_R[ra], cpu_R[rb]);
563784696d1SRichard Henderson                 tcg_temp_free(zero);
564fcf5ef2aSThomas Huth             }
565cf2ae442SRichard Henderson             return;
566fcf5ef2aSThomas Huth 
567cf2ae442SRichard Henderson         case 0xf: /* l.ff1 */
568fcf5ef2aSThomas Huth             LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
569555baef8SRichard Henderson             tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1);
570555baef8SRichard Henderson             tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1);
571cf2ae442SRichard Henderson             return;
572cf2ae442SRichard Henderson         }
573fcf5ef2aSThomas Huth         break;
574cf2ae442SRichard Henderson 
575cf2ae442SRichard Henderson     case 1:
576cf2ae442SRichard Henderson         switch (op0) {
577cf2ae442SRichard Henderson         case 0xf: /* l.fl1 */
578fcf5ef2aSThomas Huth             LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
579555baef8SRichard Henderson             tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS);
580555baef8SRichard Henderson             tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]);
581cf2ae442SRichard Henderson             return;
582fcf5ef2aSThomas Huth         }
583fcf5ef2aSThomas Huth         break;
584fcf5ef2aSThomas Huth 
585cf2ae442SRichard Henderson     case 2:
586fcf5ef2aSThomas Huth         break;
587fcf5ef2aSThomas Huth 
588cf2ae442SRichard Henderson     case 3:
589cf2ae442SRichard Henderson         switch (op0) {
590cf2ae442SRichard Henderson         case 0x6: /* l.mul */
591cf2ae442SRichard Henderson             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
592cf2ae442SRichard Henderson             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
593cf2ae442SRichard Henderson             return;
594cf2ae442SRichard Henderson 
595cc5de49eSRichard Henderson         case 0x7: /* l.muld */
596cc5de49eSRichard Henderson             LOG_DIS("l.muld r%d, r%d\n", ra, rb);
597cc5de49eSRichard Henderson             gen_muld(dc, cpu_R[ra], cpu_R[rb]);
598cc5de49eSRichard Henderson             break;
599cc5de49eSRichard Henderson 
600cf2ae442SRichard Henderson         case 0x9: /* l.div */
601cf2ae442SRichard Henderson             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
602cf2ae442SRichard Henderson             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
603cf2ae442SRichard Henderson             return;
604cf2ae442SRichard Henderson 
605cf2ae442SRichard Henderson         case 0xa: /* l.divu */
606cf2ae442SRichard Henderson             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
607cf2ae442SRichard Henderson             gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
608cf2ae442SRichard Henderson             return;
609cf2ae442SRichard Henderson 
610cf2ae442SRichard Henderson         case 0xb: /* l.mulu */
611cf2ae442SRichard Henderson             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
612cf2ae442SRichard Henderson             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
613cf2ae442SRichard Henderson             return;
614cc5de49eSRichard Henderson 
615cc5de49eSRichard Henderson         case 0xc: /* l.muldu */
616cc5de49eSRichard Henderson             LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
617cc5de49eSRichard Henderson             gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
618cc5de49eSRichard Henderson             return;
619fcf5ef2aSThomas Huth         }
620fcf5ef2aSThomas Huth         break;
621fcf5ef2aSThomas Huth     }
622fcf5ef2aSThomas Huth     gen_illegal_exception(dc);
623fcf5ef2aSThomas Huth }
624fcf5ef2aSThomas Huth 
625136e13aeSRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a, uint32_t insn)
626136e13aeSRichard Henderson {
627136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
628136e13aeSRichard Henderson 
629136e13aeSRichard Henderson     LOG_DIS("l.j %d\n", a->n);
630136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
631136e13aeSRichard Henderson     dc->delayed_branch = 2;
632136e13aeSRichard Henderson     return true;
633136e13aeSRichard Henderson }
634136e13aeSRichard Henderson 
635136e13aeSRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a, uint32_t insn)
636136e13aeSRichard Henderson {
637136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
638136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
639136e13aeSRichard Henderson 
640136e13aeSRichard Henderson     LOG_DIS("l.jal %d\n", a->n);
641136e13aeSRichard Henderson     tcg_gen_movi_tl(cpu_R[9], ret_pc);
642136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
643136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
644136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
645136e13aeSRichard Henderson         dc->delayed_branch = 2;
646136e13aeSRichard Henderson     }
647136e13aeSRichard Henderson     return true;
648136e13aeSRichard Henderson }
649136e13aeSRichard Henderson 
650136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
651136e13aeSRichard Henderson {
652136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
653136e13aeSRichard Henderson     TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
654136e13aeSRichard Henderson     TCGv t_true = tcg_const_tl(tmp_pc);
655136e13aeSRichard Henderson     TCGv t_zero = tcg_const_tl(0);
656136e13aeSRichard Henderson 
657136e13aeSRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
658136e13aeSRichard Henderson 
659136e13aeSRichard Henderson     tcg_temp_free(t_next);
660136e13aeSRichard Henderson     tcg_temp_free(t_true);
661136e13aeSRichard Henderson     tcg_temp_free(t_zero);
662136e13aeSRichard Henderson     dc->delayed_branch = 2;
663136e13aeSRichard Henderson }
664136e13aeSRichard Henderson 
665136e13aeSRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a, uint32_t insn)
666136e13aeSRichard Henderson {
667136e13aeSRichard Henderson     LOG_DIS("l.bf %d\n", a->n);
668136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
669136e13aeSRichard Henderson     return true;
670136e13aeSRichard Henderson }
671136e13aeSRichard Henderson 
672136e13aeSRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a, uint32_t insn)
673136e13aeSRichard Henderson {
674136e13aeSRichard Henderson     LOG_DIS("l.bnf %d\n", a->n);
675136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
676136e13aeSRichard Henderson     return true;
677136e13aeSRichard Henderson }
678136e13aeSRichard Henderson 
679136e13aeSRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a, uint32_t insn)
680136e13aeSRichard Henderson {
681136e13aeSRichard Henderson     LOG_DIS("l.jr r%d\n", a->b);
682136e13aeSRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
683136e13aeSRichard Henderson     dc->delayed_branch = 2;
684136e13aeSRichard Henderson     return true;
685136e13aeSRichard Henderson }
686136e13aeSRichard Henderson 
687136e13aeSRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn)
688136e13aeSRichard Henderson {
689136e13aeSRichard Henderson     LOG_DIS("l.jalr r%d\n", a->b);
690136e13aeSRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
691136e13aeSRichard Henderson     tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8);
692136e13aeSRichard Henderson     dc->delayed_branch = 2;
693136e13aeSRichard Henderson     return true;
694136e13aeSRichard Henderson }
695136e13aeSRichard Henderson 
696d80bff19SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn)
697d80bff19SRichard Henderson {
698d80bff19SRichard Henderson     TCGv ea;
699d80bff19SRichard Henderson 
700d80bff19SRichard Henderson     LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i);
701d80bff19SRichard Henderson 
702d80bff19SRichard Henderson     check_r0_write(a->d);
703d80bff19SRichard Henderson     ea = tcg_temp_new();
704d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
705d80bff19SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL);
706d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
707d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]);
708d80bff19SRichard Henderson     tcg_temp_free(ea);
709d80bff19SRichard Henderson     return true;
710d80bff19SRichard Henderson }
711d80bff19SRichard Henderson 
712d80bff19SRichard Henderson static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop)
713d80bff19SRichard Henderson {
714d80bff19SRichard Henderson     TCGv ea;
715d80bff19SRichard Henderson 
716d80bff19SRichard Henderson     check_r0_write(a->d);
717d80bff19SRichard Henderson     ea = tcg_temp_new();
718d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
719d80bff19SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop);
720d80bff19SRichard Henderson     tcg_temp_free(ea);
721d80bff19SRichard Henderson }
722d80bff19SRichard Henderson 
723d80bff19SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn)
724d80bff19SRichard Henderson {
725d80bff19SRichard Henderson     LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i);
726d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
727d80bff19SRichard Henderson     return true;
728d80bff19SRichard Henderson }
729d80bff19SRichard Henderson 
730d80bff19SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn)
731d80bff19SRichard Henderson {
732d80bff19SRichard Henderson     LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i);
733d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
734d80bff19SRichard Henderson     return true;
735d80bff19SRichard Henderson }
736d80bff19SRichard Henderson 
737d80bff19SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn)
738d80bff19SRichard Henderson {
739d80bff19SRichard Henderson     LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i);
740d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
741d80bff19SRichard Henderson     return true;
742d80bff19SRichard Henderson }
743d80bff19SRichard Henderson 
744d80bff19SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn)
745d80bff19SRichard Henderson {
746d80bff19SRichard Henderson     LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i);
747d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
748d80bff19SRichard Henderson     return true;
749d80bff19SRichard Henderson }
750d80bff19SRichard Henderson 
751d80bff19SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn)
752d80bff19SRichard Henderson {
753d80bff19SRichard Henderson     LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i);
754d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
755d80bff19SRichard Henderson     return true;
756d80bff19SRichard Henderson }
757d80bff19SRichard Henderson 
758d80bff19SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn)
759d80bff19SRichard Henderson {
760d80bff19SRichard Henderson     LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i);
761d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
762d80bff19SRichard Henderson     return true;
763d80bff19SRichard Henderson }
764d80bff19SRichard Henderson 
765d80bff19SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn)
766d80bff19SRichard Henderson {
767d80bff19SRichard Henderson     TCGv ea, val;
768d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
769d80bff19SRichard Henderson 
770d80bff19SRichard Henderson     LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i);
771d80bff19SRichard Henderson 
772d80bff19SRichard Henderson     ea = tcg_temp_new();
773d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
774d80bff19SRichard Henderson 
775d80bff19SRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
776d80bff19SRichard Henderson        to cpu_R[0].  Since l.swa is quite often immediately followed by a
777d80bff19SRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
778d80bff19SRichard Henderson        This also takes care of RB input across the branch.  */
779d80bff19SRichard Henderson     cpu_R[0] = cpu_R0;
780d80bff19SRichard Henderson 
781d80bff19SRichard Henderson     lab_fail = gen_new_label();
782d80bff19SRichard Henderson     lab_done = gen_new_label();
783d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
784d80bff19SRichard Henderson     tcg_temp_free(ea);
785d80bff19SRichard Henderson 
786d80bff19SRichard Henderson     val = tcg_temp_new();
787d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
788d80bff19SRichard Henderson                               cpu_R[a->b], dc->mem_idx, MO_TEUL);
789d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
790d80bff19SRichard Henderson     tcg_temp_free(val);
791d80bff19SRichard Henderson 
792d80bff19SRichard Henderson     tcg_gen_br(lab_done);
793d80bff19SRichard Henderson 
794d80bff19SRichard Henderson     gen_set_label(lab_fail);
795d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
796d80bff19SRichard Henderson 
797d80bff19SRichard Henderson     gen_set_label(lab_done);
798d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
799d80bff19SRichard Henderson     return true;
800d80bff19SRichard Henderson }
801d80bff19SRichard Henderson 
802d80bff19SRichard Henderson static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop)
803d80bff19SRichard Henderson {
804d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
805d80bff19SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R[a->a], a->i);
806d80bff19SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop);
807d80bff19SRichard Henderson     tcg_temp_free(t0);
808d80bff19SRichard Henderson }
809d80bff19SRichard Henderson 
810d80bff19SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn)
811d80bff19SRichard Henderson {
812d80bff19SRichard Henderson     LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i);
813d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
814d80bff19SRichard Henderson     return true;
815d80bff19SRichard Henderson }
816d80bff19SRichard Henderson 
817d80bff19SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn)
818d80bff19SRichard Henderson {
819d80bff19SRichard Henderson     LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i);
820d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
821d80bff19SRichard Henderson     return true;
822d80bff19SRichard Henderson }
823d80bff19SRichard Henderson 
824d80bff19SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn)
825d80bff19SRichard Henderson {
826d80bff19SRichard Henderson     LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i);
827d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
828d80bff19SRichard Henderson     return true;
829d80bff19SRichard Henderson }
830d80bff19SRichard Henderson 
831*8816f70bSRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a, uint32_t insn)
832fcf5ef2aSThomas Huth {
833*8816f70bSRichard Henderson     LOG_DIS("l.nop %d\n", a->k);
834*8816f70bSRichard Henderson     return true;
835*8816f70bSRichard Henderson }
836*8816f70bSRichard Henderson 
837*8816f70bSRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a, uint32_t insn)
838*8816f70bSRichard Henderson {
8399ecaa27eSRichard Henderson     TCGv t0;
840fcf5ef2aSThomas Huth 
841*8816f70bSRichard Henderson     LOG_DIS("l.addi r%d, r%d, %d\n", a->d, a->a, a->i);
842*8816f70bSRichard Henderson     check_r0_write(a->d);
843*8816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
844*8816f70bSRichard Henderson     gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0);
8456f7332baSRichard Henderson     tcg_temp_free(t0);
846*8816f70bSRichard Henderson     return true;
847*8816f70bSRichard Henderson }
848fcf5ef2aSThomas Huth 
849*8816f70bSRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a, uint32_t insn)
850fcf5ef2aSThomas Huth {
851*8816f70bSRichard Henderson     TCGv t0;
852*8816f70bSRichard Henderson 
853*8816f70bSRichard Henderson     LOG_DIS("l.addic r%d, r%d, %d\n", a->d, a->a, a->i);
854*8816f70bSRichard Henderson     check_r0_write(a->d);
855*8816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
856*8816f70bSRichard Henderson     gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0);
857*8816f70bSRichard Henderson     tcg_temp_free(t0);
858*8816f70bSRichard Henderson     return true;
859*8816f70bSRichard Henderson }
860*8816f70bSRichard Henderson 
861*8816f70bSRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a, uint32_t insn)
862*8816f70bSRichard Henderson {
863*8816f70bSRichard Henderson     TCGv t0;
864*8816f70bSRichard Henderson 
865*8816f70bSRichard Henderson     LOG_DIS("l.muli r%d, r%d, %d\n", a->d, a->a, a->i);
866*8816f70bSRichard Henderson     check_r0_write(a->d);
867*8816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
868*8816f70bSRichard Henderson     gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0);
869*8816f70bSRichard Henderson     tcg_temp_free(t0);
870*8816f70bSRichard Henderson     return true;
871*8816f70bSRichard Henderson }
872*8816f70bSRichard Henderson 
873*8816f70bSRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a, uint32_t insn)
874*8816f70bSRichard Henderson {
875*8816f70bSRichard Henderson     TCGv t0;
876*8816f70bSRichard Henderson 
877*8816f70bSRichard Henderson     LOG_DIS("l.maci r%d, %d\n", a->a, a->i);
878*8816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
879*8816f70bSRichard Henderson     gen_mac(dc, cpu_R[a->a], t0);
880*8816f70bSRichard Henderson     tcg_temp_free(t0);
881*8816f70bSRichard Henderson     return true;
882*8816f70bSRichard Henderson }
883*8816f70bSRichard Henderson 
884*8816f70bSRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a, uint32_t insn)
885*8816f70bSRichard Henderson {
886*8816f70bSRichard Henderson     LOG_DIS("l.andi r%d, r%d, %d\n", a->d, a->a, a->k);
887*8816f70bSRichard Henderson     check_r0_write(a->d);
888*8816f70bSRichard Henderson     tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k);
889*8816f70bSRichard Henderson     return true;
890*8816f70bSRichard Henderson }
891*8816f70bSRichard Henderson 
892*8816f70bSRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a, uint32_t insn)
893*8816f70bSRichard Henderson {
894*8816f70bSRichard Henderson     LOG_DIS("l.ori r%d, r%d, %d\n", a->d, a->a, a->k);
895*8816f70bSRichard Henderson     check_r0_write(a->d);
896*8816f70bSRichard Henderson     tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k);
897*8816f70bSRichard Henderson     return true;
898*8816f70bSRichard Henderson }
899*8816f70bSRichard Henderson 
900*8816f70bSRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a, uint32_t insn)
901*8816f70bSRichard Henderson {
902*8816f70bSRichard Henderson     LOG_DIS("l.xori r%d, r%d, %d\n", a->d, a->a, a->i);
903*8816f70bSRichard Henderson     check_r0_write(a->d);
904*8816f70bSRichard Henderson     tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i);
905*8816f70bSRichard Henderson     return true;
906*8816f70bSRichard Henderson }
907*8816f70bSRichard Henderson 
908*8816f70bSRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a, uint32_t insn)
909*8816f70bSRichard Henderson {
910*8816f70bSRichard Henderson     LOG_DIS("l.mfspr r%d, r%d, %d\n", a->d, a->a, a->k);
911*8816f70bSRichard Henderson     check_r0_write(a->d);
912*8816f70bSRichard Henderson 
913*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY
914*8816f70bSRichard Henderson     gen_illegal_exception(dc);
915fcf5ef2aSThomas Huth #else
916fcf5ef2aSThomas Huth     if (dc->mem_idx == MMU_USER_IDX) {
917fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
918*8816f70bSRichard Henderson     } else {
919*8816f70bSRichard Henderson         TCGv_i32 ti = tcg_const_i32(a->k);
920*8816f70bSRichard Henderson         gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], cpu_R[a->a], ti);
921fcf5ef2aSThomas Huth         tcg_temp_free_i32(ti);
922fcf5ef2aSThomas Huth     }
923*8816f70bSRichard Henderson #endif
924*8816f70bSRichard Henderson     return true;
925*8816f70bSRichard Henderson }
926fcf5ef2aSThomas Huth 
927*8816f70bSRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a, uint32_t insn)
928fcf5ef2aSThomas Huth {
929*8816f70bSRichard Henderson     LOG_DIS("l.mtspr r%d, r%d, %d\n", a->a, a->b, a->k);
930*8816f70bSRichard Henderson 
931*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY
932*8816f70bSRichard Henderson     gen_illegal_exception(dc);
933fcf5ef2aSThomas Huth #else
934fcf5ef2aSThomas Huth     if (dc->mem_idx == MMU_USER_IDX) {
935fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
936*8816f70bSRichard Henderson     } else {
937*8816f70bSRichard Henderson         TCGv_i32 ti = tcg_const_i32(a->k);
938*8816f70bSRichard Henderson         gen_helper_mtspr(cpu_env, cpu_R[a->a], cpu_R[a->b], ti);
939*8816f70bSRichard Henderson         tcg_temp_free_i32(ti);
940fcf5ef2aSThomas Huth     }
941fcf5ef2aSThomas Huth #endif
942*8816f70bSRichard Henderson     return true;
943fcf5ef2aSThomas Huth }
944fcf5ef2aSThomas Huth 
945fcf5ef2aSThomas Huth static void dec_mac(DisasContext *dc, uint32_t insn)
946fcf5ef2aSThomas Huth {
947fcf5ef2aSThomas Huth     uint32_t op0;
948fcf5ef2aSThomas Huth     uint32_t ra, rb;
949fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 4);
950fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
951fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
952fcf5ef2aSThomas Huth 
953fcf5ef2aSThomas Huth     switch (op0) {
954fcf5ef2aSThomas Huth     case 0x0001:    /* l.mac */
955fcf5ef2aSThomas Huth         LOG_DIS("l.mac r%d, r%d\n", ra, rb);
9566f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], cpu_R[rb]);
957fcf5ef2aSThomas Huth         break;
958fcf5ef2aSThomas Huth 
959fcf5ef2aSThomas Huth     case 0x0002:    /* l.msb */
960fcf5ef2aSThomas Huth         LOG_DIS("l.msb r%d, r%d\n", ra, rb);
9616f7332baSRichard Henderson         gen_msb(dc, cpu_R[ra], cpu_R[rb]);
962fcf5ef2aSThomas Huth         break;
963fcf5ef2aSThomas Huth 
964cc5de49eSRichard Henderson     case 0x0003:    /* l.macu */
965cc5de49eSRichard Henderson         LOG_DIS("l.macu r%d, r%d\n", ra, rb);
966cc5de49eSRichard Henderson         gen_macu(dc, cpu_R[ra], cpu_R[rb]);
967cc5de49eSRichard Henderson         break;
968cc5de49eSRichard Henderson 
969cc5de49eSRichard Henderson     case 0x0004:    /* l.msbu */
970cc5de49eSRichard Henderson         LOG_DIS("l.msbu r%d, r%d\n", ra, rb);
971cc5de49eSRichard Henderson         gen_msbu(dc, cpu_R[ra], cpu_R[rb]);
972cc5de49eSRichard Henderson         break;
973cc5de49eSRichard Henderson 
974fcf5ef2aSThomas Huth     default:
975fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
976fcf5ef2aSThomas Huth         break;
977fcf5ef2aSThomas Huth    }
978fcf5ef2aSThomas Huth }
979fcf5ef2aSThomas Huth 
980fcf5ef2aSThomas Huth static void dec_logic(DisasContext *dc, uint32_t insn)
981fcf5ef2aSThomas Huth {
982fcf5ef2aSThomas Huth     uint32_t op0;
9836da544a6SRichard Henderson     uint32_t rd, ra, L6, S6;
984fcf5ef2aSThomas Huth     op0 = extract32(insn, 6, 2);
985fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
986fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
987fcf5ef2aSThomas Huth     L6 = extract32(insn, 0, 6);
9886da544a6SRichard Henderson     S6 = L6 & (TARGET_LONG_BITS - 1);
989fcf5ef2aSThomas Huth 
9906597c28dSRichard Henderson     check_r0_write(rd);
991fcf5ef2aSThomas Huth     switch (op0) {
992fcf5ef2aSThomas Huth     case 0x00:    /* l.slli */
993fcf5ef2aSThomas Huth         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
9946da544a6SRichard Henderson         tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6);
995fcf5ef2aSThomas Huth         break;
996fcf5ef2aSThomas Huth 
997fcf5ef2aSThomas Huth     case 0x01:    /* l.srli */
998fcf5ef2aSThomas Huth         LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
9996da544a6SRichard Henderson         tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6);
1000fcf5ef2aSThomas Huth         break;
1001fcf5ef2aSThomas Huth 
1002fcf5ef2aSThomas Huth     case 0x02:    /* l.srai */
1003fcf5ef2aSThomas Huth         LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
10046da544a6SRichard Henderson         tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6);
10056da544a6SRichard Henderson         break;
1006fcf5ef2aSThomas Huth 
1007fcf5ef2aSThomas Huth     case 0x03:    /* l.rori */
1008fcf5ef2aSThomas Huth         LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
10096da544a6SRichard Henderson         tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6);
1010fcf5ef2aSThomas Huth         break;
1011fcf5ef2aSThomas Huth 
1012fcf5ef2aSThomas Huth     default:
1013fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1014fcf5ef2aSThomas Huth         break;
1015fcf5ef2aSThomas Huth     }
1016fcf5ef2aSThomas Huth }
1017fcf5ef2aSThomas Huth 
1018fcf5ef2aSThomas Huth static void dec_M(DisasContext *dc, uint32_t insn)
1019fcf5ef2aSThomas Huth {
1020fcf5ef2aSThomas Huth     uint32_t op0;
1021fcf5ef2aSThomas Huth     uint32_t rd;
1022fcf5ef2aSThomas Huth     uint32_t K16;
1023fcf5ef2aSThomas Huth     op0 = extract32(insn, 16, 1);
1024fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
1025fcf5ef2aSThomas Huth     K16 = extract32(insn, 0, 16);
1026fcf5ef2aSThomas Huth 
10276597c28dSRichard Henderson     check_r0_write(rd);
1028fcf5ef2aSThomas Huth     switch (op0) {
1029fcf5ef2aSThomas Huth     case 0x0:    /* l.movhi */
1030fcf5ef2aSThomas Huth         LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
1031fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
1032fcf5ef2aSThomas Huth         break;
1033fcf5ef2aSThomas Huth 
1034fcf5ef2aSThomas Huth     case 0x1:    /* l.macrc */
1035fcf5ef2aSThomas Huth         LOG_DIS("l.macrc  r%d\n", rd);
10366f7332baSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
10376f7332baSRichard Henderson         tcg_gen_movi_i64(cpu_mac, 0);
1038fcf5ef2aSThomas Huth         break;
1039fcf5ef2aSThomas Huth 
1040fcf5ef2aSThomas Huth     default:
1041fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1042fcf5ef2aSThomas Huth         break;
1043fcf5ef2aSThomas Huth     }
1044fcf5ef2aSThomas Huth }
1045fcf5ef2aSThomas Huth 
1046fcf5ef2aSThomas Huth static void dec_comp(DisasContext *dc, uint32_t insn)
1047fcf5ef2aSThomas Huth {
1048fcf5ef2aSThomas Huth     uint32_t op0;
1049fcf5ef2aSThomas Huth     uint32_t ra, rb;
1050fcf5ef2aSThomas Huth 
1051fcf5ef2aSThomas Huth     op0 = extract32(insn, 21, 5);
1052fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1053fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
1054fcf5ef2aSThomas Huth 
1055fcf5ef2aSThomas Huth     /* unsigned integers  */
1056fcf5ef2aSThomas Huth     tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
1057fcf5ef2aSThomas Huth     tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
1058fcf5ef2aSThomas Huth 
1059fcf5ef2aSThomas Huth     switch (op0) {
1060fcf5ef2aSThomas Huth     case 0x0:    /* l.sfeq */
1061fcf5ef2aSThomas Huth         LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
106284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1063fcf5ef2aSThomas Huth         break;
1064fcf5ef2aSThomas Huth 
1065fcf5ef2aSThomas Huth     case 0x1:    /* l.sfne */
1066fcf5ef2aSThomas Huth         LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
106784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1068fcf5ef2aSThomas Huth         break;
1069fcf5ef2aSThomas Huth 
1070fcf5ef2aSThomas Huth     case 0x2:    /* l.sfgtu */
1071fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
107284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1073fcf5ef2aSThomas Huth         break;
1074fcf5ef2aSThomas Huth 
1075fcf5ef2aSThomas Huth     case 0x3:    /* l.sfgeu */
1076fcf5ef2aSThomas Huth         LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
107784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1078fcf5ef2aSThomas Huth         break;
1079fcf5ef2aSThomas Huth 
1080fcf5ef2aSThomas Huth     case 0x4:    /* l.sfltu */
1081fcf5ef2aSThomas Huth         LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
108284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1083fcf5ef2aSThomas Huth         break;
1084fcf5ef2aSThomas Huth 
1085fcf5ef2aSThomas Huth     case 0x5:    /* l.sfleu */
1086fcf5ef2aSThomas Huth         LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
108784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1088fcf5ef2aSThomas Huth         break;
1089fcf5ef2aSThomas Huth 
1090fcf5ef2aSThomas Huth     case 0xa:    /* l.sfgts */
1091fcf5ef2aSThomas Huth         LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
109284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1093fcf5ef2aSThomas Huth         break;
1094fcf5ef2aSThomas Huth 
1095fcf5ef2aSThomas Huth     case 0xb:    /* l.sfges */
1096fcf5ef2aSThomas Huth         LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
109784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1098fcf5ef2aSThomas Huth         break;
1099fcf5ef2aSThomas Huth 
1100fcf5ef2aSThomas Huth     case 0xc:    /* l.sflts */
1101fcf5ef2aSThomas Huth         LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
110284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1103fcf5ef2aSThomas Huth         break;
1104fcf5ef2aSThomas Huth 
1105fcf5ef2aSThomas Huth     case 0xd:    /* l.sfles */
1106fcf5ef2aSThomas Huth         LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
110784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1108fcf5ef2aSThomas Huth         break;
1109fcf5ef2aSThomas Huth 
1110fcf5ef2aSThomas Huth     default:
1111fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1112fcf5ef2aSThomas Huth         break;
1113fcf5ef2aSThomas Huth     }
1114fcf5ef2aSThomas Huth }
1115fcf5ef2aSThomas Huth 
1116fcf5ef2aSThomas Huth static void dec_compi(DisasContext *dc, uint32_t insn)
1117fcf5ef2aSThomas Huth {
11186da544a6SRichard Henderson     uint32_t op0, ra;
11196da544a6SRichard Henderson     int32_t I16;
1120fcf5ef2aSThomas Huth 
1121fcf5ef2aSThomas Huth     op0 = extract32(insn, 21, 5);
1122fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
11236da544a6SRichard Henderson     I16 = sextract32(insn, 0, 16);
1124fcf5ef2aSThomas Huth 
1125fcf5ef2aSThomas Huth     switch (op0) {
1126fcf5ef2aSThomas Huth     case 0x0:    /* l.sfeqi */
1127fcf5ef2aSThomas Huth         LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
112884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16);
1129fcf5ef2aSThomas Huth         break;
1130fcf5ef2aSThomas Huth 
1131fcf5ef2aSThomas Huth     case 0x1:    /* l.sfnei */
1132fcf5ef2aSThomas Huth         LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
113384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16);
1134fcf5ef2aSThomas Huth         break;
1135fcf5ef2aSThomas Huth 
1136fcf5ef2aSThomas Huth     case 0x2:    /* l.sfgtui */
1137fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
113884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16);
1139fcf5ef2aSThomas Huth         break;
1140fcf5ef2aSThomas Huth 
1141fcf5ef2aSThomas Huth     case 0x3:    /* l.sfgeui */
1142fcf5ef2aSThomas Huth         LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
114384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16);
1144fcf5ef2aSThomas Huth         break;
1145fcf5ef2aSThomas Huth 
1146fcf5ef2aSThomas Huth     case 0x4:    /* l.sfltui */
1147fcf5ef2aSThomas Huth         LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
114884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16);
1149fcf5ef2aSThomas Huth         break;
1150fcf5ef2aSThomas Huth 
1151fcf5ef2aSThomas Huth     case 0x5:    /* l.sfleui */
1152fcf5ef2aSThomas Huth         LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
115384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16);
1154fcf5ef2aSThomas Huth         break;
1155fcf5ef2aSThomas Huth 
1156fcf5ef2aSThomas Huth     case 0xa:    /* l.sfgtsi */
1157fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
115884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16);
1159fcf5ef2aSThomas Huth         break;
1160fcf5ef2aSThomas Huth 
1161fcf5ef2aSThomas Huth     case 0xb:    /* l.sfgesi */
1162fcf5ef2aSThomas Huth         LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
116384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16);
1164fcf5ef2aSThomas Huth         break;
1165fcf5ef2aSThomas Huth 
1166fcf5ef2aSThomas Huth     case 0xc:    /* l.sfltsi */
1167fcf5ef2aSThomas Huth         LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
116884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16);
1169fcf5ef2aSThomas Huth         break;
1170fcf5ef2aSThomas Huth 
1171fcf5ef2aSThomas Huth     case 0xd:    /* l.sflesi */
1172fcf5ef2aSThomas Huth         LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
117384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16);
1174fcf5ef2aSThomas Huth         break;
1175fcf5ef2aSThomas Huth 
1176fcf5ef2aSThomas Huth     default:
1177fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1178fcf5ef2aSThomas Huth         break;
1179fcf5ef2aSThomas Huth     }
1180fcf5ef2aSThomas Huth }
1181fcf5ef2aSThomas Huth 
11827de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn)
1183fcf5ef2aSThomas Huth {
11847de9729fSRichard Henderson     LOG_DIS("l.sys %d\n", a->k);
11851ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1186fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_SYSCALL);
11871ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11887de9729fSRichard Henderson     return true;
11897de9729fSRichard Henderson }
1190fcf5ef2aSThomas Huth 
11917de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn)
11927de9729fSRichard Henderson {
11937de9729fSRichard Henderson     LOG_DIS("l.trap %d\n", a->k);
11941ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1195fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_TRAP);
11961ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11977de9729fSRichard Henderson     return true;
11987de9729fSRichard Henderson }
1199fcf5ef2aSThomas Huth 
12007de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn)
12017de9729fSRichard Henderson {
1202fcf5ef2aSThomas Huth     LOG_DIS("l.msync\n");
120324fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
12047de9729fSRichard Henderson     return true;
1205fcf5ef2aSThomas Huth }
12067de9729fSRichard Henderson 
12077de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn)
12087de9729fSRichard Henderson {
12097de9729fSRichard Henderson     LOG_DIS("l.psync\n");
12107de9729fSRichard Henderson     return true;
12117de9729fSRichard Henderson }
12127de9729fSRichard Henderson 
12137de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn)
12147de9729fSRichard Henderson {
12157de9729fSRichard Henderson     LOG_DIS("l.csync\n");
12167de9729fSRichard Henderson     return true;
1217fcf5ef2aSThomas Huth }
1218fcf5ef2aSThomas Huth 
1219*8816f70bSRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a, uint32_t insn)
1220*8816f70bSRichard Henderson {
1221*8816f70bSRichard Henderson     LOG_DIS("l.rfe\n");
1222*8816f70bSRichard Henderson 
1223*8816f70bSRichard Henderson #ifdef CONFIG_USER_ONLY
1224*8816f70bSRichard Henderson     gen_illegal_exception(dc);
1225*8816f70bSRichard Henderson #else
1226*8816f70bSRichard Henderson     if (dc->mem_idx == MMU_USER_IDX) {
1227*8816f70bSRichard Henderson         gen_illegal_exception(dc);
1228*8816f70bSRichard Henderson     } else {
1229*8816f70bSRichard Henderson         gen_helper_rfe(cpu_env);
1230*8816f70bSRichard Henderson         dc->base.is_jmp = DISAS_UPDATE;
1231*8816f70bSRichard Henderson     }
1232*8816f70bSRichard Henderson #endif
1233*8816f70bSRichard Henderson     return true;
1234*8816f70bSRichard Henderson }
1235*8816f70bSRichard Henderson 
1236fcf5ef2aSThomas Huth static void dec_float(DisasContext *dc, uint32_t insn)
1237fcf5ef2aSThomas Huth {
1238fcf5ef2aSThomas Huth     uint32_t op0;
1239fcf5ef2aSThomas Huth     uint32_t ra, rb, rd;
1240fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 8);
1241fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1242fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
1243fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
1244fcf5ef2aSThomas Huth 
1245fcf5ef2aSThomas Huth     switch (op0) {
1246fcf5ef2aSThomas Huth     case 0x00: /* lf.add.s */
1247fcf5ef2aSThomas Huth         LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
12486597c28dSRichard Henderson         check_r0_write(rd);
1249fcf5ef2aSThomas Huth         gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12504e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1251fcf5ef2aSThomas Huth         break;
1252fcf5ef2aSThomas Huth 
1253fcf5ef2aSThomas Huth     case 0x01: /* lf.sub.s */
1254fcf5ef2aSThomas Huth         LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
12556597c28dSRichard Henderson         check_r0_write(rd);
1256fcf5ef2aSThomas Huth         gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12574e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1258fcf5ef2aSThomas Huth         break;
1259fcf5ef2aSThomas Huth 
1260fcf5ef2aSThomas Huth     case 0x02:    /* lf.mul.s */
1261fcf5ef2aSThomas Huth         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
12626597c28dSRichard Henderson         check_r0_write(rd);
1263fcf5ef2aSThomas Huth         gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12644e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1265fcf5ef2aSThomas Huth         break;
1266fcf5ef2aSThomas Huth 
1267fcf5ef2aSThomas Huth     case 0x03: /* lf.div.s */
1268fcf5ef2aSThomas Huth         LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
12696597c28dSRichard Henderson         check_r0_write(rd);
1270fcf5ef2aSThomas Huth         gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12714e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1272fcf5ef2aSThomas Huth         break;
1273fcf5ef2aSThomas Huth 
1274fcf5ef2aSThomas Huth     case 0x04: /* lf.itof.s */
1275fcf5ef2aSThomas Huth         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
12766597c28dSRichard Henderson         check_r0_write(rd);
1277fcf5ef2aSThomas Huth         gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
12784e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1279fcf5ef2aSThomas Huth         break;
1280fcf5ef2aSThomas Huth 
1281fcf5ef2aSThomas Huth     case 0x05: /* lf.ftoi.s */
1282fcf5ef2aSThomas Huth         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
12836597c28dSRichard Henderson         check_r0_write(rd);
1284fcf5ef2aSThomas Huth         gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
12854e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1286fcf5ef2aSThomas Huth         break;
1287fcf5ef2aSThomas Huth 
1288fcf5ef2aSThomas Huth     case 0x06: /* lf.rem.s */
1289fcf5ef2aSThomas Huth         LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
12906597c28dSRichard Henderson         check_r0_write(rd);
1291fcf5ef2aSThomas Huth         gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12924e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1293fcf5ef2aSThomas Huth         break;
1294fcf5ef2aSThomas Huth 
1295fcf5ef2aSThomas Huth     case 0x07: /* lf.madd.s */
1296fcf5ef2aSThomas Huth         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
12976597c28dSRichard Henderson         check_r0_write(rd);
1298762e22edSRichard Henderson         gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
1299762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
13004e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1301fcf5ef2aSThomas Huth         break;
1302fcf5ef2aSThomas Huth 
1303fcf5ef2aSThomas Huth     case 0x08: /* lf.sfeq.s */
1304fcf5ef2aSThomas Huth         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
130584775c43SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13064e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1307fcf5ef2aSThomas Huth         break;
1308fcf5ef2aSThomas Huth 
1309fcf5ef2aSThomas Huth     case 0x09: /* lf.sfne.s */
1310fcf5ef2aSThomas Huth         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
13114e2d3007SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13124e2d3007SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
13134e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1314fcf5ef2aSThomas Huth         break;
1315fcf5ef2aSThomas Huth 
1316fcf5ef2aSThomas Huth     case 0x0a: /* lf.sfgt.s */
1317fcf5ef2aSThomas Huth         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
13184e2d3007SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
13194e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1320fcf5ef2aSThomas Huth         break;
1321fcf5ef2aSThomas Huth 
1322fcf5ef2aSThomas Huth     case 0x0b: /* lf.sfge.s */
1323fcf5ef2aSThomas Huth         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
13244e2d3007SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
13254e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1326fcf5ef2aSThomas Huth         break;
1327fcf5ef2aSThomas Huth 
1328fcf5ef2aSThomas Huth     case 0x0c: /* lf.sflt.s */
1329fcf5ef2aSThomas Huth         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
133084775c43SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13314e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1332fcf5ef2aSThomas Huth         break;
1333fcf5ef2aSThomas Huth 
1334fcf5ef2aSThomas Huth     case 0x0d: /* lf.sfle.s */
1335fcf5ef2aSThomas Huth         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
133684775c43SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13374e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1338fcf5ef2aSThomas Huth         break;
1339fcf5ef2aSThomas Huth 
13404e2d3007SRichard Henderson #ifdef TARGET_OPENRISC64
13414e2d3007SRichard Henderson     case 0x10: /* lf.add.d */
1342fcf5ef2aSThomas Huth         LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
1343fcf5ef2aSThomas Huth         check_of64s(dc);
13446597c28dSRichard Henderson         check_r0_write(rd);
1345fcf5ef2aSThomas Huth         gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13464e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1347fcf5ef2aSThomas Huth         break;
1348fcf5ef2aSThomas Huth 
13494e2d3007SRichard Henderson     case 0x11: /* lf.sub.d */
1350fcf5ef2aSThomas Huth         LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
1351fcf5ef2aSThomas Huth         check_of64s(dc);
13526597c28dSRichard Henderson         check_r0_write(rd);
1353fcf5ef2aSThomas Huth         gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13544e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1355fcf5ef2aSThomas Huth         break;
1356fcf5ef2aSThomas Huth 
13574e2d3007SRichard Henderson     case 0x12: /* lf.mul.d */
1358fcf5ef2aSThomas Huth         LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
1359fcf5ef2aSThomas Huth         check_of64s(dc);
13606597c28dSRichard Henderson         check_r0_write(rd);
1361fcf5ef2aSThomas Huth         gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13624e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1363fcf5ef2aSThomas Huth         break;
1364fcf5ef2aSThomas Huth 
13654e2d3007SRichard Henderson     case 0x13: /* lf.div.d */
1366fcf5ef2aSThomas Huth         LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
1367fcf5ef2aSThomas Huth         check_of64s(dc);
13686597c28dSRichard Henderson         check_r0_write(rd);
1369fcf5ef2aSThomas Huth         gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13704e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1371fcf5ef2aSThomas Huth         break;
1372fcf5ef2aSThomas Huth 
13734e2d3007SRichard Henderson     case 0x14: /* lf.itof.d */
1374fcf5ef2aSThomas Huth         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
1375fcf5ef2aSThomas Huth         check_of64s(dc);
13766597c28dSRichard Henderson         check_r0_write(rd);
1377fcf5ef2aSThomas Huth         gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
13784e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1379fcf5ef2aSThomas Huth         break;
1380fcf5ef2aSThomas Huth 
13814e2d3007SRichard Henderson     case 0x15: /* lf.ftoi.d */
1382fcf5ef2aSThomas Huth         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
1383fcf5ef2aSThomas Huth         check_of64s(dc);
13846597c28dSRichard Henderson         check_r0_write(rd);
1385fcf5ef2aSThomas Huth         gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
13864e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1387fcf5ef2aSThomas Huth         break;
1388fcf5ef2aSThomas Huth 
13894e2d3007SRichard Henderson     case 0x16: /* lf.rem.d */
1390fcf5ef2aSThomas Huth         LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
1391fcf5ef2aSThomas Huth         check_of64s(dc);
13926597c28dSRichard Henderson         check_r0_write(rd);
1393fcf5ef2aSThomas Huth         gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13944e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1395fcf5ef2aSThomas Huth         break;
1396fcf5ef2aSThomas Huth 
13974e2d3007SRichard Henderson     case 0x17: /* lf.madd.d */
1398fcf5ef2aSThomas Huth         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
1399fcf5ef2aSThomas Huth         check_of64s(dc);
14006597c28dSRichard Henderson         check_r0_write(rd);
1401762e22edSRichard Henderson         gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
1402762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
14034e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1404fcf5ef2aSThomas Huth         break;
1405fcf5ef2aSThomas Huth 
14064e2d3007SRichard Henderson     case 0x18: /* lf.sfeq.d */
1407fcf5ef2aSThomas Huth         LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
1408fcf5ef2aSThomas Huth         check_of64s(dc);
140984775c43SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14104e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1411fcf5ef2aSThomas Huth         break;
1412fcf5ef2aSThomas Huth 
14134e2d3007SRichard Henderson     case 0x1a: /* lf.sfgt.d */
1414fcf5ef2aSThomas Huth         LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
1415fcf5ef2aSThomas Huth         check_of64s(dc);
14164e2d3007SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
14174e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1418fcf5ef2aSThomas Huth         break;
1419fcf5ef2aSThomas Huth 
14204e2d3007SRichard Henderson     case 0x1b: /* lf.sfge.d */
1421fcf5ef2aSThomas Huth         LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
1422fcf5ef2aSThomas Huth         check_of64s(dc);
14234e2d3007SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
14244e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1425fcf5ef2aSThomas Huth         break;
1426fcf5ef2aSThomas Huth 
14274e2d3007SRichard Henderson     case 0x19: /* lf.sfne.d */
1428fcf5ef2aSThomas Huth         LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
1429fcf5ef2aSThomas Huth         check_of64s(dc);
14304e2d3007SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14314e2d3007SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
14324e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1433fcf5ef2aSThomas Huth         break;
1434fcf5ef2aSThomas Huth 
14354e2d3007SRichard Henderson     case 0x1c: /* lf.sflt.d */
1436fcf5ef2aSThomas Huth         LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
1437fcf5ef2aSThomas Huth         check_of64s(dc);
143884775c43SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14394e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1440fcf5ef2aSThomas Huth         break;
1441fcf5ef2aSThomas Huth 
14424e2d3007SRichard Henderson     case 0x1d: /* lf.sfle.d */
1443fcf5ef2aSThomas Huth         LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
1444fcf5ef2aSThomas Huth         check_of64s(dc);
144584775c43SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14464e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1447fcf5ef2aSThomas Huth         break;
14484e2d3007SRichard Henderson #endif
1449fcf5ef2aSThomas Huth 
1450fcf5ef2aSThomas Huth     default:
1451fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1452fcf5ef2aSThomas Huth         break;
1453fcf5ef2aSThomas Huth     }
1454fcf5ef2aSThomas Huth }
1455fcf5ef2aSThomas Huth 
1456fcf5ef2aSThomas Huth static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
1457fcf5ef2aSThomas Huth {
1458fcf5ef2aSThomas Huth     uint32_t op0;
14597de9729fSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1460fcf5ef2aSThomas Huth 
14617de9729fSRichard Henderson     /* Transition to the auto-generated decoder.  */
14627de9729fSRichard Henderson     if (decode(dc, insn)) {
14637de9729fSRichard Henderson         return;
14647de9729fSRichard Henderson     }
14657de9729fSRichard Henderson 
14667de9729fSRichard Henderson     op0 = extract32(insn, 26, 6);
1467fcf5ef2aSThomas Huth     switch (op0) {
1468fcf5ef2aSThomas Huth     case 0x06:
1469fcf5ef2aSThomas Huth         dec_M(dc, insn);
1470fcf5ef2aSThomas Huth         break;
1471fcf5ef2aSThomas Huth 
1472fcf5ef2aSThomas Huth     case 0x2e:
1473fcf5ef2aSThomas Huth         dec_logic(dc, insn);
1474fcf5ef2aSThomas Huth         break;
1475fcf5ef2aSThomas Huth 
1476fcf5ef2aSThomas Huth     case 0x2f:
1477fcf5ef2aSThomas Huth         dec_compi(dc, insn);
1478fcf5ef2aSThomas Huth         break;
1479fcf5ef2aSThomas Huth 
1480fcf5ef2aSThomas Huth     case 0x31:
1481fcf5ef2aSThomas Huth         dec_mac(dc, insn);
1482fcf5ef2aSThomas Huth         break;
1483fcf5ef2aSThomas Huth 
1484fcf5ef2aSThomas Huth     case 0x32:
1485fcf5ef2aSThomas Huth         dec_float(dc, insn);
1486fcf5ef2aSThomas Huth         break;
1487fcf5ef2aSThomas Huth 
1488fcf5ef2aSThomas Huth     case 0x38:
1489fcf5ef2aSThomas Huth         dec_calc(dc, insn);
1490fcf5ef2aSThomas Huth         break;
1491fcf5ef2aSThomas Huth 
1492fcf5ef2aSThomas Huth     case 0x39:
1493fcf5ef2aSThomas Huth         dec_comp(dc, insn);
1494fcf5ef2aSThomas Huth         break;
1495fcf5ef2aSThomas Huth 
1496fcf5ef2aSThomas Huth     default:
1497*8816f70bSRichard Henderson         gen_illegal_exception(dc);
1498fcf5ef2aSThomas Huth         break;
1499fcf5ef2aSThomas Huth     }
1500fcf5ef2aSThomas Huth }
1501fcf5ef2aSThomas Huth 
1502a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1503fcf5ef2aSThomas Huth {
1504a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
15059c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1506a4fd3ec3SEmilio G. Cota     int bound;
1507fcf5ef2aSThomas Huth 
1508a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
15091ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1510a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1511a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1512a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1513fcf5ef2aSThomas Huth }
1514fcf5ef2aSThomas Huth 
1515a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1516a4fd3ec3SEmilio G. Cota {
1517a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1518fcf5ef2aSThomas Huth 
15196597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15206597c28dSRichard Henderson        when it's true, which is the common case.  */
15216597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
15226597c28dSRichard Henderson         cpu_R[0] = tcg_const_tl(0);
15236597c28dSRichard Henderson     } else {
15246597c28dSRichard Henderson         cpu_R[0] = cpu_R0;
15256597c28dSRichard Henderson     }
1526a4fd3ec3SEmilio G. Cota }
15276597c28dSRichard Henderson 
1528a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1529a4fd3ec3SEmilio G. Cota {
1530a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1531a4fd3ec3SEmilio G. Cota 
15321ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1533a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1534a4fd3ec3SEmilio G. Cota }
1535fcf5ef2aSThomas Huth 
1536a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1537a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1538a4fd3ec3SEmilio G. Cota {
1539a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1540a4fd3ec3SEmilio G. Cota 
15411ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1542fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_DEBUG);
15431ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1544fcf5ef2aSThomas Huth     /* The address covered by the breakpoint must be included in
1545fcf5ef2aSThomas Huth        [tb->pc, tb->pc + tb->size) in order to for it to be
1546fcf5ef2aSThomas Huth        properly cleared -- thus we increment the PC here so that
1547fcf5ef2aSThomas Huth        the logic setting tb->size below does the right thing.  */
15481ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1549a4fd3ec3SEmilio G. Cota     return true;
1550fcf5ef2aSThomas Huth }
1551fcf5ef2aSThomas Huth 
1552a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1553a4fd3ec3SEmilio G. Cota {
1554a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1555a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1556a4fd3ec3SEmilio G. Cota 
1557fcf5ef2aSThomas Huth     disas_openrisc_insn(dc, cpu);
15581ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
155924c32852SRichard Henderson 
1560fcf5ef2aSThomas Huth     /* delay slot */
1561fcf5ef2aSThomas Huth     if (dc->delayed_branch) {
1562fcf5ef2aSThomas Huth         dc->delayed_branch--;
1563fcf5ef2aSThomas Huth         if (!dc->delayed_branch) {
1564fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, jmp_pc);
156524c32852SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
15661ffa4bceSEmilio G. Cota             dc->base.is_jmp = DISAS_UPDATE;
1567a4fd3ec3SEmilio G. Cota             return;
1568fcf5ef2aSThomas Huth         }
1569fcf5ef2aSThomas Huth     }
1570a4fd3ec3SEmilio G. Cota }
1571fcf5ef2aSThomas Huth 
1572a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1573a4fd3ec3SEmilio G. Cota {
1574a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
157524c32852SRichard Henderson 
1576a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1577a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1578a01deb36SRichard Henderson     }
1579a01deb36SRichard Henderson 
15801ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
15811ffa4bceSEmilio G. Cota     if (dc->base.is_jmp == DISAS_NEXT) {
15821ffa4bceSEmilio G. Cota         dc->base.is_jmp = DISAS_UPDATE;
15831ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1584fcf5ef2aSThomas Huth     }
15851ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
1586fcf5ef2aSThomas Huth         gen_exception(dc, EXCP_DEBUG);
1587fcf5ef2aSThomas Huth     } else {
15881ffa4bceSEmilio G. Cota         switch (dc->base.is_jmp) {
1589a4fd3ec3SEmilio G. Cota         case DISAS_TOO_MANY:
15901ffa4bceSEmilio G. Cota             gen_goto_tb(dc, 0, dc->base.pc_next);
1591fcf5ef2aSThomas Huth             break;
15921ffa4bceSEmilio G. Cota         case DISAS_NORETURN:
1593fcf5ef2aSThomas Huth         case DISAS_JUMP:
15941ffa4bceSEmilio G. Cota         case DISAS_TB_JUMP:
1595fcf5ef2aSThomas Huth             break;
1596fcf5ef2aSThomas Huth         case DISAS_UPDATE:
1597fcf5ef2aSThomas Huth             /* indicate that the hash table must be used
1598fcf5ef2aSThomas Huth                to find the next TB */
1599fcf5ef2aSThomas Huth             tcg_gen_exit_tb(0);
1600fcf5ef2aSThomas Huth             break;
1601a4fd3ec3SEmilio G. Cota         default:
1602a4fd3ec3SEmilio G. Cota             g_assert_not_reached();
1603a4fd3ec3SEmilio G. Cota         }
1604fcf5ef2aSThomas Huth     }
1605fcf5ef2aSThomas Huth }
1606fcf5ef2aSThomas Huth 
1607a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1608a4fd3ec3SEmilio G. Cota {
1609a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
1610fcf5ef2aSThomas Huth 
1611a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1612a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1613fcf5ef2aSThomas Huth }
1614a4fd3ec3SEmilio G. Cota 
1615a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1616a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1617a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1618a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1619a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1620a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1621a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1622a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1623a4fd3ec3SEmilio G. Cota };
1624a4fd3ec3SEmilio G. Cota 
1625a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
1626a4fd3ec3SEmilio G. Cota {
1627a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1628a4fd3ec3SEmilio G. Cota 
1629a4fd3ec3SEmilio G. Cota     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb);
1630fcf5ef2aSThomas Huth }
1631fcf5ef2aSThomas Huth 
1632fcf5ef2aSThomas Huth void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
1633fcf5ef2aSThomas Huth                              fprintf_function cpu_fprintf,
1634fcf5ef2aSThomas Huth                              int flags)
1635fcf5ef2aSThomas Huth {
1636fcf5ef2aSThomas Huth     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1637fcf5ef2aSThomas Huth     CPUOpenRISCState *env = &cpu->env;
1638fcf5ef2aSThomas Huth     int i;
1639fcf5ef2aSThomas Huth 
1640fcf5ef2aSThomas Huth     cpu_fprintf(f, "PC=%08x\n", env->pc);
1641fcf5ef2aSThomas Huth     for (i = 0; i < 32; ++i) {
1642d89e71e8SStafford Horne         cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1643fcf5ef2aSThomas Huth                     (i % 4) == 3 ? '\n' : ' ');
1644fcf5ef2aSThomas Huth     }
1645fcf5ef2aSThomas Huth }
1646fcf5ef2aSThomas Huth 
1647fcf5ef2aSThomas Huth void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1648fcf5ef2aSThomas Huth                           target_ulong *data)
1649fcf5ef2aSThomas Huth {
1650fcf5ef2aSThomas Huth     env->pc = data[0];
1651a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1652a01deb36SRichard Henderson     if (data[1] & 2) {
165324c32852SRichard Henderson         env->ppc = env->pc - 4;
165424c32852SRichard Henderson     }
1655fcf5ef2aSThomas Huth }
1656