xref: /qemu/target/openrisc/translate.c (revision fe636d3722bf266c7b1bd3ca12fa53fb78ceffa0)
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"
261de7afc9SPaolo Bonzini #include "qemu/log.h"
271de7afc9SPaolo Bonzini #include "qemu/bitops.h"
2890c84c56SMarkus Armbruster #include "qemu/qemu-print.h"
29f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
3077fc6f5eSLluís Vilanova #include "exec/translator.h"
31bbe418f2SJia Liu 
322ef6175aSRichard Henderson #include "exec/helper-proto.h"
332ef6175aSRichard Henderson #include "exec/helper-gen.h"
347de9729fSRichard Henderson #include "exec/gen-icount.h"
35e67db06eSJia Liu 
36a7e30d84SLluís Vilanova #include "trace-tcg.h"
37508127e2SPaolo Bonzini #include "exec/log.h"
38a7e30d84SLluís Vilanova 
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 
43bbe418f2SJia Liu typedef struct DisasContext {
441ffa4bceSEmilio G. Cota     DisasContextBase base;
45bbe418f2SJia Liu     uint32_t mem_idx;
46a01deb36SRichard Henderson     uint32_t tb_flags;
47bbe418f2SJia Liu     uint32_t delayed_branch;
48*fe636d37SRichard Henderson     uint32_t cpucfgr;
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;
52d29f4368SRichard Henderson 
53d29f4368SRichard Henderson     /* The temporary corresponding to register 0 for this compilation.  */
54d29f4368SRichard Henderson     TCGv R0;
55bbe418f2SJia Liu } DisasContext;
56bbe418f2SJia Liu 
572ba65417SRichard Henderson static inline bool is_user(DisasContext *dc)
582ba65417SRichard Henderson {
592ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY
602ba65417SRichard Henderson     return true;
612ba65417SRichard Henderson #else
62b9bed1b9SRichard Henderson     return !(dc->tb_flags & TB_FLAGS_SM);
632ba65417SRichard Henderson #endif
642ba65417SRichard Henderson }
652ba65417SRichard Henderson 
667de9729fSRichard Henderson /* Include the auto-generated decoder.  */
677de9729fSRichard Henderson #include "decode.inc.c"
687de9729fSRichard Henderson 
69bbe418f2SJia Liu static TCGv cpu_sr;
708bba7619SRichard Henderson static TCGv cpu_regs[32];
71bbe418f2SJia Liu static TCGv cpu_pc;
72bbe418f2SJia Liu static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
73bbe418f2SJia Liu static TCGv cpu_ppc;
7484775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
7597458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
7697458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
77930c3d00SRichard Henderson static TCGv cpu_lock_addr;
78930c3d00SRichard Henderson static TCGv cpu_lock_value;
79bbe418f2SJia Liu static TCGv_i32 fpcsr;
806f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
81a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
82bbe418f2SJia Liu 
83e67db06eSJia Liu void openrisc_translate_init(void)
84e67db06eSJia Liu {
85bbe418f2SJia Liu     static const char * const regnames[] = {
86bbe418f2SJia Liu         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
87bbe418f2SJia Liu         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
88bbe418f2SJia Liu         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
89bbe418f2SJia Liu         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
90bbe418f2SJia Liu     };
91bbe418f2SJia Liu     int i;
92bbe418f2SJia Liu 
93e1ccc054SRichard Henderson     cpu_sr = tcg_global_mem_new(cpu_env,
94bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, sr), "sr");
95a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
96a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
97a01deb36SRichard Henderson                                        "dflag");
98e1ccc054SRichard Henderson     cpu_pc = tcg_global_mem_new(cpu_env,
99bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, pc), "pc");
100e1ccc054SRichard Henderson     cpu_ppc = tcg_global_mem_new(cpu_env,
101bbe418f2SJia Liu                                  offsetof(CPUOpenRISCState, ppc), "ppc");
102e1ccc054SRichard Henderson     jmp_pc = tcg_global_mem_new(cpu_env,
103bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
10484775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
10584775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
10697458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
10797458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
10897458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
10997458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
110930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
111930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
112930c3d00SRichard Henderson                                        "lock_addr");
113930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
114930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
115930c3d00SRichard Henderson                                         "lock_value");
116e1ccc054SRichard Henderson     fpcsr = tcg_global_mem_new_i32(cpu_env,
117bbe418f2SJia Liu                                    offsetof(CPUOpenRISCState, fpcsr),
118bbe418f2SJia Liu                                    "fpcsr");
1196f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1206f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1216f7332baSRichard Henderson                                      "mac");
122bbe418f2SJia Liu     for (i = 0; i < 32; i++) {
1238bba7619SRichard Henderson         cpu_regs[i] = tcg_global_mem_new(cpu_env,
124d89e71e8SStafford Horne                                          offsetof(CPUOpenRISCState,
125d89e71e8SStafford Horne                                                   shadow_gpr[0][i]),
126bbe418f2SJia Liu                                          regnames[i]);
127bbe418f2SJia Liu     }
128bbe418f2SJia Liu }
129bbe418f2SJia Liu 
130bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp)
131bbe418f2SJia Liu {
132bbe418f2SJia Liu     TCGv_i32 tmp = tcg_const_i32(excp);
133bbe418f2SJia Liu     gen_helper_exception(cpu_env, tmp);
134bbe418f2SJia Liu     tcg_temp_free_i32(tmp);
135bbe418f2SJia Liu }
136bbe418f2SJia Liu 
137bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc)
138bbe418f2SJia Liu {
1391ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
140bbe418f2SJia Liu     gen_exception(dc, EXCP_ILLEGAL);
1411ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
142bbe418f2SJia Liu }
143bbe418f2SJia Liu 
144*fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc)
145bbe418f2SJia Liu {
146*fe636d37SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF32S;
147bbe418f2SJia Liu }
148bbe418f2SJia Liu 
1498bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg)
1508bba7619SRichard Henderson {
151d29f4368SRichard Henderson     if (reg == 0) {
152d29f4368SRichard Henderson         return dc->R0;
153d29f4368SRichard Henderson     } else {
1548bba7619SRichard Henderson         return cpu_regs[reg];
1558bba7619SRichard Henderson     }
156d29f4368SRichard Henderson }
1578bba7619SRichard Henderson 
158cdd0f459SRichard Henderson /*
159cdd0f459SRichard Henderson  * We're about to write to REG.  On the off-chance that the user is
160cdd0f459SRichard Henderson  * writing to R0, re-instate the architectural register.
161cdd0f459SRichard Henderson  */
162cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg)
163cdd0f459SRichard Henderson {
164cdd0f459SRichard Henderson     if (unlikely(reg == 0)) {
165d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
166cdd0f459SRichard Henderson     }
167cdd0f459SRichard Henderson }
1686597c28dSRichard Henderson 
16997458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1709ecaa27eSRichard Henderson {
1710c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
17297458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
1739ecaa27eSRichard Henderson     }
1740c53d734SRichard Henderson }
1759ecaa27eSRichard Henderson 
17697458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1779ecaa27eSRichard Henderson {
1780c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
17997458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
1809ecaa27eSRichard Henderson     }
1810c53d734SRichard Henderson }
1829ecaa27eSRichard Henderson 
18397458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1849ecaa27eSRichard Henderson {
1850c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
18697458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
1879ecaa27eSRichard Henderson     }
1880c53d734SRichard Henderson }
1899ecaa27eSRichard Henderson 
1909ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
1919ecaa27eSRichard Henderson {
1929ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
1939ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
1949ecaa27eSRichard Henderson 
19597458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
19697458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
1979ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
19897458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
1999ecaa27eSRichard Henderson     tcg_temp_free(t0);
2009ecaa27eSRichard Henderson 
2019ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2029ecaa27eSRichard Henderson     tcg_temp_free(res);
2039ecaa27eSRichard Henderson 
20497458071SRichard Henderson     gen_ove_cyov(dc);
2059ecaa27eSRichard Henderson }
2069ecaa27eSRichard Henderson 
2079ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2089ecaa27eSRichard Henderson {
2099ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2109ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2119ecaa27eSRichard Henderson 
21297458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
21397458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
21497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2159ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
21697458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2179ecaa27eSRichard Henderson     tcg_temp_free(t0);
2189ecaa27eSRichard Henderson 
2199ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2209ecaa27eSRichard Henderson     tcg_temp_free(res);
2219ecaa27eSRichard Henderson 
22297458071SRichard Henderson     gen_ove_cyov(dc);
2239ecaa27eSRichard Henderson }
2249ecaa27eSRichard Henderson 
2259ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2269ecaa27eSRichard Henderson {
2279ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2289ecaa27eSRichard Henderson 
2299ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
23097458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
23197458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
23297458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
23397458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2349ecaa27eSRichard Henderson 
2359ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2369ecaa27eSRichard Henderson     tcg_temp_free(res);
2379ecaa27eSRichard Henderson 
23897458071SRichard Henderson     gen_ove_cyov(dc);
2399ecaa27eSRichard Henderson }
2409ecaa27eSRichard Henderson 
2419ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2429ecaa27eSRichard Henderson {
2439ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2449ecaa27eSRichard Henderson 
24597458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2469ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
24797458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2489ecaa27eSRichard Henderson     tcg_temp_free(t0);
2499ecaa27eSRichard Henderson 
25097458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
25197458071SRichard Henderson     gen_ove_ov(dc);
2529ecaa27eSRichard Henderson }
2539ecaa27eSRichard Henderson 
2549ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2559ecaa27eSRichard Henderson {
25697458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
25797458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2589ecaa27eSRichard Henderson 
25997458071SRichard Henderson     gen_ove_cy(dc);
2609ecaa27eSRichard Henderson }
2619ecaa27eSRichard Henderson 
2629ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2639ecaa27eSRichard Henderson {
2649ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2659ecaa27eSRichard Henderson 
26697458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2679ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2689ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
26997458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2709ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2719ecaa27eSRichard Henderson     tcg_temp_free(t0);
2729ecaa27eSRichard Henderson 
27397458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
27497458071SRichard Henderson     gen_ove_ov(dc);
2759ecaa27eSRichard Henderson }
2769ecaa27eSRichard Henderson 
2779ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2789ecaa27eSRichard Henderson {
2799ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2809ecaa27eSRichard Henderson 
28197458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2829ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2839ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
28497458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2859ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2869ecaa27eSRichard Henderson     tcg_temp_free(t0);
2879ecaa27eSRichard Henderson 
28897458071SRichard Henderson     gen_ove_cy(dc);
2899ecaa27eSRichard Henderson }
290da1d7759SSebastian Macke 
291cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
292cc5de49eSRichard Henderson {
293cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
294cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
295cc5de49eSRichard Henderson 
296cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
297cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
298cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
299cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
300cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
301cc5de49eSRichard Henderson     } else {
302cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
303cc5de49eSRichard Henderson 
304cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
305cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
306cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
307cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
308cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
309cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
310cc5de49eSRichard Henderson 
311cc5de49eSRichard Henderson         gen_ove_ov(dc);
312cc5de49eSRichard Henderson     }
313cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
314cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
315cc5de49eSRichard Henderson }
316cc5de49eSRichard Henderson 
317cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
318cc5de49eSRichard Henderson {
319cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
320cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
321cc5de49eSRichard Henderson 
322cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
323cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
324cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
325cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
326cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
327cc5de49eSRichard Henderson     } else {
328cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
329cc5de49eSRichard Henderson 
330cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
331cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
332cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
333cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
334cc5de49eSRichard Henderson 
335cc5de49eSRichard Henderson         gen_ove_cy(dc);
336cc5de49eSRichard Henderson     }
337cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
338cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
339cc5de49eSRichard Henderson }
340cc5de49eSRichard Henderson 
3416f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3426f7332baSRichard Henderson {
3436f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3446f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3456f7332baSRichard Henderson 
3466f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3476f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3486f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3496f7332baSRichard Henderson 
3506f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3516f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3526f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3536f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3546f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3556f7332baSRichard Henderson     tcg_temp_free_i64(t2);
3566f7332baSRichard Henderson 
3576f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3586f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3596f7332baSRichard Henderson #else
3606f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3616f7332baSRichard Henderson #endif
3626f7332baSRichard Henderson     tcg_temp_free_i64(t1);
3636f7332baSRichard Henderson 
3646f7332baSRichard Henderson     gen_ove_ov(dc);
3656f7332baSRichard Henderson }
3666f7332baSRichard Henderson 
367cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
368cc5de49eSRichard Henderson {
369cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
370cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
371cc5de49eSRichard Henderson 
372cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
373cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
374cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
375cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
376cc5de49eSRichard Henderson 
377cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
378cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
379cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
380cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
381cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
382cc5de49eSRichard Henderson 
383cc5de49eSRichard Henderson     gen_ove_cy(dc);
384cc5de49eSRichard Henderson }
385cc5de49eSRichard Henderson 
3866f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
3876f7332baSRichard Henderson {
3886f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3896f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3906f7332baSRichard Henderson 
3916f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3926f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3936f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3946f7332baSRichard Henderson 
3956f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
3966f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3976f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
3986f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3996f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4006f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4016f7332baSRichard Henderson 
4026f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4036f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4046f7332baSRichard Henderson #else
4056f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4066f7332baSRichard Henderson #endif
4076f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4086f7332baSRichard Henderson 
4096f7332baSRichard Henderson     gen_ove_ov(dc);
4106f7332baSRichard Henderson }
4116f7332baSRichard Henderson 
412cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
413cc5de49eSRichard Henderson {
414cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
415cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
416cc5de49eSRichard Henderson 
417cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
418cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
419cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
420cc5de49eSRichard Henderson 
421cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
422cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
423cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
424cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
425cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
426cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
427cc5de49eSRichard Henderson 
428cc5de49eSRichard Henderson     gen_ove_cy(dc);
429cc5de49eSRichard Henderson }
430cc5de49eSRichard Henderson 
4313a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
432bbe418f2SJia Liu {
433cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4348bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4356ad216abSRichard Henderson     return true;
436bbe418f2SJia Liu }
437bbe418f2SJia Liu 
4383a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
439bbe418f2SJia Liu {
440cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4418bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4426ad216abSRichard Henderson     return true;
4436ad216abSRichard Henderson }
4446ad216abSRichard Henderson 
4453a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4466ad216abSRichard Henderson {
447cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4488bba7619SRichard Henderson     gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4496ad216abSRichard Henderson     return true;
4506ad216abSRichard Henderson }
4516ad216abSRichard Henderson 
4523a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4536ad216abSRichard Henderson {
454cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4558bba7619SRichard Henderson     tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4566ad216abSRichard Henderson     return true;
4576ad216abSRichard Henderson }
4586ad216abSRichard Henderson 
4593a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4606ad216abSRichard Henderson {
461cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4628bba7619SRichard Henderson     tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4636ad216abSRichard Henderson     return true;
4646ad216abSRichard Henderson }
4656ad216abSRichard Henderson 
4663a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4676ad216abSRichard Henderson {
468cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4698bba7619SRichard Henderson     tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4706ad216abSRichard Henderson     return true;
4716ad216abSRichard Henderson }
4726ad216abSRichard Henderson 
4733a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4746ad216abSRichard Henderson {
475cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4768bba7619SRichard Henderson     tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4776ad216abSRichard Henderson     return true;
4786ad216abSRichard Henderson }
4796ad216abSRichard Henderson 
4803a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4816ad216abSRichard Henderson {
482cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4838bba7619SRichard Henderson     tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4846ad216abSRichard Henderson     return true;
4856ad216abSRichard Henderson }
4866ad216abSRichard Henderson 
4873a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
4886ad216abSRichard Henderson {
489cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4908bba7619SRichard Henderson     tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4916ad216abSRichard Henderson     return true;
4926ad216abSRichard Henderson }
4936ad216abSRichard Henderson 
4943a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
4956ad216abSRichard Henderson {
496cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4978bba7619SRichard Henderson     tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4986ad216abSRichard Henderson     return true;
4996ad216abSRichard Henderson }
5006ad216abSRichard Henderson 
5013a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
5026ad216abSRichard Henderson {
503cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5048bba7619SRichard Henderson     tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5056ad216abSRichard Henderson     return true;
5066ad216abSRichard Henderson }
5076ad216abSRichard Henderson 
5083a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
5096ad216abSRichard Henderson {
510cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5118bba7619SRichard Henderson     tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5126ad216abSRichard Henderson     return true;
5136ad216abSRichard Henderson }
5146ad216abSRichard Henderson 
5153a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5166ad216abSRichard Henderson {
517cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5188bba7619SRichard Henderson     tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5196ad216abSRichard Henderson     return true;
5206ad216abSRichard Henderson }
5216ad216abSRichard Henderson 
5223a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5236ad216abSRichard Henderson {
524cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5258bba7619SRichard Henderson     tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5266ad216abSRichard Henderson     return true;
5276ad216abSRichard Henderson }
5286ad216abSRichard Henderson 
5293a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5306ad216abSRichard Henderson {
5316ad216abSRichard Henderson     TCGv zero;
5326ad216abSRichard Henderson 
533cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5346ad216abSRichard Henderson     zero = tcg_const_tl(0);
5358bba7619SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero,
5368bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
537784696d1SRichard Henderson     tcg_temp_free(zero);
5386ad216abSRichard Henderson     return true;
539bbe418f2SJia Liu }
540bbe418f2SJia Liu 
5413a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5426ad216abSRichard Henderson {
543cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5448bba7619SRichard Henderson     tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
5458bba7619SRichard Henderson     tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
5466ad216abSRichard Henderson     return true;
547cf2ae442SRichard Henderson }
548cf2ae442SRichard Henderson 
5493a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5506ad216abSRichard Henderson {
551cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5528bba7619SRichard Henderson     tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
5538bba7619SRichard Henderson     tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
5546ad216abSRichard Henderson     return true;
555bbe418f2SJia Liu }
556bbe418f2SJia Liu 
5573a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5586ad216abSRichard Henderson {
559cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5608bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5616ad216abSRichard Henderson     return true;
562bbe418f2SJia Liu }
5636ad216abSRichard Henderson 
5643a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5656ad216abSRichard Henderson {
566cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5678bba7619SRichard Henderson     gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5686ad216abSRichard Henderson     return true;
569bbe418f2SJia Liu }
5706ad216abSRichard Henderson 
5713a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5726ad216abSRichard Henderson {
573cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5748bba7619SRichard Henderson     gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5756ad216abSRichard Henderson     return true;
5766ad216abSRichard Henderson }
5776ad216abSRichard Henderson 
5783a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5796ad216abSRichard Henderson {
580cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5818bba7619SRichard Henderson     gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5826ad216abSRichard Henderson     return true;
5836ad216abSRichard Henderson }
5846ad216abSRichard Henderson 
5853a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5866ad216abSRichard Henderson {
5878bba7619SRichard Henderson     gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5886ad216abSRichard Henderson     return true;
5896ad216abSRichard Henderson }
5906ad216abSRichard Henderson 
5913a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
5926ad216abSRichard Henderson {
5938bba7619SRichard Henderson     gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5946ad216abSRichard Henderson     return true;
595bbe418f2SJia Liu }
596bbe418f2SJia Liu 
5973a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
598136e13aeSRichard Henderson {
599136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
600136e13aeSRichard Henderson 
601136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
6028000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
603136e13aeSRichard Henderson     dc->delayed_branch = 2;
604136e13aeSRichard Henderson     return true;
605136e13aeSRichard Henderson }
606136e13aeSRichard Henderson 
6073a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
608136e13aeSRichard Henderson {
609136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
610136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
611136e13aeSRichard Henderson 
6128bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], ret_pc);
613136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
614136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
615136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6168000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
617136e13aeSRichard Henderson         dc->delayed_branch = 2;
618136e13aeSRichard Henderson     }
619136e13aeSRichard Henderson     return true;
620136e13aeSRichard Henderson }
621136e13aeSRichard Henderson 
622136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
623136e13aeSRichard Henderson {
624136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
625136e13aeSRichard Henderson     TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
626136e13aeSRichard Henderson     TCGv t_true = tcg_const_tl(tmp_pc);
627136e13aeSRichard Henderson     TCGv t_zero = tcg_const_tl(0);
628136e13aeSRichard Henderson 
629136e13aeSRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
630136e13aeSRichard Henderson 
631136e13aeSRichard Henderson     tcg_temp_free(t_next);
632136e13aeSRichard Henderson     tcg_temp_free(t_true);
633136e13aeSRichard Henderson     tcg_temp_free(t_zero);
634136e13aeSRichard Henderson     dc->delayed_branch = 2;
635136e13aeSRichard Henderson }
636136e13aeSRichard Henderson 
6373a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
638136e13aeSRichard Henderson {
639136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
640136e13aeSRichard Henderson     return true;
641136e13aeSRichard Henderson }
642136e13aeSRichard Henderson 
6433a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
644136e13aeSRichard Henderson {
645136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
646136e13aeSRichard Henderson     return true;
647136e13aeSRichard Henderson }
648136e13aeSRichard Henderson 
6493a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
650136e13aeSRichard Henderson {
6518bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
652136e13aeSRichard Henderson     dc->delayed_branch = 2;
653136e13aeSRichard Henderson     return true;
654136e13aeSRichard Henderson }
655136e13aeSRichard Henderson 
6563a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
657136e13aeSRichard Henderson {
6588bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
6598bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
660136e13aeSRichard Henderson     dc->delayed_branch = 2;
661136e13aeSRichard Henderson     return true;
662136e13aeSRichard Henderson }
663136e13aeSRichard Henderson 
6643a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
665d80bff19SRichard Henderson {
666d80bff19SRichard Henderson     TCGv ea;
667d80bff19SRichard Henderson 
668cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
669d80bff19SRichard Henderson     ea = tcg_temp_new();
6708bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6718bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
672d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
6738bba7619SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
674d80bff19SRichard Henderson     tcg_temp_free(ea);
675d80bff19SRichard Henderson     return true;
676d80bff19SRichard Henderson }
677d80bff19SRichard Henderson 
67814776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
679d80bff19SRichard Henderson {
680d80bff19SRichard Henderson     TCGv ea;
681d80bff19SRichard Henderson 
682cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
683d80bff19SRichard Henderson     ea = tcg_temp_new();
6848bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6858bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
686d80bff19SRichard Henderson     tcg_temp_free(ea);
687d80bff19SRichard Henderson }
688d80bff19SRichard Henderson 
6893a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
690d80bff19SRichard Henderson {
691d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
692d80bff19SRichard Henderson     return true;
693d80bff19SRichard Henderson }
694d80bff19SRichard Henderson 
6953a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
696d80bff19SRichard Henderson {
697d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
698d80bff19SRichard Henderson     return true;
699d80bff19SRichard Henderson }
700d80bff19SRichard Henderson 
7013a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
702d80bff19SRichard Henderson {
703d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
704d80bff19SRichard Henderson     return true;
705d80bff19SRichard Henderson }
706d80bff19SRichard Henderson 
7073a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
708d80bff19SRichard Henderson {
709d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
710d80bff19SRichard Henderson     return true;
711d80bff19SRichard Henderson }
712d80bff19SRichard Henderson 
7133a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
714d80bff19SRichard Henderson {
715d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
716d80bff19SRichard Henderson     return true;
717d80bff19SRichard Henderson }
718d80bff19SRichard Henderson 
7193a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
720d80bff19SRichard Henderson {
721d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
722d80bff19SRichard Henderson     return true;
723d80bff19SRichard Henderson }
724d80bff19SRichard Henderson 
7253a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
726d80bff19SRichard Henderson {
727d80bff19SRichard Henderson     TCGv ea, val;
728d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
729d80bff19SRichard Henderson 
730d80bff19SRichard Henderson     ea = tcg_temp_new();
7318bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
732d80bff19SRichard Henderson 
733d80bff19SRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
7348bba7619SRichard Henderson        to cpu_regs[0].  Since l.swa is quite often immediately followed by a
735d80bff19SRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
736d80bff19SRichard Henderson        This also takes care of RB input across the branch.  */
737d29f4368SRichard Henderson     dc->R0 = cpu_regs[0];
738d80bff19SRichard Henderson 
739d80bff19SRichard Henderson     lab_fail = gen_new_label();
740d80bff19SRichard Henderson     lab_done = gen_new_label();
741d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
742d80bff19SRichard Henderson     tcg_temp_free(ea);
743d80bff19SRichard Henderson 
744d80bff19SRichard Henderson     val = tcg_temp_new();
745d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
7468bba7619SRichard Henderson                               cpu_regs[a->b], dc->mem_idx, MO_TEUL);
747d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
748d80bff19SRichard Henderson     tcg_temp_free(val);
749d80bff19SRichard Henderson 
750d80bff19SRichard Henderson     tcg_gen_br(lab_done);
751d80bff19SRichard Henderson 
752d80bff19SRichard Henderson     gen_set_label(lab_fail);
753d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
754d80bff19SRichard Henderson 
755d80bff19SRichard Henderson     gen_set_label(lab_done);
756d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
757d80bff19SRichard Henderson     return true;
758d80bff19SRichard Henderson }
759d80bff19SRichard Henderson 
76014776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
761d80bff19SRichard Henderson {
762d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
7638bba7619SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
7648bba7619SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
765d80bff19SRichard Henderson     tcg_temp_free(t0);
766d80bff19SRichard Henderson }
767d80bff19SRichard Henderson 
7683a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
769d80bff19SRichard Henderson {
770d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
771d80bff19SRichard Henderson     return true;
772d80bff19SRichard Henderson }
773d80bff19SRichard Henderson 
7743a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
775d80bff19SRichard Henderson {
776d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
777d80bff19SRichard Henderson     return true;
778d80bff19SRichard Henderson }
779d80bff19SRichard Henderson 
7803a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
781d80bff19SRichard Henderson {
782d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
783d80bff19SRichard Henderson     return true;
784d80bff19SRichard Henderson }
785d80bff19SRichard Henderson 
7863a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
787bbe418f2SJia Liu {
7888816f70bSRichard Henderson     return true;
7898816f70bSRichard Henderson }
7908816f70bSRichard Henderson 
7913a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
7928816f70bSRichard Henderson {
7939ecaa27eSRichard Henderson     TCGv t0;
7945631e69cSRichard Henderson 
795cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
7968816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
7978bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
7986f7332baSRichard Henderson     tcg_temp_free(t0);
7998816f70bSRichard Henderson     return true;
8008816f70bSRichard Henderson }
801bbe418f2SJia Liu 
8023a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
803bbe418f2SJia Liu {
8048816f70bSRichard Henderson     TCGv t0;
8058816f70bSRichard Henderson 
806cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8078816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8088bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8098816f70bSRichard Henderson     tcg_temp_free(t0);
8108816f70bSRichard Henderson     return true;
8118816f70bSRichard Henderson }
8128816f70bSRichard Henderson 
8133a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
8148816f70bSRichard Henderson {
8158816f70bSRichard Henderson     TCGv t0;
8168816f70bSRichard Henderson 
817cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8188816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8198bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8208816f70bSRichard Henderson     tcg_temp_free(t0);
8218816f70bSRichard Henderson     return true;
8228816f70bSRichard Henderson }
8238816f70bSRichard Henderson 
8243a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
8258816f70bSRichard Henderson {
8268816f70bSRichard Henderson     TCGv t0;
8278816f70bSRichard Henderson 
8288816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8298bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), t0);
8308816f70bSRichard Henderson     tcg_temp_free(t0);
8318816f70bSRichard Henderson     return true;
8328816f70bSRichard Henderson }
8338816f70bSRichard Henderson 
8343a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8358816f70bSRichard Henderson {
836cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8378bba7619SRichard Henderson     tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8388816f70bSRichard Henderson     return true;
8398816f70bSRichard Henderson }
8408816f70bSRichard Henderson 
8413a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8428816f70bSRichard Henderson {
843cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8448bba7619SRichard Henderson     tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8458816f70bSRichard Henderson     return true;
8468816f70bSRichard Henderson }
8478816f70bSRichard Henderson 
8483a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8498816f70bSRichard Henderson {
850cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8518bba7619SRichard Henderson     tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
8528816f70bSRichard Henderson     return true;
8538816f70bSRichard Henderson }
8548816f70bSRichard Henderson 
8553a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8568816f70bSRichard Henderson {
857cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8588816f70bSRichard Henderson 
8592ba65417SRichard Henderson     if (is_user(dc)) {
860bbe418f2SJia Liu         gen_illegal_exception(dc);
8618816f70bSRichard Henderson     } else {
862c28fa81fSRichard Henderson         TCGv spr = tcg_temp_new();
8638bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
8648bba7619SRichard Henderson         gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
865c28fa81fSRichard Henderson         tcg_temp_free(spr);
8664dd044c6SJia Liu     }
8678816f70bSRichard Henderson     return true;
8688816f70bSRichard Henderson }
869bbe418f2SJia Liu 
8703a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
8714dd044c6SJia Liu {
8722ba65417SRichard Henderson     if (is_user(dc)) {
8734dd044c6SJia Liu         gen_illegal_exception(dc);
8748816f70bSRichard Henderson     } else {
875c28fa81fSRichard Henderson         TCGv spr;
87601ec3ec9SRichard Henderson 
87701ec3ec9SRichard Henderson         /* For SR, we will need to exit the TB to recognize the new
87801ec3ec9SRichard Henderson          * exception state.  For NPC, in theory this counts as a branch
87901ec3ec9SRichard Henderson          * (although the SPR only exists for use by an ICE).  Save all
88001ec3ec9SRichard Henderson          * of the cpu state first, allowing it to be overwritten.
88101ec3ec9SRichard Henderson          */
88201ec3ec9SRichard Henderson         if (dc->delayed_branch) {
88301ec3ec9SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
88401ec3ec9SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
88501ec3ec9SRichard Henderson         } else {
88601ec3ec9SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
88701ec3ec9SRichard Henderson         }
88801ec3ec9SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
88901ec3ec9SRichard Henderson 
890c28fa81fSRichard Henderson         spr = tcg_temp_new();
8918bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
8928bba7619SRichard Henderson         gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b));
893c28fa81fSRichard Henderson         tcg_temp_free(spr);
8944dd044c6SJia Liu     }
8958816f70bSRichard Henderson     return true;
896bbe418f2SJia Liu }
897bbe418f2SJia Liu 
8983a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
899bbe418f2SJia Liu {
9008bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
90199d863d6SRichard Henderson     return true;
902bbe418f2SJia Liu }
90399d863d6SRichard Henderson 
9043a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
90599d863d6SRichard Henderson {
9068bba7619SRichard Henderson     gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
90799d863d6SRichard Henderson     return true;
90899d863d6SRichard Henderson }
90999d863d6SRichard Henderson 
9103a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
91199d863d6SRichard Henderson {
9128bba7619SRichard Henderson     gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
91399d863d6SRichard Henderson     return true;
91499d863d6SRichard Henderson }
91599d863d6SRichard Henderson 
9163a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
91799d863d6SRichard Henderson {
9188bba7619SRichard Henderson     gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
91999d863d6SRichard Henderson     return true;
920bbe418f2SJia Liu }
921bbe418f2SJia Liu 
9223a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
923bbe418f2SJia Liu {
924cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9258bba7619SRichard Henderson     tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9268bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
927e20c2592SRichard Henderson     return true;
928bbe418f2SJia Liu }
929e20c2592SRichard Henderson 
9303a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
931e20c2592SRichard Henderson {
932cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9338bba7619SRichard Henderson     tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9348bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
935e20c2592SRichard Henderson     return true;
936e20c2592SRichard Henderson }
937e20c2592SRichard Henderson 
9383a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
939e20c2592SRichard Henderson {
940cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9418bba7619SRichard Henderson     tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9428bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
943e20c2592SRichard Henderson     return true;
944e20c2592SRichard Henderson }
945e20c2592SRichard Henderson 
9463a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
947e20c2592SRichard Henderson {
948cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9498bba7619SRichard Henderson     tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9508bba7619SRichard Henderson                      a->l & (TARGET_LONG_BITS - 1));
951e20c2592SRichard Henderson     return true;
952bbe418f2SJia Liu }
953bbe418f2SJia Liu 
9543a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
955bbe418f2SJia Liu {
956cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9578bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
958e720a571SRichard Henderson     return true;
959bbe418f2SJia Liu }
960e720a571SRichard Henderson 
9613a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
962e720a571SRichard Henderson {
963cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9648bba7619SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
965e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
966e720a571SRichard Henderson     return true;
967bbe418f2SJia Liu }
968bbe418f2SJia Liu 
9693a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
970bbe418f2SJia Liu {
9718bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
9728bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
973fbb3e29aSRichard Henderson     return true;
974bbe418f2SJia Liu }
975fbb3e29aSRichard Henderson 
9763a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
977fbb3e29aSRichard Henderson {
9788bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
9798bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
980fbb3e29aSRichard Henderson     return true;
981fbb3e29aSRichard Henderson }
982fbb3e29aSRichard Henderson 
9833a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
984fbb3e29aSRichard Henderson {
9858bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
9868bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
987fbb3e29aSRichard Henderson     return true;
988fbb3e29aSRichard Henderson }
989fbb3e29aSRichard Henderson 
9903a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
991fbb3e29aSRichard Henderson {
9928bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
9938bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
994fbb3e29aSRichard Henderson     return true;
995fbb3e29aSRichard Henderson }
996fbb3e29aSRichard Henderson 
9973a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
998fbb3e29aSRichard Henderson {
9998bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
10008bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1001fbb3e29aSRichard Henderson     return true;
1002fbb3e29aSRichard Henderson }
1003fbb3e29aSRichard Henderson 
10043a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
1005fbb3e29aSRichard Henderson {
10068bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
10078bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1008fbb3e29aSRichard Henderson     return true;
1009fbb3e29aSRichard Henderson }
1010fbb3e29aSRichard Henderson 
10113a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
1012fbb3e29aSRichard Henderson {
10138bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
10148bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1015fbb3e29aSRichard Henderson     return true;
1016fbb3e29aSRichard Henderson }
1017fbb3e29aSRichard Henderson 
10183a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
1019fbb3e29aSRichard Henderson {
10208bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
10218bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1022fbb3e29aSRichard Henderson     return true;
1023fbb3e29aSRichard Henderson }
1024fbb3e29aSRichard Henderson 
10253a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
1026fbb3e29aSRichard Henderson {
10278bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
10288bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1029fbb3e29aSRichard Henderson     return true;
1030fbb3e29aSRichard Henderson }
1031fbb3e29aSRichard Henderson 
10323a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1033fbb3e29aSRichard Henderson {
10348bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE,
10358bba7619SRichard Henderson                        cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1036fbb3e29aSRichard Henderson     return true;
1037bbe418f2SJia Liu }
1038bbe418f2SJia Liu 
10393a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1040bbe418f2SJia Liu {
10418bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1042032de4fcSRichard Henderson     return true;
1043bbe418f2SJia Liu }
1044032de4fcSRichard Henderson 
10453a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1046032de4fcSRichard Henderson {
10478bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1048032de4fcSRichard Henderson     return true;
1049032de4fcSRichard Henderson }
1050032de4fcSRichard Henderson 
10513a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1052032de4fcSRichard Henderson {
10538bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1054032de4fcSRichard Henderson     return true;
1055032de4fcSRichard Henderson }
1056032de4fcSRichard Henderson 
10573a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1058032de4fcSRichard Henderson {
10598bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1060032de4fcSRichard Henderson     return true;
1061032de4fcSRichard Henderson }
1062032de4fcSRichard Henderson 
10633a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1064032de4fcSRichard Henderson {
10658bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1066032de4fcSRichard Henderson     return true;
1067032de4fcSRichard Henderson }
1068032de4fcSRichard Henderson 
10693a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1070032de4fcSRichard Henderson {
10718bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1072032de4fcSRichard Henderson     return true;
1073032de4fcSRichard Henderson }
1074032de4fcSRichard Henderson 
10753a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1076032de4fcSRichard Henderson {
10778bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1078032de4fcSRichard Henderson     return true;
1079032de4fcSRichard Henderson }
1080032de4fcSRichard Henderson 
10813a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1082032de4fcSRichard Henderson {
10838bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1084032de4fcSRichard Henderson     return true;
1085032de4fcSRichard Henderson }
1086032de4fcSRichard Henderson 
10873a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1088032de4fcSRichard Henderson {
10898bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1090032de4fcSRichard Henderson     return true;
1091032de4fcSRichard Henderson }
1092032de4fcSRichard Henderson 
10933a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1094032de4fcSRichard Henderson {
10958bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1096032de4fcSRichard Henderson     return true;
1097bbe418f2SJia Liu }
1098bbe418f2SJia Liu 
10993a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1100bbe418f2SJia Liu {
11011ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1102bbe418f2SJia Liu     gen_exception(dc, EXCP_SYSCALL);
11031ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11047de9729fSRichard Henderson     return true;
11057de9729fSRichard Henderson }
1106bbe418f2SJia Liu 
11073a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
11087de9729fSRichard Henderson {
11091ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1110bbe418f2SJia Liu     gen_exception(dc, EXCP_TRAP);
11111ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11127de9729fSRichard Henderson     return true;
11137de9729fSRichard Henderson }
1114bbe418f2SJia Liu 
11153a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
11167de9729fSRichard Henderson {
111724fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
11187de9729fSRichard Henderson     return true;
1119bbe418f2SJia Liu }
11207de9729fSRichard Henderson 
11213a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
11227de9729fSRichard Henderson {
11237de9729fSRichard Henderson     return true;
11247de9729fSRichard Henderson }
11257de9729fSRichard Henderson 
11263a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
11277de9729fSRichard Henderson {
11287de9729fSRichard Henderson     return true;
1129bbe418f2SJia Liu }
1130bbe418f2SJia Liu 
11313a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11328816f70bSRichard Henderson {
11332ba65417SRichard Henderson     if (is_user(dc)) {
11348816f70bSRichard Henderson         gen_illegal_exception(dc);
11358816f70bSRichard Henderson     } else {
11368816f70bSRichard Henderson         gen_helper_rfe(cpu_env);
113764e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11388816f70bSRichard Henderson     }
11398816f70bSRichard Henderson     return true;
11408816f70bSRichard Henderson }
11418816f70bSRichard Henderson 
1142*fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a,
11436fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1144bbe418f2SJia Liu {
1145*fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1146*fe636d37SRichard Henderson         return false;
1147*fe636d37SRichard Henderson     }
1148cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
11498bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a));
11504e2d3007SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1151*fe636d37SRichard Henderson     return true;
1152bbe418f2SJia Liu }
11536fd204a2SRichard Henderson 
1154*fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a,
11556fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11566fd204a2SRichard Henderson {
1157*fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1158*fe636d37SRichard Henderson         return false;
1159*fe636d37SRichard Henderson     }
1160cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
11618bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11626fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1163*fe636d37SRichard Henderson     return true;
11646fd204a2SRichard Henderson }
11656fd204a2SRichard Henderson 
1166*fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a,
11676fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11686fd204a2SRichard Henderson                      bool inv, bool swap)
11696fd204a2SRichard Henderson {
1170*fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1171*fe636d37SRichard Henderson         return false;
1172*fe636d37SRichard Henderson     }
11736fd204a2SRichard Henderson     if (swap) {
11748bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
11756fd204a2SRichard Henderson     } else {
11768bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11776fd204a2SRichard Henderson     }
11786fd204a2SRichard Henderson     if (inv) {
11796fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11806fd204a2SRichard Henderson     }
11816fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1182*fe636d37SRichard Henderson     return true;
11836fd204a2SRichard Henderson }
11846fd204a2SRichard Henderson 
11853a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11866fd204a2SRichard Henderson {
1187*fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_add_s);
11886fd204a2SRichard Henderson }
11896fd204a2SRichard Henderson 
11903a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11916fd204a2SRichard Henderson {
1192*fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_sub_s);
11936fd204a2SRichard Henderson }
11946fd204a2SRichard Henderson 
11953a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
11966fd204a2SRichard Henderson {
1197*fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_mul_s);
11986fd204a2SRichard Henderson }
11996fd204a2SRichard Henderson 
12003a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
12016fd204a2SRichard Henderson {
1202*fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_div_s);
12036fd204a2SRichard Henderson }
12046fd204a2SRichard Henderson 
12053a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
12066fd204a2SRichard Henderson {
1207*fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_rem_s);
12086fd204a2SRichard Henderson     return true;
12096fd204a2SRichard Henderson }
12106fd204a2SRichard Henderson 
12113a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
12126fd204a2SRichard Henderson {
1213*fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_itofs);
12146fd204a2SRichard Henderson }
12156fd204a2SRichard Henderson 
12163a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
12176fd204a2SRichard Henderson {
1218*fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_ftois);
12196fd204a2SRichard Henderson }
12206fd204a2SRichard Henderson 
12213a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
12226fd204a2SRichard Henderson {
1223*fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1224*fe636d37SRichard Henderson         return false;
1225*fe636d37SRichard Henderson     }
1226cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
12278bba7619SRichard Henderson     gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d),
12288bba7619SRichard Henderson                             cpu_R(dc, a->a), cpu_R(dc, a->b));
12296fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
12306fd204a2SRichard Henderson     return true;
12316fd204a2SRichard Henderson }
12326fd204a2SRichard Henderson 
12333a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12346fd204a2SRichard Henderson {
1235*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12366fd204a2SRichard Henderson }
12376fd204a2SRichard Henderson 
12383a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12396fd204a2SRichard Henderson {
1240*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12416fd204a2SRichard Henderson }
12426fd204a2SRichard Henderson 
12433a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12446fd204a2SRichard Henderson {
1245*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12466fd204a2SRichard Henderson }
12476fd204a2SRichard Henderson 
12483a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12496fd204a2SRichard Henderson {
1250*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12516fd204a2SRichard Henderson }
12526fd204a2SRichard Henderson 
12533a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12546fd204a2SRichard Henderson {
1255*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12566fd204a2SRichard Henderson }
12576fd204a2SRichard Henderson 
12583a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12596fd204a2SRichard Henderson {
1260*fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1261bbe418f2SJia Liu }
1262bbe418f2SJia Liu 
1263a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1264e67db06eSJia Liu {
1265a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
12669c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1267a4fd3ec3SEmilio G. Cota     int bound;
1268bbe418f2SJia Liu 
1269a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
12701ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1271a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1272*fe636d37SRichard Henderson     dc->cpucfgr = env->cpucfgr;
12738000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
12748000ba56SRichard Henderson 
1275a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1276a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1277190ce7fbSRichard Henderson }
1278bbe418f2SJia Liu 
1279a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1280a4fd3ec3SEmilio G. Cota {
1281a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1282bbe418f2SJia Liu 
12836597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
12846597c28dSRichard Henderson        when it's true, which is the common case.  */
12856597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1286d29f4368SRichard Henderson         dc->R0 = tcg_const_tl(0);
12876597c28dSRichard Henderson     } else {
1288d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
12896597c28dSRichard Henderson     }
1290a4fd3ec3SEmilio G. Cota }
12916597c28dSRichard Henderson 
1292a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1293a4fd3ec3SEmilio G. Cota {
1294a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1295a4fd3ec3SEmilio G. Cota 
12961ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1297a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1298a4fd3ec3SEmilio G. Cota }
1299bbe418f2SJia Liu 
1300a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1301a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1302a4fd3ec3SEmilio G. Cota {
1303a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1304a4fd3ec3SEmilio G. Cota 
13051ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1306b933066aSRichard Henderson     gen_exception(dc, EXCP_DEBUG);
13071ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1308522a0d4eSRichard Henderson     /* The address covered by the breakpoint must be included in
1309522a0d4eSRichard Henderson        [tb->pc, tb->pc + tb->size) in order to for it to be
1310522a0d4eSRichard Henderson        properly cleared -- thus we increment the PC here so that
1311522a0d4eSRichard Henderson        the logic setting tb->size below does the right thing.  */
13121ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1313a4fd3ec3SEmilio G. Cota     return true;
1314b933066aSRichard Henderson }
1315b933066aSRichard Henderson 
1316a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1317a4fd3ec3SEmilio G. Cota {
1318a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1319a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1320c7b6f54bSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1321a4fd3ec3SEmilio G. Cota 
1322c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1323c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1324c7b6f54bSRichard Henderson     }
13251ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
132624c32852SRichard Henderson 
13278000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
13288000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
13298000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
13308000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
13318000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
13328000ba56SRichard Henderson      */
13338000ba56SRichard Henderson     if (dc->delayed_branch
13348000ba56SRichard Henderson         && --dc->delayed_branch == 0
13358000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
13368000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1337bbe418f2SJia Liu     }
1338a4fd3ec3SEmilio G. Cota }
1339bbe418f2SJia Liu 
1340a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1341a4fd3ec3SEmilio G. Cota {
1342a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
13438000ba56SRichard Henderson     target_ulong jmp_dest;
134424c32852SRichard Henderson 
1345e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1346e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1347e0a369cfSRichard Henderson         return;
1348e0a369cfSRichard Henderson     }
1349e0a369cfSRichard Henderson 
13508000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1351a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1352a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1353a01deb36SRichard Henderson     }
1354a01deb36SRichard Henderson 
13558000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
13568000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
13578000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
13588000ba56SRichard Henderson 
13591ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
13608000ba56SRichard Henderson     case DISAS_JUMP:
13618000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
13628000ba56SRichard Henderson         if (jmp_dest == -1) {
13638000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
13648000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
13658000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
13668000ba56SRichard Henderson             if (unlikely(dc->base.singlestep_enabled)) {
13678000ba56SRichard Henderson                 gen_exception(dc, EXCP_DEBUG);
13688000ba56SRichard Henderson             } else {
13698000ba56SRichard Henderson                 tcg_gen_lookup_and_goto_ptr();
13708000ba56SRichard Henderson             }
1371bbe418f2SJia Liu             break;
13728000ba56SRichard Henderson         }
13738000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
13748000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
13758000ba56SRichard Henderson            we know now that it wasn't needed.  */
13768000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
13778000ba56SRichard Henderson         /* fallthru */
13788000ba56SRichard Henderson 
13798000ba56SRichard Henderson     case DISAS_TOO_MANY:
13808000ba56SRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
13818000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13828000ba56SRichard Henderson             gen_exception(dc, EXCP_DEBUG);
13838000ba56SRichard Henderson         } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
13848000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13858000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
13868000ba56SRichard Henderson         } else {
13878000ba56SRichard Henderson             tcg_gen_goto_tb(0);
13888000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
13898000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
13908000ba56SRichard Henderson         }
13918000ba56SRichard Henderson         break;
13928000ba56SRichard Henderson 
139364e46c95SRichard Henderson     case DISAS_EXIT:
1394e0a369cfSRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
1395e0a369cfSRichard Henderson             gen_exception(dc, EXCP_DEBUG);
1396e0a369cfSRichard Henderson         } else {
139707ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
1398e0a369cfSRichard Henderson         }
1399bbe418f2SJia Liu         break;
1400a4fd3ec3SEmilio G. Cota     default:
1401a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1402a4fd3ec3SEmilio G. Cota     }
1403bbe418f2SJia Liu }
1404bbe418f2SJia Liu 
1405a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1406a4fd3ec3SEmilio G. Cota {
1407a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
14080a7df5daSRichard Henderson 
1409a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1410a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1411bbe418f2SJia Liu }
1412a4fd3ec3SEmilio G. Cota 
1413a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1414a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1415a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1416a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1417a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1418a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1419a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1420a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1421a4fd3ec3SEmilio G. Cota };
1422a4fd3ec3SEmilio G. Cota 
14238b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1424a4fd3ec3SEmilio G. Cota {
1425a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1426a4fd3ec3SEmilio G. Cota 
14278b86d6d2SRichard Henderson     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
1428e67db06eSJia Liu }
1429e67db06eSJia Liu 
143090c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1431e67db06eSJia Liu {
1432878096eeSAndreas Färber     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1433878096eeSAndreas Färber     CPUOpenRISCState *env = &cpu->env;
1434e67db06eSJia Liu     int i;
1435878096eeSAndreas Färber 
143690c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1437e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
143890c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1439e67db06eSJia Liu                      (i % 4) == 3 ? '\n' : ' ');
1440e67db06eSJia Liu     }
1441e67db06eSJia Liu }
1442e67db06eSJia Liu 
1443e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1444bad729e2SRichard Henderson                           target_ulong *data)
1445e67db06eSJia Liu {
1446bad729e2SRichard Henderson     env->pc = data[0];
1447a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1448a01deb36SRichard Henderson     if (data[1] & 2) {
144924c32852SRichard Henderson         env->ppc = env->pc - 4;
145024c32852SRichard Henderson     }
1451e67db06eSJia Liu }
1452