xref: /qemu/target/openrisc/translate.c (revision 8bba7619)
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
10779fc6adSThomas Huth  * version 2.1 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/log.h"
27fcf5ef2aSThomas Huth #include "qemu/bitops.h"
2890c84c56SMarkus Armbruster #include "qemu/qemu-print.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 
3977fc6f5eSLluís Vilanova /* is_jmp field values */
4064e46c95SRichard Henderson #define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
418000ba56SRichard Henderson #define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
4277fc6f5eSLluís Vilanova 
43fcf5ef2aSThomas Huth typedef struct DisasContext {
441ffa4bceSEmilio G. Cota     DisasContextBase base;
45fcf5ef2aSThomas Huth     uint32_t mem_idx;
46a01deb36SRichard Henderson     uint32_t tb_flags;
47fcf5ef2aSThomas Huth     uint32_t delayed_branch;
488000ba56SRichard Henderson 
498000ba56SRichard Henderson     /* If not -1, jmp_pc contains this value and so is a direct jump.  */
508000ba56SRichard Henderson     target_ulong jmp_pc_imm;
51fcf5ef2aSThomas Huth } DisasContext;
52fcf5ef2aSThomas Huth 
532ba65417SRichard Henderson static inline bool is_user(DisasContext *dc)
542ba65417SRichard Henderson {
552ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY
562ba65417SRichard Henderson     return true;
572ba65417SRichard Henderson #else
58b9bed1b9SRichard Henderson     return !(dc->tb_flags & TB_FLAGS_SM);
592ba65417SRichard Henderson #endif
602ba65417SRichard Henderson }
612ba65417SRichard Henderson 
627de9729fSRichard Henderson /* Include the auto-generated decoder.  */
637de9729fSRichard Henderson #include "decode.inc.c"
647de9729fSRichard Henderson 
65fcf5ef2aSThomas Huth static TCGv cpu_sr;
66*8bba7619SRichard Henderson static TCGv cpu_regs[32];
676597c28dSRichard Henderson static TCGv cpu_R0;
68fcf5ef2aSThomas Huth static TCGv cpu_pc;
69fcf5ef2aSThomas Huth static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
70fcf5ef2aSThomas Huth static TCGv cpu_ppc;
7184775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
7297458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
7397458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
74930c3d00SRichard Henderson static TCGv cpu_lock_addr;
75930c3d00SRichard Henderson static TCGv cpu_lock_value;
76fcf5ef2aSThomas Huth static TCGv_i32 fpcsr;
776f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
78a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
79fcf5ef2aSThomas Huth 
80fcf5ef2aSThomas Huth void openrisc_translate_init(void)
81fcf5ef2aSThomas Huth {
82fcf5ef2aSThomas Huth     static const char * const regnames[] = {
83fcf5ef2aSThomas Huth         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
84fcf5ef2aSThomas Huth         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
85fcf5ef2aSThomas Huth         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
86fcf5ef2aSThomas Huth         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
87fcf5ef2aSThomas Huth     };
88fcf5ef2aSThomas Huth     int i;
89fcf5ef2aSThomas Huth 
90fcf5ef2aSThomas Huth     cpu_sr = tcg_global_mem_new(cpu_env,
91fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, sr), "sr");
92a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
93a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
94a01deb36SRichard Henderson                                        "dflag");
95fcf5ef2aSThomas Huth     cpu_pc = tcg_global_mem_new(cpu_env,
96fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, pc), "pc");
97fcf5ef2aSThomas Huth     cpu_ppc = tcg_global_mem_new(cpu_env,
98fcf5ef2aSThomas Huth                                  offsetof(CPUOpenRISCState, ppc), "ppc");
99fcf5ef2aSThomas Huth     jmp_pc = tcg_global_mem_new(cpu_env,
100fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
10184775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
10284775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
10397458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
10497458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
10597458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
10697458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
107930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
108930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
109930c3d00SRichard Henderson                                        "lock_addr");
110930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
111930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
112930c3d00SRichard Henderson                                         "lock_value");
113fcf5ef2aSThomas Huth     fpcsr = tcg_global_mem_new_i32(cpu_env,
114fcf5ef2aSThomas Huth                                    offsetof(CPUOpenRISCState, fpcsr),
115fcf5ef2aSThomas Huth                                    "fpcsr");
1166f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1176f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1186f7332baSRichard Henderson                                      "mac");
119fcf5ef2aSThomas Huth     for (i = 0; i < 32; i++) {
120*8bba7619SRichard Henderson         cpu_regs[i] = tcg_global_mem_new(cpu_env,
121d89e71e8SStafford Horne                                          offsetof(CPUOpenRISCState,
122d89e71e8SStafford Horne                                                   shadow_gpr[0][i]),
123fcf5ef2aSThomas Huth                                          regnames[i]);
124fcf5ef2aSThomas Huth     }
125*8bba7619SRichard Henderson     cpu_R0 = cpu_regs[0];
126fcf5ef2aSThomas Huth }
127fcf5ef2aSThomas Huth 
128fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, unsigned int excp)
129fcf5ef2aSThomas Huth {
130fcf5ef2aSThomas Huth     TCGv_i32 tmp = tcg_const_i32(excp);
131fcf5ef2aSThomas Huth     gen_helper_exception(cpu_env, tmp);
132fcf5ef2aSThomas Huth     tcg_temp_free_i32(tmp);
133fcf5ef2aSThomas Huth }
134fcf5ef2aSThomas Huth 
135fcf5ef2aSThomas Huth static void gen_illegal_exception(DisasContext *dc)
136fcf5ef2aSThomas Huth {
1371ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
138fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_ILLEGAL);
1391ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
140fcf5ef2aSThomas Huth }
141fcf5ef2aSThomas Huth 
142fcf5ef2aSThomas Huth /* not used yet, open it when we need or64.  */
143fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64
144fcf5ef2aSThomas Huth static void check_ob64s(DisasContext *dc)
145fcf5ef2aSThomas Huth {
146fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OB64S)) {
147fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
148fcf5ef2aSThomas Huth     }
149fcf5ef2aSThomas Huth }
150fcf5ef2aSThomas Huth 
151fcf5ef2aSThomas Huth static void check_of64s(DisasContext *dc)
152fcf5ef2aSThomas Huth {
153fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OF64S)) {
154fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
155fcf5ef2aSThomas Huth     }
156fcf5ef2aSThomas Huth }
157fcf5ef2aSThomas Huth 
158fcf5ef2aSThomas Huth static void check_ov64s(DisasContext *dc)
159fcf5ef2aSThomas Huth {
160fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OV64S)) {
161fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
162fcf5ef2aSThomas Huth     }
163fcf5ef2aSThomas Huth }
164fcf5ef2aSThomas Huth #endif*/
165fcf5ef2aSThomas Huth 
166*8bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg)
167*8bba7619SRichard Henderson {
168*8bba7619SRichard Henderson     return cpu_regs[reg];
169*8bba7619SRichard Henderson }
170*8bba7619SRichard Henderson 
171cdd0f459SRichard Henderson /*
172cdd0f459SRichard Henderson  * We're about to write to REG.  On the off-chance that the user is
173cdd0f459SRichard Henderson  * writing to R0, re-instate the architectural register.
174cdd0f459SRichard Henderson  */
175cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg)
176cdd0f459SRichard Henderson {
177cdd0f459SRichard Henderson     if (unlikely(reg == 0)) {
178*8bba7619SRichard Henderson         cpu_regs[0] = cpu_R0;
179cdd0f459SRichard Henderson     }
180cdd0f459SRichard Henderson }
1816597c28dSRichard Henderson 
18297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1839ecaa27eSRichard Henderson {
1840c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
18597458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
1869ecaa27eSRichard Henderson     }
1870c53d734SRichard Henderson }
1889ecaa27eSRichard Henderson 
18997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1909ecaa27eSRichard Henderson {
1910c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
19297458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
1939ecaa27eSRichard Henderson     }
1940c53d734SRichard Henderson }
1959ecaa27eSRichard Henderson 
19697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1979ecaa27eSRichard Henderson {
1980c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
19997458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
2009ecaa27eSRichard Henderson     }
2010c53d734SRichard Henderson }
2029ecaa27eSRichard Henderson 
2039ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2049ecaa27eSRichard Henderson {
2059ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2069ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2079ecaa27eSRichard Henderson 
20897458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
20997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2109ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
21197458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2129ecaa27eSRichard Henderson     tcg_temp_free(t0);
2139ecaa27eSRichard Henderson 
2149ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2159ecaa27eSRichard Henderson     tcg_temp_free(res);
2169ecaa27eSRichard Henderson 
21797458071SRichard Henderson     gen_ove_cyov(dc);
2189ecaa27eSRichard Henderson }
2199ecaa27eSRichard Henderson 
2209ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2219ecaa27eSRichard Henderson {
2229ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2239ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2249ecaa27eSRichard Henderson 
22597458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
22697458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
22797458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2289ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22997458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2309ecaa27eSRichard Henderson     tcg_temp_free(t0);
2319ecaa27eSRichard Henderson 
2329ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2339ecaa27eSRichard Henderson     tcg_temp_free(res);
2349ecaa27eSRichard Henderson 
23597458071SRichard Henderson     gen_ove_cyov(dc);
2369ecaa27eSRichard Henderson }
2379ecaa27eSRichard Henderson 
2389ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2399ecaa27eSRichard Henderson {
2409ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2419ecaa27eSRichard Henderson 
2429ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
24397458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
24497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
24597458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
24697458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2479ecaa27eSRichard Henderson 
2489ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2499ecaa27eSRichard Henderson     tcg_temp_free(res);
2509ecaa27eSRichard Henderson 
25197458071SRichard Henderson     gen_ove_cyov(dc);
2529ecaa27eSRichard Henderson }
2539ecaa27eSRichard Henderson 
2549ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2559ecaa27eSRichard Henderson {
2569ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2579ecaa27eSRichard Henderson 
25897458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2599ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
26097458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2619ecaa27eSRichard Henderson     tcg_temp_free(t0);
2629ecaa27eSRichard Henderson 
26397458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
26497458071SRichard Henderson     gen_ove_ov(dc);
2659ecaa27eSRichard Henderson }
2669ecaa27eSRichard Henderson 
2679ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2689ecaa27eSRichard Henderson {
26997458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
27097458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2719ecaa27eSRichard Henderson 
27297458071SRichard Henderson     gen_ove_cy(dc);
2739ecaa27eSRichard Henderson }
2749ecaa27eSRichard Henderson 
2759ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2769ecaa27eSRichard Henderson {
2779ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2789ecaa27eSRichard Henderson 
27997458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2809ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2819ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
28297458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2839ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2849ecaa27eSRichard Henderson     tcg_temp_free(t0);
2859ecaa27eSRichard Henderson 
28697458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
28797458071SRichard Henderson     gen_ove_ov(dc);
2889ecaa27eSRichard Henderson }
2899ecaa27eSRichard Henderson 
2909ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2919ecaa27eSRichard Henderson {
2929ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2939ecaa27eSRichard Henderson 
29497458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2959ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2969ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
29797458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2989ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2999ecaa27eSRichard Henderson     tcg_temp_free(t0);
3009ecaa27eSRichard Henderson 
30197458071SRichard Henderson     gen_ove_cy(dc);
3029ecaa27eSRichard Henderson }
303fcf5ef2aSThomas Huth 
304cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
305cc5de49eSRichard Henderson {
306cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
307cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
308cc5de49eSRichard Henderson 
309cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
310cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
311cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
312cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
313cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
314cc5de49eSRichard Henderson     } else {
315cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
316cc5de49eSRichard Henderson 
317cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
318cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
319cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
320cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
321cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
322cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
323cc5de49eSRichard Henderson 
324cc5de49eSRichard Henderson         gen_ove_ov(dc);
325cc5de49eSRichard Henderson     }
326cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
327cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
328cc5de49eSRichard Henderson }
329cc5de49eSRichard Henderson 
330cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
331cc5de49eSRichard Henderson {
332cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
333cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
334cc5de49eSRichard Henderson 
335cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
336cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
337cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
338cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
339cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
340cc5de49eSRichard Henderson     } else {
341cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
342cc5de49eSRichard Henderson 
343cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
344cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
345cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
346cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
347cc5de49eSRichard Henderson 
348cc5de49eSRichard Henderson         gen_ove_cy(dc);
349cc5de49eSRichard Henderson     }
350cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
351cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
352cc5de49eSRichard Henderson }
353cc5de49eSRichard Henderson 
3546f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3556f7332baSRichard Henderson {
3566f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3576f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3586f7332baSRichard Henderson 
3596f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3606f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3616f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3626f7332baSRichard Henderson 
3636f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3646f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3656f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3666f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3676f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3686f7332baSRichard Henderson     tcg_temp_free_i64(t2);
3696f7332baSRichard Henderson 
3706f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3716f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3726f7332baSRichard Henderson #else
3736f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3746f7332baSRichard Henderson #endif
3756f7332baSRichard Henderson     tcg_temp_free_i64(t1);
3766f7332baSRichard Henderson 
3776f7332baSRichard Henderson     gen_ove_ov(dc);
3786f7332baSRichard Henderson }
3796f7332baSRichard Henderson 
380cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
381cc5de49eSRichard Henderson {
382cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
383cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
384cc5de49eSRichard Henderson 
385cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
386cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
387cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
388cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
389cc5de49eSRichard Henderson 
390cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
391cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
392cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
393cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
394cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
395cc5de49eSRichard Henderson 
396cc5de49eSRichard Henderson     gen_ove_cy(dc);
397cc5de49eSRichard Henderson }
398cc5de49eSRichard Henderson 
3996f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
4006f7332baSRichard Henderson {
4016f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4026f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4036f7332baSRichard Henderson 
4046f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4056f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4066f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4076f7332baSRichard Henderson 
4086f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4096f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4106f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4116f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4126f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4136f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4146f7332baSRichard Henderson 
4156f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4166f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4176f7332baSRichard Henderson #else
4186f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4196f7332baSRichard Henderson #endif
4206f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4216f7332baSRichard Henderson 
4226f7332baSRichard Henderson     gen_ove_ov(dc);
4236f7332baSRichard Henderson }
4246f7332baSRichard Henderson 
425cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
426cc5de49eSRichard Henderson {
427cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
428cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
429cc5de49eSRichard Henderson 
430cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
431cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
432cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
433cc5de49eSRichard Henderson 
434cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
435cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
436cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
437cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
438cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
439cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
440cc5de49eSRichard Henderson 
441cc5de49eSRichard Henderson     gen_ove_cy(dc);
442cc5de49eSRichard Henderson }
443cc5de49eSRichard Henderson 
4443a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
445fcf5ef2aSThomas Huth {
446cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
447*8bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4486ad216abSRichard Henderson     return true;
449fcf5ef2aSThomas Huth }
450fcf5ef2aSThomas Huth 
4513a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
452fcf5ef2aSThomas Huth {
453cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
454*8bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4556ad216abSRichard Henderson     return true;
4566ad216abSRichard Henderson }
4576ad216abSRichard Henderson 
4583a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4596ad216abSRichard Henderson {
460cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
461*8bba7619SRichard Henderson     gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4626ad216abSRichard Henderson     return true;
4636ad216abSRichard Henderson }
4646ad216abSRichard Henderson 
4653a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4666ad216abSRichard Henderson {
467cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
468*8bba7619SRichard Henderson     tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4696ad216abSRichard Henderson     return true;
4706ad216abSRichard Henderson }
4716ad216abSRichard Henderson 
4723a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4736ad216abSRichard Henderson {
474cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
475*8bba7619SRichard Henderson     tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4766ad216abSRichard Henderson     return true;
4776ad216abSRichard Henderson }
4786ad216abSRichard Henderson 
4793a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4806ad216abSRichard Henderson {
481cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
482*8bba7619SRichard Henderson     tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4836ad216abSRichard Henderson     return true;
4846ad216abSRichard Henderson }
4856ad216abSRichard Henderson 
4863a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4876ad216abSRichard Henderson {
488cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
489*8bba7619SRichard Henderson     tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4906ad216abSRichard Henderson     return true;
4916ad216abSRichard Henderson }
4926ad216abSRichard Henderson 
4933a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4946ad216abSRichard Henderson {
495cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
496*8bba7619SRichard Henderson     tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4976ad216abSRichard Henderson     return true;
4986ad216abSRichard Henderson }
4996ad216abSRichard Henderson 
5003a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
5016ad216abSRichard Henderson {
502cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
503*8bba7619SRichard Henderson     tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5046ad216abSRichard Henderson     return true;
5056ad216abSRichard Henderson }
5066ad216abSRichard Henderson 
5073a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
5086ad216abSRichard Henderson {
509cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
510*8bba7619SRichard Henderson     tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5116ad216abSRichard Henderson     return true;
5126ad216abSRichard Henderson }
5136ad216abSRichard Henderson 
5143a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
5156ad216abSRichard Henderson {
516cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
517*8bba7619SRichard Henderson     tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5186ad216abSRichard Henderson     return true;
5196ad216abSRichard Henderson }
5206ad216abSRichard Henderson 
5213a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
5226ad216abSRichard Henderson {
523cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
524*8bba7619SRichard Henderson     tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5256ad216abSRichard Henderson     return true;
5266ad216abSRichard Henderson }
5276ad216abSRichard Henderson 
5283a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5296ad216abSRichard Henderson {
530cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
531*8bba7619SRichard Henderson     tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5326ad216abSRichard Henderson     return true;
5336ad216abSRichard Henderson }
5346ad216abSRichard Henderson 
5353a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5366ad216abSRichard Henderson {
537cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
538*8bba7619SRichard Henderson     tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5396ad216abSRichard Henderson     return true;
5406ad216abSRichard Henderson }
5416ad216abSRichard Henderson 
5423a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5436ad216abSRichard Henderson {
5446ad216abSRichard Henderson     TCGv zero;
5456ad216abSRichard Henderson 
546cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5476ad216abSRichard Henderson     zero = tcg_const_tl(0);
548*8bba7619SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero,
549*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
550784696d1SRichard Henderson     tcg_temp_free(zero);
5516ad216abSRichard Henderson     return true;
552fcf5ef2aSThomas Huth }
553fcf5ef2aSThomas Huth 
5543a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5556ad216abSRichard Henderson {
556cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
557*8bba7619SRichard Henderson     tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
558*8bba7619SRichard Henderson     tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
5596ad216abSRichard Henderson     return true;
560cf2ae442SRichard Henderson }
561cf2ae442SRichard Henderson 
5623a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5636ad216abSRichard Henderson {
564cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
565*8bba7619SRichard Henderson     tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
566*8bba7619SRichard Henderson     tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
5676ad216abSRichard Henderson     return true;
568fcf5ef2aSThomas Huth }
569fcf5ef2aSThomas Huth 
5703a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5716ad216abSRichard Henderson {
572cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
573*8bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5746ad216abSRichard Henderson     return true;
575fcf5ef2aSThomas Huth }
5766ad216abSRichard Henderson 
5773a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5786ad216abSRichard Henderson {
579cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
580*8bba7619SRichard Henderson     gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5816ad216abSRichard Henderson     return true;
582fcf5ef2aSThomas Huth }
5836ad216abSRichard Henderson 
5843a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5856ad216abSRichard Henderson {
586cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
587*8bba7619SRichard Henderson     gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5886ad216abSRichard Henderson     return true;
5896ad216abSRichard Henderson }
5906ad216abSRichard Henderson 
5913a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5926ad216abSRichard Henderson {
593cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
594*8bba7619SRichard Henderson     gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5956ad216abSRichard Henderson     return true;
5966ad216abSRichard Henderson }
5976ad216abSRichard Henderson 
5983a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5996ad216abSRichard Henderson {
600*8bba7619SRichard Henderson     gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
6016ad216abSRichard Henderson     return true;
6026ad216abSRichard Henderson }
6036ad216abSRichard Henderson 
6043a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
6056ad216abSRichard Henderson {
606*8bba7619SRichard Henderson     gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
6076ad216abSRichard Henderson     return true;
608fcf5ef2aSThomas Huth }
609fcf5ef2aSThomas Huth 
6103a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
611136e13aeSRichard Henderson {
612136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
613136e13aeSRichard Henderson 
614136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
6158000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
616136e13aeSRichard Henderson     dc->delayed_branch = 2;
617136e13aeSRichard Henderson     return true;
618136e13aeSRichard Henderson }
619136e13aeSRichard Henderson 
6203a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
621136e13aeSRichard Henderson {
622136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
623136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
624136e13aeSRichard Henderson 
625*8bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], ret_pc);
626136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
627136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
628136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6298000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
630136e13aeSRichard Henderson         dc->delayed_branch = 2;
631136e13aeSRichard Henderson     }
632136e13aeSRichard Henderson     return true;
633136e13aeSRichard Henderson }
634136e13aeSRichard Henderson 
635136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
636136e13aeSRichard Henderson {
637136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
638136e13aeSRichard Henderson     TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
639136e13aeSRichard Henderson     TCGv t_true = tcg_const_tl(tmp_pc);
640136e13aeSRichard Henderson     TCGv t_zero = tcg_const_tl(0);
641136e13aeSRichard Henderson 
642136e13aeSRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
643136e13aeSRichard Henderson 
644136e13aeSRichard Henderson     tcg_temp_free(t_next);
645136e13aeSRichard Henderson     tcg_temp_free(t_true);
646136e13aeSRichard Henderson     tcg_temp_free(t_zero);
647136e13aeSRichard Henderson     dc->delayed_branch = 2;
648136e13aeSRichard Henderson }
649136e13aeSRichard Henderson 
6503a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
651136e13aeSRichard Henderson {
652136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
653136e13aeSRichard Henderson     return true;
654136e13aeSRichard Henderson }
655136e13aeSRichard Henderson 
6563a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
657136e13aeSRichard Henderson {
658136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
659136e13aeSRichard Henderson     return true;
660136e13aeSRichard Henderson }
661136e13aeSRichard Henderson 
6623a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
663136e13aeSRichard Henderson {
664*8bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
665136e13aeSRichard Henderson     dc->delayed_branch = 2;
666136e13aeSRichard Henderson     return true;
667136e13aeSRichard Henderson }
668136e13aeSRichard Henderson 
6693a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
670136e13aeSRichard Henderson {
671*8bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
672*8bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
673136e13aeSRichard Henderson     dc->delayed_branch = 2;
674136e13aeSRichard Henderson     return true;
675136e13aeSRichard Henderson }
676136e13aeSRichard Henderson 
6773a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
678d80bff19SRichard Henderson {
679d80bff19SRichard Henderson     TCGv ea;
680d80bff19SRichard Henderson 
681cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
682d80bff19SRichard Henderson     ea = tcg_temp_new();
683*8bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
684*8bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
685d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
686*8bba7619SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
687d80bff19SRichard Henderson     tcg_temp_free(ea);
688d80bff19SRichard Henderson     return true;
689d80bff19SRichard Henderson }
690d80bff19SRichard Henderson 
69114776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
692d80bff19SRichard Henderson {
693d80bff19SRichard Henderson     TCGv ea;
694d80bff19SRichard Henderson 
695cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
696d80bff19SRichard Henderson     ea = tcg_temp_new();
697*8bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
698*8bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
699d80bff19SRichard Henderson     tcg_temp_free(ea);
700d80bff19SRichard Henderson }
701d80bff19SRichard Henderson 
7023a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
703d80bff19SRichard Henderson {
704d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
705d80bff19SRichard Henderson     return true;
706d80bff19SRichard Henderson }
707d80bff19SRichard Henderson 
7083a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
709d80bff19SRichard Henderson {
710d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
711d80bff19SRichard Henderson     return true;
712d80bff19SRichard Henderson }
713d80bff19SRichard Henderson 
7143a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
715d80bff19SRichard Henderson {
716d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
717d80bff19SRichard Henderson     return true;
718d80bff19SRichard Henderson }
719d80bff19SRichard Henderson 
7203a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
721d80bff19SRichard Henderson {
722d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
723d80bff19SRichard Henderson     return true;
724d80bff19SRichard Henderson }
725d80bff19SRichard Henderson 
7263a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
727d80bff19SRichard Henderson {
728d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
729d80bff19SRichard Henderson     return true;
730d80bff19SRichard Henderson }
731d80bff19SRichard Henderson 
7323a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
733d80bff19SRichard Henderson {
734d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
735d80bff19SRichard Henderson     return true;
736d80bff19SRichard Henderson }
737d80bff19SRichard Henderson 
7383a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
739d80bff19SRichard Henderson {
740d80bff19SRichard Henderson     TCGv ea, val;
741d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
742d80bff19SRichard Henderson 
743d80bff19SRichard Henderson     ea = tcg_temp_new();
744*8bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
745d80bff19SRichard Henderson 
746d80bff19SRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
747*8bba7619SRichard Henderson        to cpu_regs[0].  Since l.swa is quite often immediately followed by a
748d80bff19SRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
749d80bff19SRichard Henderson        This also takes care of RB input across the branch.  */
750*8bba7619SRichard Henderson     cpu_regs[0] = cpu_R0;
751d80bff19SRichard Henderson 
752d80bff19SRichard Henderson     lab_fail = gen_new_label();
753d80bff19SRichard Henderson     lab_done = gen_new_label();
754d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
755d80bff19SRichard Henderson     tcg_temp_free(ea);
756d80bff19SRichard Henderson 
757d80bff19SRichard Henderson     val = tcg_temp_new();
758d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
759*8bba7619SRichard Henderson                               cpu_regs[a->b], dc->mem_idx, MO_TEUL);
760d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
761d80bff19SRichard Henderson     tcg_temp_free(val);
762d80bff19SRichard Henderson 
763d80bff19SRichard Henderson     tcg_gen_br(lab_done);
764d80bff19SRichard Henderson 
765d80bff19SRichard Henderson     gen_set_label(lab_fail);
766d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
767d80bff19SRichard Henderson 
768d80bff19SRichard Henderson     gen_set_label(lab_done);
769d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
770d80bff19SRichard Henderson     return true;
771d80bff19SRichard Henderson }
772d80bff19SRichard Henderson 
77314776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
774d80bff19SRichard Henderson {
775d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
776*8bba7619SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
777*8bba7619SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
778d80bff19SRichard Henderson     tcg_temp_free(t0);
779d80bff19SRichard Henderson }
780d80bff19SRichard Henderson 
7813a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
782d80bff19SRichard Henderson {
783d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
784d80bff19SRichard Henderson     return true;
785d80bff19SRichard Henderson }
786d80bff19SRichard Henderson 
7873a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
788d80bff19SRichard Henderson {
789d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
790d80bff19SRichard Henderson     return true;
791d80bff19SRichard Henderson }
792d80bff19SRichard Henderson 
7933a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
794d80bff19SRichard Henderson {
795d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
796d80bff19SRichard Henderson     return true;
797d80bff19SRichard Henderson }
798d80bff19SRichard Henderson 
7993a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
800fcf5ef2aSThomas Huth {
8018816f70bSRichard Henderson     return true;
8028816f70bSRichard Henderson }
8038816f70bSRichard Henderson 
8043a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
8058816f70bSRichard Henderson {
8069ecaa27eSRichard Henderson     TCGv t0;
807fcf5ef2aSThomas Huth 
808cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8098816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
810*8bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8116f7332baSRichard Henderson     tcg_temp_free(t0);
8128816f70bSRichard Henderson     return true;
8138816f70bSRichard Henderson }
814fcf5ef2aSThomas Huth 
8153a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
816fcf5ef2aSThomas Huth {
8178816f70bSRichard Henderson     TCGv t0;
8188816f70bSRichard Henderson 
819cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8208816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
821*8bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8228816f70bSRichard Henderson     tcg_temp_free(t0);
8238816f70bSRichard Henderson     return true;
8248816f70bSRichard Henderson }
8258816f70bSRichard Henderson 
8263a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
8278816f70bSRichard Henderson {
8288816f70bSRichard Henderson     TCGv t0;
8298816f70bSRichard Henderson 
830cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8318816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
832*8bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8338816f70bSRichard Henderson     tcg_temp_free(t0);
8348816f70bSRichard Henderson     return true;
8358816f70bSRichard Henderson }
8368816f70bSRichard Henderson 
8373a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
8388816f70bSRichard Henderson {
8398816f70bSRichard Henderson     TCGv t0;
8408816f70bSRichard Henderson 
8418816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
842*8bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), t0);
8438816f70bSRichard Henderson     tcg_temp_free(t0);
8448816f70bSRichard Henderson     return true;
8458816f70bSRichard Henderson }
8468816f70bSRichard Henderson 
8473a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8488816f70bSRichard Henderson {
849cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
850*8bba7619SRichard Henderson     tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8518816f70bSRichard Henderson     return true;
8528816f70bSRichard Henderson }
8538816f70bSRichard Henderson 
8543a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8558816f70bSRichard Henderson {
856cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
857*8bba7619SRichard Henderson     tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8588816f70bSRichard Henderson     return true;
8598816f70bSRichard Henderson }
8608816f70bSRichard Henderson 
8613a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8628816f70bSRichard Henderson {
863cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
864*8bba7619SRichard Henderson     tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
8658816f70bSRichard Henderson     return true;
8668816f70bSRichard Henderson }
8678816f70bSRichard Henderson 
8683a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8698816f70bSRichard Henderson {
870cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8718816f70bSRichard Henderson 
8722ba65417SRichard Henderson     if (is_user(dc)) {
873fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
8748816f70bSRichard Henderson     } else {
875c28fa81fSRichard Henderson         TCGv spr = tcg_temp_new();
876*8bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
877*8bba7619SRichard Henderson         gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
878c28fa81fSRichard Henderson         tcg_temp_free(spr);
879fcf5ef2aSThomas Huth     }
8808816f70bSRichard Henderson     return true;
8818816f70bSRichard Henderson }
882fcf5ef2aSThomas Huth 
8833a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
884fcf5ef2aSThomas Huth {
8852ba65417SRichard Henderson     if (is_user(dc)) {
886fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
8878816f70bSRichard Henderson     } else {
888c28fa81fSRichard Henderson         TCGv spr;
88901ec3ec9SRichard Henderson 
89001ec3ec9SRichard Henderson         /* For SR, we will need to exit the TB to recognize the new
89101ec3ec9SRichard Henderson          * exception state.  For NPC, in theory this counts as a branch
89201ec3ec9SRichard Henderson          * (although the SPR only exists for use by an ICE).  Save all
89301ec3ec9SRichard Henderson          * of the cpu state first, allowing it to be overwritten.
89401ec3ec9SRichard Henderson          */
89501ec3ec9SRichard Henderson         if (dc->delayed_branch) {
89601ec3ec9SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
89701ec3ec9SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
89801ec3ec9SRichard Henderson         } else {
89901ec3ec9SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
90001ec3ec9SRichard Henderson         }
90101ec3ec9SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
90201ec3ec9SRichard Henderson 
903c28fa81fSRichard Henderson         spr = tcg_temp_new();
904*8bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
905*8bba7619SRichard Henderson         gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b));
906c28fa81fSRichard Henderson         tcg_temp_free(spr);
907fcf5ef2aSThomas Huth     }
9088816f70bSRichard Henderson     return true;
909fcf5ef2aSThomas Huth }
910fcf5ef2aSThomas Huth 
9113a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
912fcf5ef2aSThomas Huth {
913*8bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
91499d863d6SRichard Henderson     return true;
915fcf5ef2aSThomas Huth }
91699d863d6SRichard Henderson 
9173a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
91899d863d6SRichard Henderson {
919*8bba7619SRichard Henderson     gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
92099d863d6SRichard Henderson     return true;
92199d863d6SRichard Henderson }
92299d863d6SRichard Henderson 
9233a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
92499d863d6SRichard Henderson {
925*8bba7619SRichard Henderson     gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
92699d863d6SRichard Henderson     return true;
92799d863d6SRichard Henderson }
92899d863d6SRichard Henderson 
9293a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
93099d863d6SRichard Henderson {
931*8bba7619SRichard Henderson     gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
93299d863d6SRichard Henderson     return true;
933fcf5ef2aSThomas Huth }
934fcf5ef2aSThomas Huth 
9353a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
936fcf5ef2aSThomas Huth {
937cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
938*8bba7619SRichard Henderson     tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
939*8bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
940e20c2592SRichard Henderson     return true;
941fcf5ef2aSThomas Huth }
942e20c2592SRichard Henderson 
9433a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
944e20c2592SRichard Henderson {
945cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
946*8bba7619SRichard Henderson     tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
947*8bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
948e20c2592SRichard Henderson     return true;
949e20c2592SRichard Henderson }
950e20c2592SRichard Henderson 
9513a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
952e20c2592SRichard Henderson {
953cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
954*8bba7619SRichard Henderson     tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
955*8bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
956e20c2592SRichard Henderson     return true;
957e20c2592SRichard Henderson }
958e20c2592SRichard Henderson 
9593a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
960e20c2592SRichard Henderson {
961cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
962*8bba7619SRichard Henderson     tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
963*8bba7619SRichard Henderson                      a->l & (TARGET_LONG_BITS - 1));
964e20c2592SRichard Henderson     return true;
965fcf5ef2aSThomas Huth }
966fcf5ef2aSThomas Huth 
9673a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
968fcf5ef2aSThomas Huth {
969cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
970*8bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
971e720a571SRichard Henderson     return true;
972fcf5ef2aSThomas Huth }
973e720a571SRichard Henderson 
9743a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
975e720a571SRichard Henderson {
976cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
977*8bba7619SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
978e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
979e720a571SRichard Henderson     return true;
980fcf5ef2aSThomas Huth }
981fcf5ef2aSThomas Huth 
9823a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
983fcf5ef2aSThomas Huth {
984*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
985*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
986fbb3e29aSRichard Henderson     return true;
987fcf5ef2aSThomas Huth }
988fbb3e29aSRichard Henderson 
9893a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
990fbb3e29aSRichard Henderson {
991*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
992*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
993fbb3e29aSRichard Henderson     return true;
994fbb3e29aSRichard Henderson }
995fbb3e29aSRichard Henderson 
9963a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
997fbb3e29aSRichard Henderson {
998*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
999*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1000fbb3e29aSRichard Henderson     return true;
1001fbb3e29aSRichard Henderson }
1002fbb3e29aSRichard Henderson 
10033a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
1004fbb3e29aSRichard Henderson {
1005*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
1006*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1007fbb3e29aSRichard Henderson     return true;
1008fbb3e29aSRichard Henderson }
1009fbb3e29aSRichard Henderson 
10103a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
1011fbb3e29aSRichard Henderson {
1012*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
1013*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1014fbb3e29aSRichard Henderson     return true;
1015fbb3e29aSRichard Henderson }
1016fbb3e29aSRichard Henderson 
10173a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
1018fbb3e29aSRichard Henderson {
1019*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
1020*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1021fbb3e29aSRichard Henderson     return true;
1022fbb3e29aSRichard Henderson }
1023fbb3e29aSRichard Henderson 
10243a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
1025fbb3e29aSRichard Henderson {
1026*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
1027*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1028fbb3e29aSRichard Henderson     return true;
1029fbb3e29aSRichard Henderson }
1030fbb3e29aSRichard Henderson 
10313a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
1032fbb3e29aSRichard Henderson {
1033*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
1034*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1035fbb3e29aSRichard Henderson     return true;
1036fbb3e29aSRichard Henderson }
1037fbb3e29aSRichard Henderson 
10383a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
1039fbb3e29aSRichard Henderson {
1040*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
1041*8bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1042fbb3e29aSRichard Henderson     return true;
1043fbb3e29aSRichard Henderson }
1044fbb3e29aSRichard Henderson 
10453a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1046fbb3e29aSRichard Henderson {
1047*8bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE,
1048*8bba7619SRichard Henderson                        cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1049fbb3e29aSRichard Henderson     return true;
1050fcf5ef2aSThomas Huth }
1051fcf5ef2aSThomas Huth 
10523a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1053fcf5ef2aSThomas Huth {
1054*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1055032de4fcSRichard Henderson     return true;
1056fcf5ef2aSThomas Huth }
1057032de4fcSRichard Henderson 
10583a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1059032de4fcSRichard Henderson {
1060*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1061032de4fcSRichard Henderson     return true;
1062032de4fcSRichard Henderson }
1063032de4fcSRichard Henderson 
10643a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1065032de4fcSRichard Henderson {
1066*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1067032de4fcSRichard Henderson     return true;
1068032de4fcSRichard Henderson }
1069032de4fcSRichard Henderson 
10703a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1071032de4fcSRichard Henderson {
1072*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1073032de4fcSRichard Henderson     return true;
1074032de4fcSRichard Henderson }
1075032de4fcSRichard Henderson 
10763a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1077032de4fcSRichard Henderson {
1078*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1079032de4fcSRichard Henderson     return true;
1080032de4fcSRichard Henderson }
1081032de4fcSRichard Henderson 
10823a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1083032de4fcSRichard Henderson {
1084*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1085032de4fcSRichard Henderson     return true;
1086032de4fcSRichard Henderson }
1087032de4fcSRichard Henderson 
10883a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1089032de4fcSRichard Henderson {
1090*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1091032de4fcSRichard Henderson     return true;
1092032de4fcSRichard Henderson }
1093032de4fcSRichard Henderson 
10943a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1095032de4fcSRichard Henderson {
1096*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1097032de4fcSRichard Henderson     return true;
1098032de4fcSRichard Henderson }
1099032de4fcSRichard Henderson 
11003a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1101032de4fcSRichard Henderson {
1102*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1103032de4fcSRichard Henderson     return true;
1104032de4fcSRichard Henderson }
1105032de4fcSRichard Henderson 
11063a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1107032de4fcSRichard Henderson {
1108*8bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1109032de4fcSRichard Henderson     return true;
1110fcf5ef2aSThomas Huth }
1111fcf5ef2aSThomas Huth 
11123a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1113fcf5ef2aSThomas Huth {
11141ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1115fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_SYSCALL);
11161ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11177de9729fSRichard Henderson     return true;
11187de9729fSRichard Henderson }
1119fcf5ef2aSThomas Huth 
11203a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
11217de9729fSRichard Henderson {
11221ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1123fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_TRAP);
11241ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11257de9729fSRichard Henderson     return true;
11267de9729fSRichard Henderson }
1127fcf5ef2aSThomas Huth 
11283a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
11297de9729fSRichard Henderson {
113024fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
11317de9729fSRichard Henderson     return true;
1132fcf5ef2aSThomas Huth }
11337de9729fSRichard Henderson 
11343a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
11357de9729fSRichard Henderson {
11367de9729fSRichard Henderson     return true;
11377de9729fSRichard Henderson }
11387de9729fSRichard Henderson 
11393a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
11407de9729fSRichard Henderson {
11417de9729fSRichard Henderson     return true;
1142fcf5ef2aSThomas Huth }
1143fcf5ef2aSThomas Huth 
11443a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11458816f70bSRichard Henderson {
11462ba65417SRichard Henderson     if (is_user(dc)) {
11478816f70bSRichard Henderson         gen_illegal_exception(dc);
11488816f70bSRichard Henderson     } else {
11498816f70bSRichard Henderson         gen_helper_rfe(cpu_env);
115064e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11518816f70bSRichard Henderson     }
11528816f70bSRichard Henderson     return true;
11538816f70bSRichard Henderson }
11548816f70bSRichard Henderson 
11556fd204a2SRichard Henderson static void do_fp2(DisasContext *dc, arg_da *a,
11566fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1157fcf5ef2aSThomas Huth {
1158cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1159*8bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a));
11604e2d3007SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1161fcf5ef2aSThomas Huth }
11626fd204a2SRichard Henderson 
11636fd204a2SRichard Henderson static void do_fp3(DisasContext *dc, arg_dab *a,
11646fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11656fd204a2SRichard Henderson {
1166cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1167*8bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11686fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
11696fd204a2SRichard Henderson }
11706fd204a2SRichard Henderson 
11716fd204a2SRichard Henderson static void do_fpcmp(DisasContext *dc, arg_ab *a,
11726fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11736fd204a2SRichard Henderson                      bool inv, bool swap)
11746fd204a2SRichard Henderson {
11756fd204a2SRichard Henderson     if (swap) {
1176*8bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
11776fd204a2SRichard Henderson     } else {
1178*8bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11796fd204a2SRichard Henderson     }
11806fd204a2SRichard Henderson     if (inv) {
11816fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11826fd204a2SRichard Henderson     }
11836fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
11846fd204a2SRichard Henderson }
11856fd204a2SRichard Henderson 
11863a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11876fd204a2SRichard Henderson {
11886fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_add_s);
11896fd204a2SRichard Henderson     return true;
11906fd204a2SRichard Henderson }
11916fd204a2SRichard Henderson 
11923a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11936fd204a2SRichard Henderson {
11946fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_sub_s);
11956fd204a2SRichard Henderson     return true;
11966fd204a2SRichard Henderson }
11976fd204a2SRichard Henderson 
11983a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
11996fd204a2SRichard Henderson {
12006fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_mul_s);
12016fd204a2SRichard Henderson     return true;
12026fd204a2SRichard Henderson }
12036fd204a2SRichard Henderson 
12043a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
12056fd204a2SRichard Henderson {
12066fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_div_s);
12076fd204a2SRichard Henderson     return true;
12086fd204a2SRichard Henderson }
12096fd204a2SRichard Henderson 
12103a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
12116fd204a2SRichard Henderson {
12126fd204a2SRichard Henderson     do_fp3(dc, a, gen_helper_float_rem_s);
12136fd204a2SRichard Henderson     return true;
12146fd204a2SRichard Henderson }
12156fd204a2SRichard Henderson 
12163a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
12176fd204a2SRichard Henderson {
12186fd204a2SRichard Henderson     do_fp2(dc, a, gen_helper_itofs);
12196fd204a2SRichard Henderson     return true;
12206fd204a2SRichard Henderson }
12216fd204a2SRichard Henderson 
12223a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
12236fd204a2SRichard Henderson {
12246fd204a2SRichard Henderson     do_fp2(dc, a, gen_helper_ftois);
12256fd204a2SRichard Henderson     return true;
12266fd204a2SRichard Henderson }
12276fd204a2SRichard Henderson 
12283a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
12296fd204a2SRichard Henderson {
1230cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1231*8bba7619SRichard Henderson     gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d),
1232*8bba7619SRichard Henderson                             cpu_R(dc, a->a), cpu_R(dc, a->b));
12336fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
12346fd204a2SRichard Henderson     return true;
12356fd204a2SRichard Henderson }
12366fd204a2SRichard Henderson 
12373a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12386fd204a2SRichard Henderson {
12396fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12406fd204a2SRichard Henderson     return true;
12416fd204a2SRichard Henderson }
12426fd204a2SRichard Henderson 
12433a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12446fd204a2SRichard Henderson {
12456fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12466fd204a2SRichard Henderson     return true;
12476fd204a2SRichard Henderson }
12486fd204a2SRichard Henderson 
12493a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12506fd204a2SRichard Henderson {
12516fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12526fd204a2SRichard Henderson     return true;
12536fd204a2SRichard Henderson }
12546fd204a2SRichard Henderson 
12553a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12566fd204a2SRichard Henderson {
12576fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12586fd204a2SRichard Henderson     return true;
12596fd204a2SRichard Henderson }
12606fd204a2SRichard Henderson 
12613a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12626fd204a2SRichard Henderson {
12636fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12646fd204a2SRichard Henderson     return true;
12656fd204a2SRichard Henderson }
12666fd204a2SRichard Henderson 
12673a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12686fd204a2SRichard Henderson {
12696fd204a2SRichard Henderson     do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
12706fd204a2SRichard Henderson     return true;
1271fcf5ef2aSThomas Huth }
1272fcf5ef2aSThomas Huth 
1273a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1274fcf5ef2aSThomas Huth {
1275a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
12769c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1277a4fd3ec3SEmilio G. Cota     int bound;
1278fcf5ef2aSThomas Huth 
1279a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
12801ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1281a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
12828000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
12838000ba56SRichard Henderson 
1284a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1285a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1286fcf5ef2aSThomas Huth }
1287fcf5ef2aSThomas Huth 
1288a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1289a4fd3ec3SEmilio G. Cota {
1290a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1291fcf5ef2aSThomas Huth 
12926597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
12936597c28dSRichard Henderson        when it's true, which is the common case.  */
12946597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1295*8bba7619SRichard Henderson         cpu_regs[0] = tcg_const_tl(0);
12966597c28dSRichard Henderson     } else {
1297*8bba7619SRichard Henderson         cpu_regs[0] = cpu_R0;
12986597c28dSRichard Henderson     }
1299a4fd3ec3SEmilio G. Cota }
13006597c28dSRichard Henderson 
1301a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1302a4fd3ec3SEmilio G. Cota {
1303a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1304a4fd3ec3SEmilio G. Cota 
13051ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1306a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1307a4fd3ec3SEmilio G. Cota }
1308fcf5ef2aSThomas Huth 
1309a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1310a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1311a4fd3ec3SEmilio G. Cota {
1312a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1313a4fd3ec3SEmilio G. Cota 
13141ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1315fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_DEBUG);
13161ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1317fcf5ef2aSThomas Huth     /* The address covered by the breakpoint must be included in
1318fcf5ef2aSThomas Huth        [tb->pc, tb->pc + tb->size) in order to for it to be
1319fcf5ef2aSThomas Huth        properly cleared -- thus we increment the PC here so that
1320fcf5ef2aSThomas Huth        the logic setting tb->size below does the right thing.  */
13211ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1322a4fd3ec3SEmilio G. Cota     return true;
1323fcf5ef2aSThomas Huth }
1324fcf5ef2aSThomas Huth 
1325a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1326a4fd3ec3SEmilio G. Cota {
1327a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1328a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1329c7b6f54bSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1330a4fd3ec3SEmilio G. Cota 
1331c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1332c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1333c7b6f54bSRichard Henderson     }
13341ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
133524c32852SRichard Henderson 
13368000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
13378000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
13388000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
13398000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
13408000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
13418000ba56SRichard Henderson      */
13428000ba56SRichard Henderson     if (dc->delayed_branch
13438000ba56SRichard Henderson         && --dc->delayed_branch == 0
13448000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
13458000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1346fcf5ef2aSThomas Huth     }
1347a4fd3ec3SEmilio G. Cota }
1348fcf5ef2aSThomas Huth 
1349a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1350a4fd3ec3SEmilio G. Cota {
1351a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
13528000ba56SRichard Henderson     target_ulong jmp_dest;
135324c32852SRichard Henderson 
1354e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1355e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1356e0a369cfSRichard Henderson         return;
1357e0a369cfSRichard Henderson     }
1358e0a369cfSRichard Henderson 
13598000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1360a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1361a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1362a01deb36SRichard Henderson     }
1363a01deb36SRichard Henderson 
13648000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
13658000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
13668000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
13678000ba56SRichard Henderson 
13681ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
13698000ba56SRichard Henderson     case DISAS_JUMP:
13708000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
13718000ba56SRichard Henderson         if (jmp_dest == -1) {
13728000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
13738000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
13748000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
13758000ba56SRichard Henderson             if (unlikely(dc->base.singlestep_enabled)) {
13768000ba56SRichard Henderson                 gen_exception(dc, EXCP_DEBUG);
13778000ba56SRichard Henderson             } else {
13788000ba56SRichard Henderson                 tcg_gen_lookup_and_goto_ptr();
13798000ba56SRichard Henderson             }
1380fcf5ef2aSThomas Huth             break;
13818000ba56SRichard Henderson         }
13828000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
13838000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
13848000ba56SRichard Henderson            we know now that it wasn't needed.  */
13858000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
13868000ba56SRichard Henderson         /* fallthru */
13878000ba56SRichard Henderson 
13888000ba56SRichard Henderson     case DISAS_TOO_MANY:
13898000ba56SRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
13908000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13918000ba56SRichard Henderson             gen_exception(dc, EXCP_DEBUG);
13928000ba56SRichard Henderson         } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
13938000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13948000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
13958000ba56SRichard Henderson         } else {
13968000ba56SRichard Henderson             tcg_gen_goto_tb(0);
13978000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13988000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
13998000ba56SRichard Henderson         }
14008000ba56SRichard Henderson         break;
14018000ba56SRichard Henderson 
140264e46c95SRichard Henderson     case DISAS_EXIT:
1403e0a369cfSRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
1404e0a369cfSRichard Henderson             gen_exception(dc, EXCP_DEBUG);
1405e0a369cfSRichard Henderson         } else {
140607ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
1407e0a369cfSRichard Henderson         }
1408fcf5ef2aSThomas Huth         break;
1409a4fd3ec3SEmilio G. Cota     default:
1410a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1411a4fd3ec3SEmilio G. Cota     }
1412fcf5ef2aSThomas Huth }
1413fcf5ef2aSThomas Huth 
1414a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1415a4fd3ec3SEmilio G. Cota {
1416a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
1417fcf5ef2aSThomas Huth 
1418a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1419a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1420fcf5ef2aSThomas Huth }
1421a4fd3ec3SEmilio G. Cota 
1422a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1423a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1424a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1425a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1426a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1427a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1428a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1429a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1430a4fd3ec3SEmilio G. Cota };
1431a4fd3ec3SEmilio G. Cota 
14328b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1433a4fd3ec3SEmilio G. Cota {
1434a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1435a4fd3ec3SEmilio G. Cota 
14368b86d6d2SRichard Henderson     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
1437fcf5ef2aSThomas Huth }
1438fcf5ef2aSThomas Huth 
143990c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1440fcf5ef2aSThomas Huth {
1441fcf5ef2aSThomas Huth     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1442fcf5ef2aSThomas Huth     CPUOpenRISCState *env = &cpu->env;
1443fcf5ef2aSThomas Huth     int i;
1444fcf5ef2aSThomas Huth 
144590c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1446fcf5ef2aSThomas Huth     for (i = 0; i < 32; ++i) {
144790c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1448fcf5ef2aSThomas Huth                      (i % 4) == 3 ? '\n' : ' ');
1449fcf5ef2aSThomas Huth     }
1450fcf5ef2aSThomas Huth }
1451fcf5ef2aSThomas Huth 
1452fcf5ef2aSThomas Huth void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1453fcf5ef2aSThomas Huth                           target_ulong *data)
1454fcf5ef2aSThomas Huth {
1455fcf5ef2aSThomas Huth     env->pc = data[0];
1456a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1457a01deb36SRichard Henderson     if (data[1] & 2) {
145824c32852SRichard Henderson         env->ppc = env->pc - 4;
145924c32852SRichard Henderson     }
1460fcf5ef2aSThomas Huth }
1461