xref: /qemu/target/openrisc/translate.c (revision 8b86d6d25807e13a63ab6ea879f976b9f18cc45a)
1e67db06eSJia Liu /*
2e67db06eSJia Liu  * OpenRISC translation
3e67db06eSJia Liu  *
4e67db06eSJia Liu  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5e67db06eSJia Liu  *                         Feng Gao <gf91597@gmail.com>
6e67db06eSJia Liu  *
7e67db06eSJia Liu  * This library is free software; you can redistribute it and/or
8e67db06eSJia Liu  * modify it under the terms of the GNU Lesser General Public
9e67db06eSJia Liu  * License as published by the Free Software Foundation; either
10779fc6adSThomas Huth  * version 2.1 of the License, or (at your option) any later version.
11e67db06eSJia Liu  *
12e67db06eSJia Liu  * This library is distributed in the hope that it will be useful,
13e67db06eSJia Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14e67db06eSJia Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15e67db06eSJia Liu  * Lesser General Public License for more details.
16e67db06eSJia Liu  *
17e67db06eSJia Liu  * You should have received a copy of the GNU Lesser General Public
18e67db06eSJia Liu  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19e67db06eSJia Liu  */
20e67db06eSJia Liu 
21ed2decc6SPeter Maydell #include "qemu/osdep.h"
22e67db06eSJia Liu #include "cpu.h"
23022c62cbSPaolo Bonzini #include "exec/exec-all.h"
2476cad711SPaolo Bonzini #include "disas/disas.h"
25e67db06eSJia Liu #include "tcg-op.h"
26e67db06eSJia Liu #include "qemu-common.h"
271de7afc9SPaolo Bonzini #include "qemu/log.h"
281de7afc9SPaolo Bonzini #include "qemu/bitops.h"
2990c84c56SMarkus Armbruster #include "qemu/qemu-print.h"
30f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
3177fc6f5eSLluís Vilanova #include "exec/translator.h"
32bbe418f2SJia Liu 
332ef6175aSRichard Henderson #include "exec/helper-proto.h"
342ef6175aSRichard Henderson #include "exec/helper-gen.h"
357de9729fSRichard Henderson #include "exec/gen-icount.h"
36e67db06eSJia Liu 
37a7e30d84SLluís Vilanova #include "trace-tcg.h"
38508127e2SPaolo Bonzini #include "exec/log.h"
39a7e30d84SLluís Vilanova 
4077fc6f5eSLluís Vilanova /* is_jmp field values */
4164e46c95SRichard Henderson #define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
428000ba56SRichard Henderson #define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
4377fc6f5eSLluís Vilanova 
44bbe418f2SJia Liu typedef struct DisasContext {
451ffa4bceSEmilio G. Cota     DisasContextBase base;
46bbe418f2SJia Liu     uint32_t mem_idx;
47a01deb36SRichard Henderson     uint32_t tb_flags;
48bbe418f2SJia Liu     uint32_t delayed_branch;
498000ba56SRichard Henderson 
508000ba56SRichard Henderson     /* If not -1, jmp_pc contains this value and so is a direct jump.  */
518000ba56SRichard Henderson     target_ulong jmp_pc_imm;
52bbe418f2SJia Liu } DisasContext;
53bbe418f2SJia Liu 
542ba65417SRichard Henderson static inline bool is_user(DisasContext *dc)
552ba65417SRichard Henderson {
562ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY
572ba65417SRichard Henderson     return true;
582ba65417SRichard Henderson #else
59b9bed1b9SRichard Henderson     return !(dc->tb_flags & TB_FLAGS_SM);
602ba65417SRichard Henderson #endif
612ba65417SRichard Henderson }
622ba65417SRichard Henderson 
637de9729fSRichard Henderson /* Include the auto-generated decoder.  */
647de9729fSRichard Henderson #include "decode.inc.c"
657de9729fSRichard Henderson 
66bbe418f2SJia Liu static TCGv cpu_sr;
67bbe418f2SJia Liu static TCGv cpu_R[32];
686597c28dSRichard Henderson static TCGv cpu_R0;
69bbe418f2SJia Liu static TCGv cpu_pc;
70bbe418f2SJia Liu static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
71bbe418f2SJia Liu static TCGv cpu_ppc;
7284775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
7397458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
7497458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
75930c3d00SRichard Henderson static TCGv cpu_lock_addr;
76930c3d00SRichard Henderson static TCGv cpu_lock_value;
77bbe418f2SJia Liu static TCGv_i32 fpcsr;
786f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
79a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
80bbe418f2SJia Liu 
81e67db06eSJia Liu void openrisc_translate_init(void)
82e67db06eSJia Liu {
83bbe418f2SJia Liu     static const char * const regnames[] = {
84bbe418f2SJia Liu         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
85bbe418f2SJia Liu         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
86bbe418f2SJia Liu         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
87bbe418f2SJia Liu         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
88bbe418f2SJia Liu     };
89bbe418f2SJia Liu     int i;
90bbe418f2SJia Liu 
91e1ccc054SRichard Henderson     cpu_sr = tcg_global_mem_new(cpu_env,
92bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, sr), "sr");
93a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
94a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
95a01deb36SRichard Henderson                                        "dflag");
96e1ccc054SRichard Henderson     cpu_pc = tcg_global_mem_new(cpu_env,
97bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, pc), "pc");
98e1ccc054SRichard Henderson     cpu_ppc = tcg_global_mem_new(cpu_env,
99bbe418f2SJia Liu                                  offsetof(CPUOpenRISCState, ppc), "ppc");
100e1ccc054SRichard Henderson     jmp_pc = tcg_global_mem_new(cpu_env,
101bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
10284775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
10384775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
10497458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
10597458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
10697458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
10797458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
108930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
109930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
110930c3d00SRichard Henderson                                        "lock_addr");
111930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
112930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
113930c3d00SRichard Henderson                                         "lock_value");
114e1ccc054SRichard Henderson     fpcsr = tcg_global_mem_new_i32(cpu_env,
115bbe418f2SJia Liu                                    offsetof(CPUOpenRISCState, fpcsr),
116bbe418f2SJia Liu                                    "fpcsr");
1176f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1186f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1196f7332baSRichard Henderson                                      "mac");
120bbe418f2SJia Liu     for (i = 0; i < 32; i++) {
121e1ccc054SRichard Henderson         cpu_R[i] = tcg_global_mem_new(cpu_env,
122d89e71e8SStafford Horne                                       offsetof(CPUOpenRISCState,
123d89e71e8SStafford Horne                                                shadow_gpr[0][i]),
124bbe418f2SJia Liu                                       regnames[i]);
125bbe418f2SJia Liu     }
1266597c28dSRichard Henderson     cpu_R0 = cpu_R[0];
127bbe418f2SJia Liu }
128bbe418f2SJia Liu 
129bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp)
130bbe418f2SJia Liu {
131bbe418f2SJia Liu     TCGv_i32 tmp = tcg_const_i32(excp);
132bbe418f2SJia Liu     gen_helper_exception(cpu_env, tmp);
133bbe418f2SJia Liu     tcg_temp_free_i32(tmp);
134bbe418f2SJia Liu }
135bbe418f2SJia Liu 
136bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc)
137bbe418f2SJia Liu {
1381ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
139bbe418f2SJia Liu     gen_exception(dc, EXCP_ILLEGAL);
1401ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
141bbe418f2SJia Liu }
142bbe418f2SJia Liu 
143bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
144bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
145bbe418f2SJia Liu static void check_ob64s(DisasContext *dc)
146bbe418f2SJia Liu {
147bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OB64S)) {
148bbe418f2SJia Liu         gen_illegal_exception(dc);
149bbe418f2SJia Liu     }
150bbe418f2SJia Liu }
151bbe418f2SJia Liu 
152bbe418f2SJia Liu static void check_of64s(DisasContext *dc)
153bbe418f2SJia Liu {
154bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OF64S)) {
155bbe418f2SJia Liu         gen_illegal_exception(dc);
156bbe418f2SJia Liu     }
157bbe418f2SJia Liu }
158bbe418f2SJia Liu 
159bbe418f2SJia Liu static void check_ov64s(DisasContext *dc)
160bbe418f2SJia Liu {
161bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OV64S)) {
162bbe418f2SJia Liu         gen_illegal_exception(dc);
163bbe418f2SJia Liu     }
164bbe418f2SJia Liu }
165bbe418f2SJia Liu #endif*/
166bbe418f2SJia Liu 
1676597c28dSRichard Henderson /* We're about to write to REG.  On the off-chance that the user is
1686597c28dSRichard Henderson    writing to R0, re-instate the architectural register.  */
1696597c28dSRichard Henderson #define check_r0_write(reg)             \
1706597c28dSRichard Henderson     do {                                \
1716597c28dSRichard Henderson         if (unlikely(reg == 0)) {       \
1726597c28dSRichard Henderson             cpu_R[0] = cpu_R0;          \
1736597c28dSRichard Henderson         }                               \
1746597c28dSRichard Henderson     } while (0)
1756597c28dSRichard Henderson 
17697458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1779ecaa27eSRichard Henderson {
1780c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
17997458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
1809ecaa27eSRichard Henderson     }
1810c53d734SRichard Henderson }
1829ecaa27eSRichard Henderson 
18397458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1849ecaa27eSRichard Henderson {
1850c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
18697458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
1879ecaa27eSRichard Henderson     }
1880c53d734SRichard Henderson }
1899ecaa27eSRichard Henderson 
19097458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1919ecaa27eSRichard Henderson {
1920c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
19397458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
1949ecaa27eSRichard Henderson     }
1950c53d734SRichard Henderson }
1969ecaa27eSRichard Henderson 
1979ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
1989ecaa27eSRichard Henderson {
1999ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2009ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2019ecaa27eSRichard Henderson 
20297458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
20397458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2049ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
20597458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2069ecaa27eSRichard Henderson     tcg_temp_free(t0);
2079ecaa27eSRichard Henderson 
2089ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2099ecaa27eSRichard Henderson     tcg_temp_free(res);
2109ecaa27eSRichard Henderson 
21197458071SRichard Henderson     gen_ove_cyov(dc);
2129ecaa27eSRichard Henderson }
2139ecaa27eSRichard Henderson 
2149ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2159ecaa27eSRichard Henderson {
2169ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2179ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2189ecaa27eSRichard Henderson 
21997458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
22097458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
22197458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2229ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22397458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2249ecaa27eSRichard Henderson     tcg_temp_free(t0);
2259ecaa27eSRichard Henderson 
2269ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2279ecaa27eSRichard Henderson     tcg_temp_free(res);
2289ecaa27eSRichard Henderson 
22997458071SRichard Henderson     gen_ove_cyov(dc);
2309ecaa27eSRichard Henderson }
2319ecaa27eSRichard Henderson 
2329ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2339ecaa27eSRichard Henderson {
2349ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2359ecaa27eSRichard Henderson 
2369ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
23797458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
23897458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
23997458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
24097458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2419ecaa27eSRichard Henderson 
2429ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2439ecaa27eSRichard Henderson     tcg_temp_free(res);
2449ecaa27eSRichard Henderson 
24597458071SRichard Henderson     gen_ove_cyov(dc);
2469ecaa27eSRichard Henderson }
2479ecaa27eSRichard Henderson 
2489ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2499ecaa27eSRichard Henderson {
2509ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2519ecaa27eSRichard Henderson 
25297458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2539ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
25497458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2559ecaa27eSRichard Henderson     tcg_temp_free(t0);
2569ecaa27eSRichard Henderson 
25797458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
25897458071SRichard Henderson     gen_ove_ov(dc);
2599ecaa27eSRichard Henderson }
2609ecaa27eSRichard Henderson 
2619ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2629ecaa27eSRichard Henderson {
26397458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
26497458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2659ecaa27eSRichard Henderson 
26697458071SRichard Henderson     gen_ove_cy(dc);
2679ecaa27eSRichard Henderson }
2689ecaa27eSRichard Henderson 
2699ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2709ecaa27eSRichard Henderson {
2719ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2729ecaa27eSRichard Henderson 
27397458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2749ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2759ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
27697458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2779ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2789ecaa27eSRichard Henderson     tcg_temp_free(t0);
2799ecaa27eSRichard Henderson 
28097458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
28197458071SRichard Henderson     gen_ove_ov(dc);
2829ecaa27eSRichard Henderson }
2839ecaa27eSRichard Henderson 
2849ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2859ecaa27eSRichard Henderson {
2869ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2879ecaa27eSRichard Henderson 
28897458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2899ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2909ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
29197458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2929ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2939ecaa27eSRichard Henderson     tcg_temp_free(t0);
2949ecaa27eSRichard Henderson 
29597458071SRichard Henderson     gen_ove_cy(dc);
2969ecaa27eSRichard Henderson }
297da1d7759SSebastian Macke 
298cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
299cc5de49eSRichard Henderson {
300cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
301cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
302cc5de49eSRichard Henderson 
303cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
304cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
305cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
306cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
307cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
308cc5de49eSRichard Henderson     } else {
309cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
310cc5de49eSRichard Henderson 
311cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
312cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
313cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
314cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
315cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
316cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
317cc5de49eSRichard Henderson 
318cc5de49eSRichard Henderson         gen_ove_ov(dc);
319cc5de49eSRichard Henderson     }
320cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
321cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
322cc5de49eSRichard Henderson }
323cc5de49eSRichard Henderson 
324cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
325cc5de49eSRichard Henderson {
326cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
327cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
328cc5de49eSRichard Henderson 
329cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
330cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
331cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
332cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
333cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
334cc5de49eSRichard Henderson     } else {
335cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
336cc5de49eSRichard Henderson 
337cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
338cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
339cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
340cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
341cc5de49eSRichard Henderson 
342cc5de49eSRichard Henderson         gen_ove_cy(dc);
343cc5de49eSRichard Henderson     }
344cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
345cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
346cc5de49eSRichard Henderson }
347cc5de49eSRichard Henderson 
3486f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3496f7332baSRichard Henderson {
3506f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3516f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3526f7332baSRichard Henderson 
3536f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3546f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3556f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3566f7332baSRichard Henderson 
3576f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3586f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3596f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3606f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3616f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3626f7332baSRichard Henderson     tcg_temp_free_i64(t2);
3636f7332baSRichard Henderson 
3646f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3656f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3666f7332baSRichard Henderson #else
3676f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3686f7332baSRichard Henderson #endif
3696f7332baSRichard Henderson     tcg_temp_free_i64(t1);
3706f7332baSRichard Henderson 
3716f7332baSRichard Henderson     gen_ove_ov(dc);
3726f7332baSRichard Henderson }
3736f7332baSRichard Henderson 
374cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
375cc5de49eSRichard Henderson {
376cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
377cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
378cc5de49eSRichard Henderson 
379cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
380cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
381cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
382cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
383cc5de49eSRichard Henderson 
384cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
385cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
386cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
387cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
388cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
389cc5de49eSRichard Henderson 
390cc5de49eSRichard Henderson     gen_ove_cy(dc);
391cc5de49eSRichard Henderson }
392cc5de49eSRichard Henderson 
3936f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
3946f7332baSRichard Henderson {
3956f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3966f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3976f7332baSRichard Henderson 
3986f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3996f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4006f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4016f7332baSRichard Henderson 
4026f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4036f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4046f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4056f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4066f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4076f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4086f7332baSRichard Henderson 
4096f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4106f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4116f7332baSRichard Henderson #else
4126f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4136f7332baSRichard Henderson #endif
4146f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4156f7332baSRichard Henderson 
4166f7332baSRichard Henderson     gen_ove_ov(dc);
4176f7332baSRichard Henderson }
4186f7332baSRichard Henderson 
419cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
420cc5de49eSRichard Henderson {
421cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
422cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
423cc5de49eSRichard Henderson 
424cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
425cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
426cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
427cc5de49eSRichard Henderson 
428cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
429cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
430cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
431cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
432cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
433cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
434cc5de49eSRichard Henderson 
435cc5de49eSRichard Henderson     gen_ove_cy(dc);
436cc5de49eSRichard Henderson }
437cc5de49eSRichard Henderson 
4383a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
439bbe418f2SJia Liu {
4406ad216abSRichard Henderson     check_r0_write(a->d);
4416ad216abSRichard Henderson     gen_add(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4426ad216abSRichard Henderson     return true;
443bbe418f2SJia Liu }
444bbe418f2SJia Liu 
4453a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
446bbe418f2SJia Liu {
4476ad216abSRichard Henderson     check_r0_write(a->d);
4486ad216abSRichard Henderson     gen_addc(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4496ad216abSRichard Henderson     return true;
4506ad216abSRichard Henderson }
4516ad216abSRichard Henderson 
4523a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4536ad216abSRichard Henderson {
4546ad216abSRichard Henderson     check_r0_write(a->d);
4556ad216abSRichard Henderson     gen_sub(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4566ad216abSRichard Henderson     return true;
4576ad216abSRichard Henderson }
4586ad216abSRichard Henderson 
4593a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4606ad216abSRichard Henderson {
4616ad216abSRichard Henderson     check_r0_write(a->d);
4626ad216abSRichard Henderson     tcg_gen_and_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4636ad216abSRichard Henderson     return true;
4646ad216abSRichard Henderson }
4656ad216abSRichard Henderson 
4663a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4676ad216abSRichard Henderson {
4686ad216abSRichard Henderson     check_r0_write(a->d);
4696ad216abSRichard Henderson     tcg_gen_or_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4706ad216abSRichard Henderson     return true;
4716ad216abSRichard Henderson }
4726ad216abSRichard Henderson 
4733a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4746ad216abSRichard Henderson {
4756ad216abSRichard Henderson     check_r0_write(a->d);
4766ad216abSRichard Henderson     tcg_gen_xor_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4776ad216abSRichard Henderson     return true;
4786ad216abSRichard Henderson }
4796ad216abSRichard Henderson 
4803a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4816ad216abSRichard Henderson {
4826ad216abSRichard Henderson     check_r0_write(a->d);
4836ad216abSRichard Henderson     tcg_gen_shl_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4846ad216abSRichard Henderson     return true;
4856ad216abSRichard Henderson }
4866ad216abSRichard Henderson 
4873a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4886ad216abSRichard Henderson {
4896ad216abSRichard Henderson     check_r0_write(a->d);
4906ad216abSRichard Henderson     tcg_gen_shr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4916ad216abSRichard Henderson     return true;
4926ad216abSRichard Henderson }
4936ad216abSRichard Henderson 
4943a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
4956ad216abSRichard Henderson {
4966ad216abSRichard Henderson     check_r0_write(a->d);
4976ad216abSRichard Henderson     tcg_gen_sar_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
4986ad216abSRichard Henderson     return true;
4996ad216abSRichard Henderson }
5006ad216abSRichard Henderson 
5013a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
5026ad216abSRichard Henderson {
5036ad216abSRichard Henderson     check_r0_write(a->d);
5046ad216abSRichard Henderson     tcg_gen_rotr_tl(cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
5056ad216abSRichard Henderson     return true;
5066ad216abSRichard Henderson }
5076ad216abSRichard Henderson 
5083a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
5096ad216abSRichard Henderson {
5106ad216abSRichard Henderson     check_r0_write(a->d);
5116ad216abSRichard Henderson     tcg_gen_ext16s_tl(cpu_R[a->d], cpu_R[a->a]);
5126ad216abSRichard Henderson     return true;
5136ad216abSRichard Henderson }
5146ad216abSRichard Henderson 
5153a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
5166ad216abSRichard Henderson {
5176ad216abSRichard Henderson     check_r0_write(a->d);
5186ad216abSRichard Henderson     tcg_gen_ext8s_tl(cpu_R[a->d], cpu_R[a->a]);
5196ad216abSRichard Henderson     return true;
5206ad216abSRichard Henderson }
5216ad216abSRichard Henderson 
5223a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5236ad216abSRichard Henderson {
5246ad216abSRichard Henderson     check_r0_write(a->d);
5256ad216abSRichard Henderson     tcg_gen_ext16u_tl(cpu_R[a->d], cpu_R[a->a]);
5266ad216abSRichard Henderson     return true;
5276ad216abSRichard Henderson }
5286ad216abSRichard Henderson 
5293a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5306ad216abSRichard Henderson {
5316ad216abSRichard Henderson     check_r0_write(a->d);
5326ad216abSRichard Henderson     tcg_gen_ext8u_tl(cpu_R[a->d], cpu_R[a->a]);
5336ad216abSRichard Henderson     return true;
5346ad216abSRichard Henderson }
5356ad216abSRichard Henderson 
5363a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5376ad216abSRichard Henderson {
5386ad216abSRichard Henderson     TCGv zero;
5396ad216abSRichard Henderson 
5406ad216abSRichard Henderson     check_r0_write(a->d);
5416ad216abSRichard Henderson     zero = tcg_const_tl(0);
5426ad216abSRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[a->d], cpu_sr_f, zero,
5436ad216abSRichard Henderson                        cpu_R[a->a], cpu_R[a->b]);
544784696d1SRichard Henderson     tcg_temp_free(zero);
5456ad216abSRichard Henderson     return true;
546bbe418f2SJia Liu }
547bbe418f2SJia Liu 
5483a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5496ad216abSRichard Henderson {
5506ad216abSRichard Henderson     check_r0_write(a->d);
5516ad216abSRichard Henderson     tcg_gen_ctzi_tl(cpu_R[a->d], cpu_R[a->a], -1);
5526ad216abSRichard Henderson     tcg_gen_addi_tl(cpu_R[a->d], cpu_R[a->d], 1);
5536ad216abSRichard Henderson     return true;
554cf2ae442SRichard Henderson }
555cf2ae442SRichard Henderson 
5563a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5576ad216abSRichard Henderson {
5586ad216abSRichard Henderson     check_r0_write(a->d);
5596ad216abSRichard Henderson     tcg_gen_clzi_tl(cpu_R[a->d], cpu_R[a->a], TARGET_LONG_BITS);
5606ad216abSRichard Henderson     tcg_gen_subfi_tl(cpu_R[a->d], TARGET_LONG_BITS, cpu_R[a->d]);
5616ad216abSRichard Henderson     return true;
562bbe418f2SJia Liu }
563bbe418f2SJia Liu 
5643a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5656ad216abSRichard Henderson {
5666ad216abSRichard Henderson     check_r0_write(a->d);
5676ad216abSRichard Henderson     gen_mul(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
5686ad216abSRichard Henderson     return true;
569bbe418f2SJia Liu }
5706ad216abSRichard Henderson 
5713a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5726ad216abSRichard Henderson {
5736ad216abSRichard Henderson     check_r0_write(a->d);
5746ad216abSRichard Henderson     gen_mulu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
5756ad216abSRichard Henderson     return true;
576bbe418f2SJia Liu }
5776ad216abSRichard Henderson 
5783a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5796ad216abSRichard Henderson {
5806ad216abSRichard Henderson     check_r0_write(a->d);
5816ad216abSRichard Henderson     gen_div(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
5826ad216abSRichard Henderson     return true;
5836ad216abSRichard Henderson }
5846ad216abSRichard Henderson 
5853a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5866ad216abSRichard Henderson {
5876ad216abSRichard Henderson     check_r0_write(a->d);
5886ad216abSRichard Henderson     gen_divu(dc, cpu_R[a->d], cpu_R[a->a], cpu_R[a->b]);
5896ad216abSRichard Henderson     return true;
5906ad216abSRichard Henderson }
5916ad216abSRichard Henderson 
5923a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5936ad216abSRichard Henderson {
5946ad216abSRichard Henderson     gen_muld(dc, cpu_R[a->a], cpu_R[a->b]);
5956ad216abSRichard Henderson     return true;
5966ad216abSRichard Henderson }
5976ad216abSRichard Henderson 
5983a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
5996ad216abSRichard Henderson {
6006ad216abSRichard Henderson     gen_muldu(dc, cpu_R[a->a], cpu_R[a->b]);
6016ad216abSRichard Henderson     return true;
602bbe418f2SJia Liu }
603bbe418f2SJia Liu 
6043a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
605136e13aeSRichard Henderson {
606136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
607136e13aeSRichard Henderson 
608136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
6098000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
610136e13aeSRichard Henderson     dc->delayed_branch = 2;
611136e13aeSRichard Henderson     return true;
612136e13aeSRichard Henderson }
613136e13aeSRichard Henderson 
6143a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
615136e13aeSRichard Henderson {
616136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
617136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
618136e13aeSRichard Henderson 
619136e13aeSRichard Henderson     tcg_gen_movi_tl(cpu_R[9], ret_pc);
620136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
621136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
622136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6238000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
624136e13aeSRichard Henderson         dc->delayed_branch = 2;
625136e13aeSRichard Henderson     }
626136e13aeSRichard Henderson     return true;
627136e13aeSRichard Henderson }
628136e13aeSRichard Henderson 
629136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
630136e13aeSRichard Henderson {
631136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
632136e13aeSRichard Henderson     TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
633136e13aeSRichard Henderson     TCGv t_true = tcg_const_tl(tmp_pc);
634136e13aeSRichard Henderson     TCGv t_zero = tcg_const_tl(0);
635136e13aeSRichard Henderson 
636136e13aeSRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
637136e13aeSRichard Henderson 
638136e13aeSRichard Henderson     tcg_temp_free(t_next);
639136e13aeSRichard Henderson     tcg_temp_free(t_true);
640136e13aeSRichard Henderson     tcg_temp_free(t_zero);
641136e13aeSRichard Henderson     dc->delayed_branch = 2;
642136e13aeSRichard Henderson }
643136e13aeSRichard Henderson 
6443a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
645136e13aeSRichard Henderson {
646136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
647136e13aeSRichard Henderson     return true;
648136e13aeSRichard Henderson }
649136e13aeSRichard Henderson 
6503a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
651136e13aeSRichard Henderson {
652136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
653136e13aeSRichard Henderson     return true;
654136e13aeSRichard Henderson }
655136e13aeSRichard Henderson 
6563a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
657136e13aeSRichard Henderson {
658136e13aeSRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
659136e13aeSRichard Henderson     dc->delayed_branch = 2;
660136e13aeSRichard Henderson     return true;
661136e13aeSRichard Henderson }
662136e13aeSRichard Henderson 
6633a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
664136e13aeSRichard Henderson {
665136e13aeSRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R[a->b]);
666136e13aeSRichard Henderson     tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8);
667136e13aeSRichard Henderson     dc->delayed_branch = 2;
668136e13aeSRichard Henderson     return true;
669136e13aeSRichard Henderson }
670136e13aeSRichard Henderson 
6713a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
672d80bff19SRichard Henderson {
673d80bff19SRichard Henderson     TCGv ea;
674d80bff19SRichard Henderson 
675d80bff19SRichard Henderson     check_r0_write(a->d);
676d80bff19SRichard Henderson     ea = tcg_temp_new();
677d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
678d80bff19SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL);
679d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
680d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]);
681d80bff19SRichard Henderson     tcg_temp_free(ea);
682d80bff19SRichard Henderson     return true;
683d80bff19SRichard Henderson }
684d80bff19SRichard Henderson 
685d80bff19SRichard Henderson static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop)
686d80bff19SRichard Henderson {
687d80bff19SRichard Henderson     TCGv ea;
688d80bff19SRichard Henderson 
689d80bff19SRichard Henderson     check_r0_write(a->d);
690d80bff19SRichard Henderson     ea = tcg_temp_new();
691d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
692d80bff19SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop);
693d80bff19SRichard Henderson     tcg_temp_free(ea);
694d80bff19SRichard Henderson }
695d80bff19SRichard Henderson 
6963a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
697d80bff19SRichard Henderson {
698d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
699d80bff19SRichard Henderson     return true;
700d80bff19SRichard Henderson }
701d80bff19SRichard Henderson 
7023a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
703d80bff19SRichard Henderson {
704d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
705d80bff19SRichard Henderson     return true;
706d80bff19SRichard Henderson }
707d80bff19SRichard Henderson 
7083a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
709d80bff19SRichard Henderson {
710d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
711d80bff19SRichard Henderson     return true;
712d80bff19SRichard Henderson }
713d80bff19SRichard Henderson 
7143a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
715d80bff19SRichard Henderson {
716d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
717d80bff19SRichard Henderson     return true;
718d80bff19SRichard Henderson }
719d80bff19SRichard Henderson 
7203a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
721d80bff19SRichard Henderson {
722d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
723d80bff19SRichard Henderson     return true;
724d80bff19SRichard Henderson }
725d80bff19SRichard Henderson 
7263a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
727d80bff19SRichard Henderson {
728d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
729d80bff19SRichard Henderson     return true;
730d80bff19SRichard Henderson }
731d80bff19SRichard Henderson 
7323a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
733d80bff19SRichard Henderson {
734d80bff19SRichard Henderson     TCGv ea, val;
735d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
736d80bff19SRichard Henderson 
737d80bff19SRichard Henderson     ea = tcg_temp_new();
738d80bff19SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
739d80bff19SRichard Henderson 
740d80bff19SRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
741d80bff19SRichard Henderson        to cpu_R[0].  Since l.swa is quite often immediately followed by a
742d80bff19SRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
743d80bff19SRichard Henderson        This also takes care of RB input across the branch.  */
744d80bff19SRichard Henderson     cpu_R[0] = cpu_R0;
745d80bff19SRichard Henderson 
746d80bff19SRichard Henderson     lab_fail = gen_new_label();
747d80bff19SRichard Henderson     lab_done = gen_new_label();
748d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
749d80bff19SRichard Henderson     tcg_temp_free(ea);
750d80bff19SRichard Henderson 
751d80bff19SRichard Henderson     val = tcg_temp_new();
752d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
753d80bff19SRichard Henderson                               cpu_R[a->b], dc->mem_idx, MO_TEUL);
754d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
755d80bff19SRichard Henderson     tcg_temp_free(val);
756d80bff19SRichard Henderson 
757d80bff19SRichard Henderson     tcg_gen_br(lab_done);
758d80bff19SRichard Henderson 
759d80bff19SRichard Henderson     gen_set_label(lab_fail);
760d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
761d80bff19SRichard Henderson 
762d80bff19SRichard Henderson     gen_set_label(lab_done);
763d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
764d80bff19SRichard Henderson     return true;
765d80bff19SRichard Henderson }
766d80bff19SRichard Henderson 
767d80bff19SRichard Henderson static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop)
768d80bff19SRichard Henderson {
769d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
770d80bff19SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R[a->a], a->i);
771d80bff19SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop);
772d80bff19SRichard Henderson     tcg_temp_free(t0);
773d80bff19SRichard Henderson }
774d80bff19SRichard Henderson 
7753a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
776d80bff19SRichard Henderson {
777d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
778d80bff19SRichard Henderson     return true;
779d80bff19SRichard Henderson }
780d80bff19SRichard Henderson 
7813a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
782d80bff19SRichard Henderson {
783d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
784d80bff19SRichard Henderson     return true;
785d80bff19SRichard Henderson }
786d80bff19SRichard Henderson 
7873a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
788d80bff19SRichard Henderson {
789d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
790d80bff19SRichard Henderson     return true;
791d80bff19SRichard Henderson }
792d80bff19SRichard Henderson 
7933a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
794bbe418f2SJia Liu {
7958816f70bSRichard Henderson     return true;
7968816f70bSRichard Henderson }
7978816f70bSRichard Henderson 
7983a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
7998816f70bSRichard Henderson {
8009ecaa27eSRichard Henderson     TCGv t0;
8015631e69cSRichard Henderson 
8028816f70bSRichard Henderson     check_r0_write(a->d);
8038816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8048816f70bSRichard Henderson     gen_add(dc, cpu_R[a->d], cpu_R[a->a], t0);
8056f7332baSRichard Henderson     tcg_temp_free(t0);
8068816f70bSRichard Henderson     return true;
8078816f70bSRichard Henderson }
808bbe418f2SJia Liu 
8093a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
810bbe418f2SJia Liu {
8118816f70bSRichard Henderson     TCGv t0;
8128816f70bSRichard Henderson 
8138816f70bSRichard Henderson     check_r0_write(a->d);
8148816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8158816f70bSRichard Henderson     gen_addc(dc, cpu_R[a->d], cpu_R[a->a], t0);
8168816f70bSRichard Henderson     tcg_temp_free(t0);
8178816f70bSRichard Henderson     return true;
8188816f70bSRichard Henderson }
8198816f70bSRichard Henderson 
8203a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
8218816f70bSRichard Henderson {
8228816f70bSRichard Henderson     TCGv t0;
8238816f70bSRichard Henderson 
8248816f70bSRichard Henderson     check_r0_write(a->d);
8258816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8268816f70bSRichard Henderson     gen_mul(dc, cpu_R[a->d], cpu_R[a->a], t0);
8278816f70bSRichard Henderson     tcg_temp_free(t0);
8288816f70bSRichard Henderson     return true;
8298816f70bSRichard Henderson }
8308816f70bSRichard Henderson 
8313a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
8328816f70bSRichard Henderson {
8338816f70bSRichard Henderson     TCGv t0;
8348816f70bSRichard Henderson 
8358816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8368816f70bSRichard Henderson     gen_mac(dc, cpu_R[a->a], t0);
8378816f70bSRichard Henderson     tcg_temp_free(t0);
8388816f70bSRichard Henderson     return true;
8398816f70bSRichard Henderson }
8408816f70bSRichard Henderson 
8413a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8428816f70bSRichard Henderson {
8438816f70bSRichard Henderson     check_r0_write(a->d);
8448816f70bSRichard Henderson     tcg_gen_andi_tl(cpu_R[a->d], cpu_R[a->a], a->k);
8458816f70bSRichard Henderson     return true;
8468816f70bSRichard Henderson }
8478816f70bSRichard Henderson 
8483a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8498816f70bSRichard Henderson {
8508816f70bSRichard Henderson     check_r0_write(a->d);
8518816f70bSRichard Henderson     tcg_gen_ori_tl(cpu_R[a->d], cpu_R[a->a], a->k);
8528816f70bSRichard Henderson     return true;
8538816f70bSRichard Henderson }
8548816f70bSRichard Henderson 
8553a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8568816f70bSRichard Henderson {
8578816f70bSRichard Henderson     check_r0_write(a->d);
8588816f70bSRichard Henderson     tcg_gen_xori_tl(cpu_R[a->d], cpu_R[a->a], a->i);
8598816f70bSRichard Henderson     return true;
8608816f70bSRichard Henderson }
8618816f70bSRichard Henderson 
8623a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8638816f70bSRichard Henderson {
8648816f70bSRichard Henderson     check_r0_write(a->d);
8658816f70bSRichard Henderson 
8662ba65417SRichard Henderson     if (is_user(dc)) {
867bbe418f2SJia Liu         gen_illegal_exception(dc);
8688816f70bSRichard Henderson     } else {
869c28fa81fSRichard Henderson         TCGv spr = tcg_temp_new();
870c28fa81fSRichard Henderson         tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
871c28fa81fSRichard Henderson         gen_helper_mfspr(cpu_R[a->d], cpu_env, cpu_R[a->d], spr);
872c28fa81fSRichard Henderson         tcg_temp_free(spr);
8734dd044c6SJia Liu     }
8748816f70bSRichard Henderson     return true;
8758816f70bSRichard Henderson }
876bbe418f2SJia Liu 
8773a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
8784dd044c6SJia Liu {
8792ba65417SRichard Henderson     if (is_user(dc)) {
8804dd044c6SJia Liu         gen_illegal_exception(dc);
8818816f70bSRichard Henderson     } else {
882c28fa81fSRichard Henderson         TCGv spr;
88301ec3ec9SRichard Henderson 
88401ec3ec9SRichard Henderson         /* For SR, we will need to exit the TB to recognize the new
88501ec3ec9SRichard Henderson          * exception state.  For NPC, in theory this counts as a branch
88601ec3ec9SRichard Henderson          * (although the SPR only exists for use by an ICE).  Save all
88701ec3ec9SRichard Henderson          * of the cpu state first, allowing it to be overwritten.
88801ec3ec9SRichard Henderson          */
88901ec3ec9SRichard Henderson         if (dc->delayed_branch) {
89001ec3ec9SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
89101ec3ec9SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
89201ec3ec9SRichard Henderson         } else {
89301ec3ec9SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
89401ec3ec9SRichard Henderson         }
89501ec3ec9SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
89601ec3ec9SRichard Henderson 
897c28fa81fSRichard Henderson         spr = tcg_temp_new();
898c28fa81fSRichard Henderson         tcg_gen_ori_tl(spr, cpu_R[a->a], a->k);
899c28fa81fSRichard Henderson         gen_helper_mtspr(cpu_env, spr, cpu_R[a->b]);
900c28fa81fSRichard Henderson         tcg_temp_free(spr);
9014dd044c6SJia Liu     }
9028816f70bSRichard Henderson     return true;
903bbe418f2SJia Liu }
904bbe418f2SJia Liu 
9053a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
906bbe418f2SJia Liu {
90799d863d6SRichard Henderson     gen_mac(dc, cpu_R[a->a], cpu_R[a->b]);
90899d863d6SRichard Henderson     return true;
909bbe418f2SJia Liu }
91099d863d6SRichard Henderson 
9113a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
91299d863d6SRichard Henderson {
91399d863d6SRichard Henderson     gen_msb(dc, cpu_R[a->a], cpu_R[a->b]);
91499d863d6SRichard Henderson     return true;
91599d863d6SRichard Henderson }
91699d863d6SRichard Henderson 
9173a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
91899d863d6SRichard Henderson {
91999d863d6SRichard Henderson     gen_macu(dc, cpu_R[a->a], cpu_R[a->b]);
92099d863d6SRichard Henderson     return true;
92199d863d6SRichard Henderson }
92299d863d6SRichard Henderson 
9233a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
92499d863d6SRichard Henderson {
92599d863d6SRichard Henderson     gen_msbu(dc, cpu_R[a->a], cpu_R[a->b]);
92699d863d6SRichard Henderson     return true;
927bbe418f2SJia Liu }
928bbe418f2SJia Liu 
9293a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
930bbe418f2SJia Liu {
931e20c2592SRichard Henderson     check_r0_write(a->d);
932e20c2592SRichard Henderson     tcg_gen_shli_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
933e20c2592SRichard Henderson     return true;
934bbe418f2SJia Liu }
935e20c2592SRichard Henderson 
9363a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
937e20c2592SRichard Henderson {
938e20c2592SRichard Henderson     check_r0_write(a->d);
939e20c2592SRichard Henderson     tcg_gen_shri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
940e20c2592SRichard Henderson     return true;
941e20c2592SRichard Henderson }
942e20c2592SRichard Henderson 
9433a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
944e20c2592SRichard Henderson {
945e20c2592SRichard Henderson     check_r0_write(a->d);
946e20c2592SRichard Henderson     tcg_gen_sari_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
947e20c2592SRichard Henderson     return true;
948e20c2592SRichard Henderson }
949e20c2592SRichard Henderson 
9503a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
951e20c2592SRichard Henderson {
952e20c2592SRichard Henderson     check_r0_write(a->d);
953e20c2592SRichard Henderson     tcg_gen_rotri_tl(cpu_R[a->d], cpu_R[a->a], a->l & (TARGET_LONG_BITS - 1));
954e20c2592SRichard Henderson     return true;
955bbe418f2SJia Liu }
956bbe418f2SJia Liu 
9573a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
958bbe418f2SJia Liu {
959e720a571SRichard Henderson     check_r0_write(a->d);
960e720a571SRichard Henderson     tcg_gen_movi_tl(cpu_R[a->d], a->k << 16);
961e720a571SRichard Henderson     return true;
962bbe418f2SJia Liu }
963e720a571SRichard Henderson 
9643a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
965e720a571SRichard Henderson {
966e720a571SRichard Henderson     check_r0_write(a->d);
967e720a571SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R[a->d], cpu_mac);
968e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
969e720a571SRichard Henderson     return true;
970bbe418f2SJia Liu }
971bbe418f2SJia Liu 
9723a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
973bbe418f2SJia Liu {
974fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
975fbb3e29aSRichard Henderson     return true;
976bbe418f2SJia Liu }
977fbb3e29aSRichard Henderson 
9783a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
979fbb3e29aSRichard Henderson {
980fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
981fbb3e29aSRichard Henderson     return true;
982fbb3e29aSRichard Henderson }
983fbb3e29aSRichard Henderson 
9843a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
985fbb3e29aSRichard Henderson {
986fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
987fbb3e29aSRichard Henderson     return true;
988fbb3e29aSRichard Henderson }
989fbb3e29aSRichard Henderson 
9903a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
991fbb3e29aSRichard Henderson {
992fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
993fbb3e29aSRichard Henderson     return true;
994fbb3e29aSRichard Henderson }
995fbb3e29aSRichard Henderson 
9963a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
997fbb3e29aSRichard Henderson {
998fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
999fbb3e29aSRichard Henderson     return true;
1000fbb3e29aSRichard Henderson }
1001fbb3e29aSRichard Henderson 
10023a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
1003fbb3e29aSRichard Henderson {
1004fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1005fbb3e29aSRichard Henderson     return true;
1006fbb3e29aSRichard Henderson }
1007fbb3e29aSRichard Henderson 
10083a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
1009fbb3e29aSRichard Henderson {
1010fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1011fbb3e29aSRichard Henderson     return true;
1012fbb3e29aSRichard Henderson }
1013fbb3e29aSRichard Henderson 
10143a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
1015fbb3e29aSRichard Henderson {
1016fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1017fbb3e29aSRichard Henderson     return true;
1018fbb3e29aSRichard Henderson }
1019fbb3e29aSRichard Henderson 
10203a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
1021fbb3e29aSRichard Henderson {
1022fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1023fbb3e29aSRichard Henderson     return true;
1024fbb3e29aSRichard Henderson }
1025fbb3e29aSRichard Henderson 
10263a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1027fbb3e29aSRichard Henderson {
1028fbb3e29aSRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], cpu_R[a->b]);
1029fbb3e29aSRichard Henderson     return true;
1030bbe418f2SJia Liu }
1031bbe418f2SJia Liu 
10323a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1033bbe418f2SJia Liu {
1034032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[a->a], a->i);
1035032de4fcSRichard Henderson     return true;
1036bbe418f2SJia Liu }
1037032de4fcSRichard Henderson 
10383a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1039032de4fcSRichard Henderson {
1040032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[a->a], a->i);
1041032de4fcSRichard Henderson     return true;
1042032de4fcSRichard Henderson }
1043032de4fcSRichard Henderson 
10443a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1045032de4fcSRichard Henderson {
1046032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[a->a], a->i);
1047032de4fcSRichard Henderson     return true;
1048032de4fcSRichard Henderson }
1049032de4fcSRichard Henderson 
10503a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1051032de4fcSRichard Henderson {
1052032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[a->a], a->i);
1053032de4fcSRichard Henderson     return true;
1054032de4fcSRichard Henderson }
1055032de4fcSRichard Henderson 
10563a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1057032de4fcSRichard Henderson {
1058032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[a->a], a->i);
1059032de4fcSRichard Henderson     return true;
1060032de4fcSRichard Henderson }
1061032de4fcSRichard Henderson 
10623a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1063032de4fcSRichard Henderson {
1064032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[a->a], a->i);
1065032de4fcSRichard Henderson     return true;
1066032de4fcSRichard Henderson }
1067032de4fcSRichard Henderson 
10683a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1069032de4fcSRichard Henderson {
1070032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[a->a], a->i);
1071032de4fcSRichard Henderson     return true;
1072032de4fcSRichard Henderson }
1073032de4fcSRichard Henderson 
10743a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1075032de4fcSRichard Henderson {
1076032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[a->a], a->i);
1077032de4fcSRichard Henderson     return true;
1078032de4fcSRichard Henderson }
1079032de4fcSRichard Henderson 
10803a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1081032de4fcSRichard Henderson {
1082032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[a->a], a->i);
1083032de4fcSRichard Henderson     return true;
1084032de4fcSRichard Henderson }
1085032de4fcSRichard Henderson 
10863a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1087032de4fcSRichard Henderson {
1088032de4fcSRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[a->a], a->i);
1089032de4fcSRichard Henderson     return true;
1090bbe418f2SJia Liu }
1091bbe418f2SJia Liu 
10923a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1093bbe418f2SJia Liu {
10941ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1095bbe418f2SJia Liu     gen_exception(dc, EXCP_SYSCALL);
10961ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
10977de9729fSRichard Henderson     return true;
10987de9729fSRichard Henderson }
1099bbe418f2SJia Liu 
11003a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
11017de9729fSRichard Henderson {
11021ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1103bbe418f2SJia Liu     gen_exception(dc, EXCP_TRAP);
11041ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11057de9729fSRichard Henderson     return true;
11067de9729fSRichard Henderson }
1107bbe418f2SJia Liu 
11083a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
11097de9729fSRichard Henderson {
111024fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
11117de9729fSRichard Henderson     return true;
1112bbe418f2SJia Liu }
11137de9729fSRichard Henderson 
11143a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
11157de9729fSRichard Henderson {
11167de9729fSRichard Henderson     return true;
11177de9729fSRichard Henderson }
11187de9729fSRichard Henderson 
11193a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
11207de9729fSRichard Henderson {
11217de9729fSRichard Henderson     return true;
1122bbe418f2SJia Liu }
1123bbe418f2SJia Liu 
11243a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11258816f70bSRichard Henderson {
11262ba65417SRichard Henderson     if (is_user(dc)) {
11278816f70bSRichard Henderson         gen_illegal_exception(dc);
11288816f70bSRichard Henderson     } else {
11298816f70bSRichard Henderson         gen_helper_rfe(cpu_env);
113064e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11318816f70bSRichard Henderson     }
11328816f70bSRichard Henderson     return true;
11338816f70bSRichard Henderson }
11348816f70bSRichard Henderson 
11356fd204a2SRichard Henderson static void do_fp2(DisasContext *dc, arg_da *a,
11366fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1137bbe418f2SJia Liu {
11386fd204a2SRichard Henderson     check_r0_write(a->d);
11396fd204a2SRichard Henderson     fn(cpu_R[a->d], cpu_env, cpu_R[a->a]);
11404e2d3007SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1141bbe418f2SJia Liu }
11426fd204a2SRichard Henderson 
11436fd204a2SRichard Henderson static void do_fp3(DisasContext *dc, arg_dab *a,
11446fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11456fd204a2SRichard Henderson {
11466fd204a2SRichard Henderson     check_r0_write(a->d);
11476fd204a2SRichard Henderson     fn(cpu_R[a->d], cpu_env, cpu_R[a->a], cpu_R[a->b]);
11486fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
11496fd204a2SRichard Henderson }
11506fd204a2SRichard Henderson 
11516fd204a2SRichard Henderson static void do_fpcmp(DisasContext *dc, arg_ab *a,
11526fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11536fd204a2SRichard Henderson                      bool inv, bool swap)
11546fd204a2SRichard Henderson {
11556fd204a2SRichard Henderson     if (swap) {
11566fd204a2SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R[a->b], cpu_R[a->a]);
11576fd204a2SRichard Henderson     } else {
11586fd204a2SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R[a->a], cpu_R[a->b]);
11596fd204a2SRichard Henderson     }
11606fd204a2SRichard Henderson     if (inv) {
11616fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11626fd204a2SRichard Henderson     }
11636fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
11646fd204a2SRichard Henderson }
11656fd204a2SRichard Henderson 
11663a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11676fd204a2SRichard Henderson {
11686fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_add_s);
11696fd204a2SRichard Henderson     return true;
11706fd204a2SRichard Henderson }
11716fd204a2SRichard Henderson 
11723a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11736fd204a2SRichard Henderson {
11746fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_sub_s);
11756fd204a2SRichard Henderson     return true;
11766fd204a2SRichard Henderson }
11776fd204a2SRichard Henderson 
11783a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
11796fd204a2SRichard Henderson {
11806fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_mul_s);
11816fd204a2SRichard Henderson     return true;
11826fd204a2SRichard Henderson }
11836fd204a2SRichard Henderson 
11843a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
11856fd204a2SRichard Henderson {
11866fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_div_s);
11876fd204a2SRichard Henderson     return true;
11886fd204a2SRichard Henderson }
11896fd204a2SRichard Henderson 
11903a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
11916fd204a2SRichard Henderson {
11926fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_rem_s);
11936fd204a2SRichard Henderson     return true;
11946fd204a2SRichard Henderson }
11956fd204a2SRichard Henderson 
11963a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
11976fd204a2SRichard Henderson {
11986fd204a2SRichard Henderson     do_fp2(dc, a, gen_helper_itofs);
11996fd204a2SRichard Henderson     return true;
12006fd204a2SRichard Henderson }
12016fd204a2SRichard Henderson 
12023a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
12036fd204a2SRichard Henderson {
12046fd204a2SRichard Henderson     do_fp2(dc, a, gen_helper_ftois);
12056fd204a2SRichard Henderson     return true;
12066fd204a2SRichard Henderson }
12076fd204a2SRichard Henderson 
12083a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
12096fd204a2SRichard Henderson {
12106fd204a2SRichard Henderson     check_r0_write(a->d);
12116fd204a2SRichard Henderson     gen_helper_float_madd_s(cpu_R[a->d], cpu_env, cpu_R[a->d],
12126fd204a2SRichard Henderson                             cpu_R[a->a], cpu_R[a->b]);
12136fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
12146fd204a2SRichard Henderson     return true;
12156fd204a2SRichard Henderson }
12166fd204a2SRichard Henderson 
12173a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12186fd204a2SRichard Henderson {
12196fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12206fd204a2SRichard Henderson     return true;
12216fd204a2SRichard Henderson }
12226fd204a2SRichard Henderson 
12233a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12246fd204a2SRichard Henderson {
12256fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12266fd204a2SRichard Henderson     return true;
12276fd204a2SRichard Henderson }
12286fd204a2SRichard Henderson 
12293a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12306fd204a2SRichard Henderson {
12316fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12326fd204a2SRichard Henderson     return true;
12336fd204a2SRichard Henderson }
12346fd204a2SRichard Henderson 
12353a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12366fd204a2SRichard Henderson {
12376fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12386fd204a2SRichard Henderson     return true;
12396fd204a2SRichard Henderson }
12406fd204a2SRichard Henderson 
12413a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12426fd204a2SRichard Henderson {
12436fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12446fd204a2SRichard Henderson     return true;
12456fd204a2SRichard Henderson }
12466fd204a2SRichard Henderson 
12473a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12486fd204a2SRichard Henderson {
12496fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
12506fd204a2SRichard Henderson     return true;
1251bbe418f2SJia Liu }
1252bbe418f2SJia Liu 
1253a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1254e67db06eSJia Liu {
1255a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
12569c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1257a4fd3ec3SEmilio G. Cota     int bound;
1258bbe418f2SJia Liu 
1259a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
12601ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1261a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
12628000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
12638000ba56SRichard Henderson 
1264a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1265a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1266190ce7fbSRichard Henderson }
1267bbe418f2SJia Liu 
1268a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1269a4fd3ec3SEmilio G. Cota {
1270a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1271bbe418f2SJia Liu 
12726597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
12736597c28dSRichard Henderson        when it's true, which is the common case.  */
12746597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
12756597c28dSRichard Henderson         cpu_R[0] = tcg_const_tl(0);
12766597c28dSRichard Henderson     } else {
12776597c28dSRichard Henderson         cpu_R[0] = cpu_R0;
12786597c28dSRichard Henderson     }
1279a4fd3ec3SEmilio G. Cota }
12806597c28dSRichard Henderson 
1281a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1282a4fd3ec3SEmilio G. Cota {
1283a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1284a4fd3ec3SEmilio G. Cota 
12851ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1286a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1287a4fd3ec3SEmilio G. Cota }
1288bbe418f2SJia Liu 
1289a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1290a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1291a4fd3ec3SEmilio G. Cota {
1292a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1293a4fd3ec3SEmilio G. Cota 
12941ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1295b933066aSRichard Henderson     gen_exception(dc, EXCP_DEBUG);
12961ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1297522a0d4eSRichard Henderson     /* The address covered by the breakpoint must be included in
1298522a0d4eSRichard Henderson        [tb->pc, tb->pc + tb->size) in order to for it to be
1299522a0d4eSRichard Henderson        properly cleared -- thus we increment the PC here so that
1300522a0d4eSRichard Henderson        the logic setting tb->size below does the right thing.  */
13011ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1302a4fd3ec3SEmilio G. Cota     return true;
1303b933066aSRichard Henderson }
1304b933066aSRichard Henderson 
1305a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1306a4fd3ec3SEmilio G. Cota {
1307a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1308a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1309c7b6f54bSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1310a4fd3ec3SEmilio G. Cota 
1311c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1312c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1313c7b6f54bSRichard Henderson     }
13141ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
131524c32852SRichard Henderson 
13168000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
13178000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
13188000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
13198000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
13208000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
13218000ba56SRichard Henderson      */
13228000ba56SRichard Henderson     if (dc->delayed_branch
13238000ba56SRichard Henderson         && --dc->delayed_branch == 0
13248000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
13258000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1326bbe418f2SJia Liu     }
1327a4fd3ec3SEmilio G. Cota }
1328bbe418f2SJia Liu 
1329a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1330a4fd3ec3SEmilio G. Cota {
1331a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
13328000ba56SRichard Henderson     target_ulong jmp_dest;
133324c32852SRichard Henderson 
1334e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1335e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1336e0a369cfSRichard Henderson         return;
1337e0a369cfSRichard Henderson     }
1338e0a369cfSRichard Henderson 
13398000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1340a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1341a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1342a01deb36SRichard Henderson     }
1343a01deb36SRichard Henderson 
13448000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
13458000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
13468000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
13478000ba56SRichard Henderson 
13481ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
13498000ba56SRichard Henderson     case DISAS_JUMP:
13508000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
13518000ba56SRichard Henderson         if (jmp_dest == -1) {
13528000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
13538000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
13548000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
13558000ba56SRichard Henderson             if (unlikely(dc->base.singlestep_enabled)) {
13568000ba56SRichard Henderson                 gen_exception(dc, EXCP_DEBUG);
13578000ba56SRichard Henderson             } else {
13588000ba56SRichard Henderson                 tcg_gen_lookup_and_goto_ptr();
13598000ba56SRichard Henderson             }
1360bbe418f2SJia Liu             break;
13618000ba56SRichard Henderson         }
13628000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
13638000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
13648000ba56SRichard Henderson            we know now that it wasn't needed.  */
13658000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
13668000ba56SRichard Henderson         /* fallthru */
13678000ba56SRichard Henderson 
13688000ba56SRichard Henderson     case DISAS_TOO_MANY:
13698000ba56SRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
13708000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13718000ba56SRichard Henderson             gen_exception(dc, EXCP_DEBUG);
13728000ba56SRichard Henderson         } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
13738000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13748000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
13758000ba56SRichard Henderson         } else {
13768000ba56SRichard Henderson             tcg_gen_goto_tb(0);
13778000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13788000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
13798000ba56SRichard Henderson         }
13808000ba56SRichard Henderson         break;
13818000ba56SRichard Henderson 
138264e46c95SRichard Henderson     case DISAS_EXIT:
1383e0a369cfSRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
1384e0a369cfSRichard Henderson             gen_exception(dc, EXCP_DEBUG);
1385e0a369cfSRichard Henderson         } else {
138607ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
1387e0a369cfSRichard Henderson         }
1388bbe418f2SJia Liu         break;
1389a4fd3ec3SEmilio G. Cota     default:
1390a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1391a4fd3ec3SEmilio G. Cota     }
1392bbe418f2SJia Liu }
1393bbe418f2SJia Liu 
1394a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1395a4fd3ec3SEmilio G. Cota {
1396a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
13970a7df5daSRichard Henderson 
1398a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1399a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1400bbe418f2SJia Liu }
1401a4fd3ec3SEmilio G. Cota 
1402a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1403a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1404a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1405a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1406a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1407a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1408a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1409a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1410a4fd3ec3SEmilio G. Cota };
1411a4fd3ec3SEmilio G. Cota 
1412*8b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1413a4fd3ec3SEmilio G. Cota {
1414a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1415a4fd3ec3SEmilio G. Cota 
1416*8b86d6d2SRichard Henderson     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
1417e67db06eSJia Liu }
1418e67db06eSJia Liu 
141990c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1420e67db06eSJia Liu {
1421878096eeSAndreas Färber     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1422878096eeSAndreas Färber     CPUOpenRISCState *env = &cpu->env;
1423e67db06eSJia Liu     int i;
1424878096eeSAndreas Färber 
142590c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1426e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
142790c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1428e67db06eSJia Liu                      (i % 4) == 3 ? '\n' : ' ');
1429e67db06eSJia Liu     }
1430e67db06eSJia Liu }
1431e67db06eSJia Liu 
1432e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1433bad729e2SRichard Henderson                           target_ulong *data)
1434e67db06eSJia Liu {
1435bad729e2SRichard Henderson     env->pc = data[0];
1436a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1437a01deb36SRichard Henderson     if (data[1] & 2) {
143824c32852SRichard Henderson         env->ppc = env->pc - 4;
143924c32852SRichard Henderson     }
1440e67db06eSJia Liu }
1441