xref: /qemu/target/openrisc/translate.c (revision 62f2b0389ff6fc7856b801bb5bee1c2d364d3e6c)
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;
48fe636d37SRichard 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 
144fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc)
145bbe418f2SJia Liu {
146fe636d37SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF32S;
147bbe418f2SJia Liu }
148bbe418f2SJia Liu 
149*62f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc)
150*62f2b038SRichard Henderson {
151*62f2b038SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF64A32S;
152*62f2b038SRichard Henderson }
153*62f2b038SRichard Henderson 
1548bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg)
1558bba7619SRichard Henderson {
156d29f4368SRichard Henderson     if (reg == 0) {
157d29f4368SRichard Henderson         return dc->R0;
158d29f4368SRichard Henderson     } else {
1598bba7619SRichard Henderson         return cpu_regs[reg];
1608bba7619SRichard Henderson     }
161d29f4368SRichard Henderson }
1628bba7619SRichard Henderson 
163cdd0f459SRichard Henderson /*
164cdd0f459SRichard Henderson  * We're about to write to REG.  On the off-chance that the user is
165cdd0f459SRichard Henderson  * writing to R0, re-instate the architectural register.
166cdd0f459SRichard Henderson  */
167cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg)
168cdd0f459SRichard Henderson {
169cdd0f459SRichard Henderson     if (unlikely(reg == 0)) {
170d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
171cdd0f459SRichard Henderson     }
172cdd0f459SRichard Henderson }
1736597c28dSRichard Henderson 
17497458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1759ecaa27eSRichard Henderson {
1760c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
17797458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
1789ecaa27eSRichard Henderson     }
1790c53d734SRichard Henderson }
1809ecaa27eSRichard Henderson 
18197458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1829ecaa27eSRichard Henderson {
1830c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
18497458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
1859ecaa27eSRichard Henderson     }
1860c53d734SRichard Henderson }
1879ecaa27eSRichard Henderson 
18897458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1899ecaa27eSRichard Henderson {
1900c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
19197458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
1929ecaa27eSRichard Henderson     }
1930c53d734SRichard Henderson }
1949ecaa27eSRichard Henderson 
1959ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
1969ecaa27eSRichard Henderson {
1979ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
1989ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
1999ecaa27eSRichard Henderson 
20097458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
20197458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2029ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
20397458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2049ecaa27eSRichard Henderson     tcg_temp_free(t0);
2059ecaa27eSRichard Henderson 
2069ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2079ecaa27eSRichard Henderson     tcg_temp_free(res);
2089ecaa27eSRichard Henderson 
20997458071SRichard Henderson     gen_ove_cyov(dc);
2109ecaa27eSRichard Henderson }
2119ecaa27eSRichard Henderson 
2129ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2139ecaa27eSRichard Henderson {
2149ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2159ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2169ecaa27eSRichard Henderson 
21797458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
21897458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
21997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2209ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22197458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2229ecaa27eSRichard Henderson     tcg_temp_free(t0);
2239ecaa27eSRichard Henderson 
2249ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2259ecaa27eSRichard Henderson     tcg_temp_free(res);
2269ecaa27eSRichard Henderson 
22797458071SRichard Henderson     gen_ove_cyov(dc);
2289ecaa27eSRichard Henderson }
2299ecaa27eSRichard Henderson 
2309ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2319ecaa27eSRichard Henderson {
2329ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2339ecaa27eSRichard Henderson 
2349ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
23597458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
23697458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
23797458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
23897458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2399ecaa27eSRichard Henderson 
2409ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2419ecaa27eSRichard Henderson     tcg_temp_free(res);
2429ecaa27eSRichard Henderson 
24397458071SRichard Henderson     gen_ove_cyov(dc);
2449ecaa27eSRichard Henderson }
2459ecaa27eSRichard Henderson 
2469ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2479ecaa27eSRichard Henderson {
2489ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2499ecaa27eSRichard Henderson 
25097458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2519ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
25297458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2539ecaa27eSRichard Henderson     tcg_temp_free(t0);
2549ecaa27eSRichard Henderson 
25597458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
25697458071SRichard Henderson     gen_ove_ov(dc);
2579ecaa27eSRichard Henderson }
2589ecaa27eSRichard Henderson 
2599ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2609ecaa27eSRichard Henderson {
26197458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
26297458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2639ecaa27eSRichard Henderson 
26497458071SRichard Henderson     gen_ove_cy(dc);
2659ecaa27eSRichard Henderson }
2669ecaa27eSRichard Henderson 
2679ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2689ecaa27eSRichard Henderson {
2699ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2709ecaa27eSRichard Henderson 
27197458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2729ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2739ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
27497458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2759ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2769ecaa27eSRichard Henderson     tcg_temp_free(t0);
2779ecaa27eSRichard Henderson 
27897458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
27997458071SRichard Henderson     gen_ove_ov(dc);
2809ecaa27eSRichard Henderson }
2819ecaa27eSRichard Henderson 
2829ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2839ecaa27eSRichard Henderson {
2849ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2859ecaa27eSRichard Henderson 
28697458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2879ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2889ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
28997458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2909ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2919ecaa27eSRichard Henderson     tcg_temp_free(t0);
2929ecaa27eSRichard Henderson 
29397458071SRichard Henderson     gen_ove_cy(dc);
2949ecaa27eSRichard Henderson }
295da1d7759SSebastian Macke 
296cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
297cc5de49eSRichard Henderson {
298cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
299cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
300cc5de49eSRichard Henderson 
301cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
302cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
303cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
304cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
305cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
306cc5de49eSRichard Henderson     } else {
307cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
308cc5de49eSRichard Henderson 
309cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
310cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
311cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
312cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
313cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
314cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
315cc5de49eSRichard Henderson 
316cc5de49eSRichard Henderson         gen_ove_ov(dc);
317cc5de49eSRichard Henderson     }
318cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
319cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
320cc5de49eSRichard Henderson }
321cc5de49eSRichard Henderson 
322cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
323cc5de49eSRichard Henderson {
324cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
325cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
326cc5de49eSRichard Henderson 
327cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
328cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
329cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
330cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
331cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
332cc5de49eSRichard Henderson     } else {
333cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
334cc5de49eSRichard Henderson 
335cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
336cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
337cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
338cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
339cc5de49eSRichard Henderson 
340cc5de49eSRichard Henderson         gen_ove_cy(dc);
341cc5de49eSRichard Henderson     }
342cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
343cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
344cc5de49eSRichard Henderson }
345cc5de49eSRichard Henderson 
3466f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3476f7332baSRichard Henderson {
3486f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3496f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3506f7332baSRichard Henderson 
3516f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3526f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3536f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3546f7332baSRichard Henderson 
3556f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3566f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3576f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3586f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3596f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3606f7332baSRichard Henderson     tcg_temp_free_i64(t2);
3616f7332baSRichard Henderson 
3626f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3636f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3646f7332baSRichard Henderson #else
3656f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3666f7332baSRichard Henderson #endif
3676f7332baSRichard Henderson     tcg_temp_free_i64(t1);
3686f7332baSRichard Henderson 
3696f7332baSRichard Henderson     gen_ove_ov(dc);
3706f7332baSRichard Henderson }
3716f7332baSRichard Henderson 
372cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
373cc5de49eSRichard Henderson {
374cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
375cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
376cc5de49eSRichard Henderson 
377cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
378cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
379cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
380cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
381cc5de49eSRichard Henderson 
382cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
383cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
384cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
385cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
386cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
387cc5de49eSRichard Henderson 
388cc5de49eSRichard Henderson     gen_ove_cy(dc);
389cc5de49eSRichard Henderson }
390cc5de49eSRichard Henderson 
3916f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
3926f7332baSRichard Henderson {
3936f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3946f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3956f7332baSRichard Henderson 
3966f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3976f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3986f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3996f7332baSRichard Henderson 
4006f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4016f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4026f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4036f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4046f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4056f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4066f7332baSRichard Henderson 
4076f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4086f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4096f7332baSRichard Henderson #else
4106f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4116f7332baSRichard Henderson #endif
4126f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4136f7332baSRichard Henderson 
4146f7332baSRichard Henderson     gen_ove_ov(dc);
4156f7332baSRichard Henderson }
4166f7332baSRichard Henderson 
417cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
418cc5de49eSRichard Henderson {
419cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
420cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
421cc5de49eSRichard Henderson 
422cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
423cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
424cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
425cc5de49eSRichard Henderson 
426cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
427cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
428cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
429cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
430cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
431cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
432cc5de49eSRichard Henderson 
433cc5de49eSRichard Henderson     gen_ove_cy(dc);
434cc5de49eSRichard Henderson }
435cc5de49eSRichard Henderson 
4363a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
437bbe418f2SJia Liu {
438cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4398bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4406ad216abSRichard Henderson     return true;
441bbe418f2SJia Liu }
442bbe418f2SJia Liu 
4433a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
444bbe418f2SJia Liu {
445cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4468bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4476ad216abSRichard Henderson     return true;
4486ad216abSRichard Henderson }
4496ad216abSRichard Henderson 
4503a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4516ad216abSRichard Henderson {
452cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4538bba7619SRichard Henderson     gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4546ad216abSRichard Henderson     return true;
4556ad216abSRichard Henderson }
4566ad216abSRichard Henderson 
4573a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4586ad216abSRichard Henderson {
459cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4608bba7619SRichard Henderson     tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4616ad216abSRichard Henderson     return true;
4626ad216abSRichard Henderson }
4636ad216abSRichard Henderson 
4643a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4656ad216abSRichard Henderson {
466cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4678bba7619SRichard Henderson     tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4686ad216abSRichard Henderson     return true;
4696ad216abSRichard Henderson }
4706ad216abSRichard Henderson 
4713a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4726ad216abSRichard Henderson {
473cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4748bba7619SRichard Henderson     tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4756ad216abSRichard Henderson     return true;
4766ad216abSRichard Henderson }
4776ad216abSRichard Henderson 
4783a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4796ad216abSRichard Henderson {
480cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4818bba7619SRichard Henderson     tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4826ad216abSRichard Henderson     return true;
4836ad216abSRichard Henderson }
4846ad216abSRichard Henderson 
4853a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4866ad216abSRichard Henderson {
487cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4888bba7619SRichard Henderson     tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4896ad216abSRichard Henderson     return true;
4906ad216abSRichard Henderson }
4916ad216abSRichard Henderson 
4923a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
4936ad216abSRichard Henderson {
494cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4958bba7619SRichard Henderson     tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4966ad216abSRichard Henderson     return true;
4976ad216abSRichard Henderson }
4986ad216abSRichard Henderson 
4993a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
5006ad216abSRichard Henderson {
501cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5028bba7619SRichard Henderson     tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5036ad216abSRichard Henderson     return true;
5046ad216abSRichard Henderson }
5056ad216abSRichard Henderson 
5063a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
5076ad216abSRichard Henderson {
508cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5098bba7619SRichard Henderson     tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5106ad216abSRichard Henderson     return true;
5116ad216abSRichard Henderson }
5126ad216abSRichard Henderson 
5133a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
5146ad216abSRichard Henderson {
515cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5168bba7619SRichard Henderson     tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5176ad216abSRichard Henderson     return true;
5186ad216abSRichard Henderson }
5196ad216abSRichard Henderson 
5203a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5216ad216abSRichard Henderson {
522cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5238bba7619SRichard Henderson     tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5246ad216abSRichard Henderson     return true;
5256ad216abSRichard Henderson }
5266ad216abSRichard Henderson 
5273a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5286ad216abSRichard Henderson {
529cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5308bba7619SRichard Henderson     tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5316ad216abSRichard Henderson     return true;
5326ad216abSRichard Henderson }
5336ad216abSRichard Henderson 
5343a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5356ad216abSRichard Henderson {
5366ad216abSRichard Henderson     TCGv zero;
5376ad216abSRichard Henderson 
538cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5396ad216abSRichard Henderson     zero = tcg_const_tl(0);
5408bba7619SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, zero,
5418bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
542784696d1SRichard Henderson     tcg_temp_free(zero);
5436ad216abSRichard Henderson     return true;
544bbe418f2SJia Liu }
545bbe418f2SJia Liu 
5463a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5476ad216abSRichard Henderson {
548cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5498bba7619SRichard Henderson     tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
5508bba7619SRichard Henderson     tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
5516ad216abSRichard Henderson     return true;
552cf2ae442SRichard Henderson }
553cf2ae442SRichard Henderson 
5543a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5556ad216abSRichard Henderson {
556cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5578bba7619SRichard Henderson     tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
5588bba7619SRichard Henderson     tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
5596ad216abSRichard Henderson     return true;
560bbe418f2SJia Liu }
561bbe418f2SJia Liu 
5623a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5636ad216abSRichard Henderson {
564cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5658bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5666ad216abSRichard Henderson     return true;
567bbe418f2SJia Liu }
5686ad216abSRichard Henderson 
5693a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5706ad216abSRichard Henderson {
571cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5728bba7619SRichard Henderson     gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5736ad216abSRichard Henderson     return true;
574bbe418f2SJia Liu }
5756ad216abSRichard Henderson 
5763a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5776ad216abSRichard Henderson {
578cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5798bba7619SRichard Henderson     gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5806ad216abSRichard Henderson     return true;
5816ad216abSRichard Henderson }
5826ad216abSRichard Henderson 
5833a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5846ad216abSRichard Henderson {
585cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5868bba7619SRichard Henderson     gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5876ad216abSRichard Henderson     return true;
5886ad216abSRichard Henderson }
5896ad216abSRichard Henderson 
5903a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5916ad216abSRichard Henderson {
5928bba7619SRichard Henderson     gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5936ad216abSRichard Henderson     return true;
5946ad216abSRichard Henderson }
5956ad216abSRichard Henderson 
5963a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
5976ad216abSRichard Henderson {
5988bba7619SRichard Henderson     gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5996ad216abSRichard Henderson     return true;
600bbe418f2SJia Liu }
601bbe418f2SJia Liu 
6023a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
603136e13aeSRichard Henderson {
604136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
605136e13aeSRichard Henderson 
606136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
6078000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
608136e13aeSRichard Henderson     dc->delayed_branch = 2;
609136e13aeSRichard Henderson     return true;
610136e13aeSRichard Henderson }
611136e13aeSRichard Henderson 
6123a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
613136e13aeSRichard Henderson {
614136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
615136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
616136e13aeSRichard Henderson 
6178bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], ret_pc);
618136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
619136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
620136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6218000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
622136e13aeSRichard Henderson         dc->delayed_branch = 2;
623136e13aeSRichard Henderson     }
624136e13aeSRichard Henderson     return true;
625136e13aeSRichard Henderson }
626136e13aeSRichard Henderson 
627136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
628136e13aeSRichard Henderson {
629136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
630136e13aeSRichard Henderson     TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
631136e13aeSRichard Henderson     TCGv t_true = tcg_const_tl(tmp_pc);
632136e13aeSRichard Henderson     TCGv t_zero = tcg_const_tl(0);
633136e13aeSRichard Henderson 
634136e13aeSRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
635136e13aeSRichard Henderson 
636136e13aeSRichard Henderson     tcg_temp_free(t_next);
637136e13aeSRichard Henderson     tcg_temp_free(t_true);
638136e13aeSRichard Henderson     tcg_temp_free(t_zero);
639136e13aeSRichard Henderson     dc->delayed_branch = 2;
640136e13aeSRichard Henderson }
641136e13aeSRichard Henderson 
6423a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
643136e13aeSRichard Henderson {
644136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
645136e13aeSRichard Henderson     return true;
646136e13aeSRichard Henderson }
647136e13aeSRichard Henderson 
6483a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
649136e13aeSRichard Henderson {
650136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
651136e13aeSRichard Henderson     return true;
652136e13aeSRichard Henderson }
653136e13aeSRichard Henderson 
6543a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
655136e13aeSRichard Henderson {
6568bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
657136e13aeSRichard Henderson     dc->delayed_branch = 2;
658136e13aeSRichard Henderson     return true;
659136e13aeSRichard Henderson }
660136e13aeSRichard Henderson 
6613a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
662136e13aeSRichard Henderson {
6638bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
6648bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
665136e13aeSRichard Henderson     dc->delayed_branch = 2;
666136e13aeSRichard Henderson     return true;
667136e13aeSRichard Henderson }
668136e13aeSRichard Henderson 
6693a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
670d80bff19SRichard Henderson {
671d80bff19SRichard Henderson     TCGv ea;
672d80bff19SRichard Henderson 
673cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
674d80bff19SRichard Henderson     ea = tcg_temp_new();
6758bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6768bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
677d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
6788bba7619SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
679d80bff19SRichard Henderson     tcg_temp_free(ea);
680d80bff19SRichard Henderson     return true;
681d80bff19SRichard Henderson }
682d80bff19SRichard Henderson 
68314776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
684d80bff19SRichard Henderson {
685d80bff19SRichard Henderson     TCGv ea;
686d80bff19SRichard Henderson 
687cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
688d80bff19SRichard Henderson     ea = tcg_temp_new();
6898bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6908bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
691d80bff19SRichard Henderson     tcg_temp_free(ea);
692d80bff19SRichard Henderson }
693d80bff19SRichard Henderson 
6943a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
695d80bff19SRichard Henderson {
696d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
697d80bff19SRichard Henderson     return true;
698d80bff19SRichard Henderson }
699d80bff19SRichard Henderson 
7003a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
701d80bff19SRichard Henderson {
702d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
703d80bff19SRichard Henderson     return true;
704d80bff19SRichard Henderson }
705d80bff19SRichard Henderson 
7063a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
707d80bff19SRichard Henderson {
708d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
709d80bff19SRichard Henderson     return true;
710d80bff19SRichard Henderson }
711d80bff19SRichard Henderson 
7123a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
713d80bff19SRichard Henderson {
714d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
715d80bff19SRichard Henderson     return true;
716d80bff19SRichard Henderson }
717d80bff19SRichard Henderson 
7183a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
719d80bff19SRichard Henderson {
720d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
721d80bff19SRichard Henderson     return true;
722d80bff19SRichard Henderson }
723d80bff19SRichard Henderson 
7243a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
725d80bff19SRichard Henderson {
726d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
727d80bff19SRichard Henderson     return true;
728d80bff19SRichard Henderson }
729d80bff19SRichard Henderson 
7303a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
731d80bff19SRichard Henderson {
732d80bff19SRichard Henderson     TCGv ea, val;
733d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
734d80bff19SRichard Henderson 
735d80bff19SRichard Henderson     ea = tcg_temp_new();
7368bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
737d80bff19SRichard Henderson 
738d80bff19SRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
7398bba7619SRichard Henderson        to cpu_regs[0].  Since l.swa is quite often immediately followed by a
740d80bff19SRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
741d80bff19SRichard Henderson        This also takes care of RB input across the branch.  */
742d29f4368SRichard Henderson     dc->R0 = cpu_regs[0];
743d80bff19SRichard Henderson 
744d80bff19SRichard Henderson     lab_fail = gen_new_label();
745d80bff19SRichard Henderson     lab_done = gen_new_label();
746d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
747d80bff19SRichard Henderson     tcg_temp_free(ea);
748d80bff19SRichard Henderson 
749d80bff19SRichard Henderson     val = tcg_temp_new();
750d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
7518bba7619SRichard Henderson                               cpu_regs[a->b], dc->mem_idx, MO_TEUL);
752d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
753d80bff19SRichard Henderson     tcg_temp_free(val);
754d80bff19SRichard Henderson 
755d80bff19SRichard Henderson     tcg_gen_br(lab_done);
756d80bff19SRichard Henderson 
757d80bff19SRichard Henderson     gen_set_label(lab_fail);
758d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
759d80bff19SRichard Henderson 
760d80bff19SRichard Henderson     gen_set_label(lab_done);
761d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
762d80bff19SRichard Henderson     return true;
763d80bff19SRichard Henderson }
764d80bff19SRichard Henderson 
76514776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
766d80bff19SRichard Henderson {
767d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
7688bba7619SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
7698bba7619SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
770d80bff19SRichard Henderson     tcg_temp_free(t0);
771d80bff19SRichard Henderson }
772d80bff19SRichard Henderson 
7733a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
774d80bff19SRichard Henderson {
775d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
776d80bff19SRichard Henderson     return true;
777d80bff19SRichard Henderson }
778d80bff19SRichard Henderson 
7793a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
780d80bff19SRichard Henderson {
781d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
782d80bff19SRichard Henderson     return true;
783d80bff19SRichard Henderson }
784d80bff19SRichard Henderson 
7853a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
786d80bff19SRichard Henderson {
787d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
788d80bff19SRichard Henderson     return true;
789d80bff19SRichard Henderson }
790d80bff19SRichard Henderson 
7913a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
792bbe418f2SJia Liu {
7938816f70bSRichard Henderson     return true;
7948816f70bSRichard Henderson }
7958816f70bSRichard Henderson 
7963a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
7978816f70bSRichard Henderson {
7989ecaa27eSRichard Henderson     TCGv t0;
7995631e69cSRichard Henderson 
800cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8018816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8028bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8036f7332baSRichard Henderson     tcg_temp_free(t0);
8048816f70bSRichard Henderson     return true;
8058816f70bSRichard Henderson }
806bbe418f2SJia Liu 
8073a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
808bbe418f2SJia Liu {
8098816f70bSRichard Henderson     TCGv t0;
8108816f70bSRichard Henderson 
811cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8128816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8138bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8148816f70bSRichard Henderson     tcg_temp_free(t0);
8158816f70bSRichard Henderson     return true;
8168816f70bSRichard Henderson }
8178816f70bSRichard Henderson 
8183a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
8198816f70bSRichard Henderson {
8208816f70bSRichard Henderson     TCGv t0;
8218816f70bSRichard Henderson 
822cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8238816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8248bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), t0);
8258816f70bSRichard Henderson     tcg_temp_free(t0);
8268816f70bSRichard Henderson     return true;
8278816f70bSRichard Henderson }
8288816f70bSRichard Henderson 
8293a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
8308816f70bSRichard Henderson {
8318816f70bSRichard Henderson     TCGv t0;
8328816f70bSRichard Henderson 
8338816f70bSRichard Henderson     t0 = tcg_const_tl(a->i);
8348bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), t0);
8358816f70bSRichard Henderson     tcg_temp_free(t0);
8368816f70bSRichard Henderson     return true;
8378816f70bSRichard Henderson }
8388816f70bSRichard Henderson 
8393a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8408816f70bSRichard Henderson {
841cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8428bba7619SRichard Henderson     tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8438816f70bSRichard Henderson     return true;
8448816f70bSRichard Henderson }
8458816f70bSRichard Henderson 
8463a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8478816f70bSRichard Henderson {
848cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8498bba7619SRichard Henderson     tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8508816f70bSRichard Henderson     return true;
8518816f70bSRichard Henderson }
8528816f70bSRichard Henderson 
8533a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8548816f70bSRichard Henderson {
855cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8568bba7619SRichard Henderson     tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
8578816f70bSRichard Henderson     return true;
8588816f70bSRichard Henderson }
8598816f70bSRichard Henderson 
8603a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8618816f70bSRichard Henderson {
862cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8638816f70bSRichard Henderson 
8642ba65417SRichard Henderson     if (is_user(dc)) {
865bbe418f2SJia Liu         gen_illegal_exception(dc);
8668816f70bSRichard Henderson     } else {
867c28fa81fSRichard Henderson         TCGv spr = tcg_temp_new();
8688bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
8698bba7619SRichard Henderson         gen_helper_mfspr(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d), spr);
870c28fa81fSRichard Henderson         tcg_temp_free(spr);
8714dd044c6SJia Liu     }
8728816f70bSRichard Henderson     return true;
8738816f70bSRichard Henderson }
874bbe418f2SJia Liu 
8753a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
8764dd044c6SJia Liu {
8772ba65417SRichard Henderson     if (is_user(dc)) {
8784dd044c6SJia Liu         gen_illegal_exception(dc);
8798816f70bSRichard Henderson     } else {
880c28fa81fSRichard Henderson         TCGv spr;
88101ec3ec9SRichard Henderson 
88201ec3ec9SRichard Henderson         /* For SR, we will need to exit the TB to recognize the new
88301ec3ec9SRichard Henderson          * exception state.  For NPC, in theory this counts as a branch
88401ec3ec9SRichard Henderson          * (although the SPR only exists for use by an ICE).  Save all
88501ec3ec9SRichard Henderson          * of the cpu state first, allowing it to be overwritten.
88601ec3ec9SRichard Henderson          */
88701ec3ec9SRichard Henderson         if (dc->delayed_branch) {
88801ec3ec9SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
88901ec3ec9SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
89001ec3ec9SRichard Henderson         } else {
89101ec3ec9SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
89201ec3ec9SRichard Henderson         }
89301ec3ec9SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
89401ec3ec9SRichard Henderson 
895c28fa81fSRichard Henderson         spr = tcg_temp_new();
8968bba7619SRichard Henderson         tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
8978bba7619SRichard Henderson         gen_helper_mtspr(cpu_env, spr, cpu_R(dc, a->b));
898c28fa81fSRichard Henderson         tcg_temp_free(spr);
8994dd044c6SJia Liu     }
9008816f70bSRichard Henderson     return true;
901bbe418f2SJia Liu }
902bbe418f2SJia Liu 
9033a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
904bbe418f2SJia Liu {
9058bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
90699d863d6SRichard Henderson     return true;
907bbe418f2SJia Liu }
90899d863d6SRichard Henderson 
9093a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
91099d863d6SRichard Henderson {
9118bba7619SRichard Henderson     gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
91299d863d6SRichard Henderson     return true;
91399d863d6SRichard Henderson }
91499d863d6SRichard Henderson 
9153a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
91699d863d6SRichard Henderson {
9178bba7619SRichard Henderson     gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
91899d863d6SRichard Henderson     return true;
91999d863d6SRichard Henderson }
92099d863d6SRichard Henderson 
9213a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
92299d863d6SRichard Henderson {
9238bba7619SRichard Henderson     gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
92499d863d6SRichard Henderson     return true;
925bbe418f2SJia Liu }
926bbe418f2SJia Liu 
9273a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
928bbe418f2SJia Liu {
929cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9308bba7619SRichard Henderson     tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9318bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
932e20c2592SRichard Henderson     return true;
933bbe418f2SJia Liu }
934e20c2592SRichard Henderson 
9353a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
936e20c2592SRichard Henderson {
937cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9388bba7619SRichard Henderson     tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9398bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
940e20c2592SRichard Henderson     return true;
941e20c2592SRichard Henderson }
942e20c2592SRichard Henderson 
9433a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
944e20c2592SRichard Henderson {
945cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9468bba7619SRichard Henderson     tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9478bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
948e20c2592SRichard Henderson     return true;
949e20c2592SRichard Henderson }
950e20c2592SRichard Henderson 
9513a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
952e20c2592SRichard Henderson {
953cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9548bba7619SRichard Henderson     tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9558bba7619SRichard Henderson                      a->l & (TARGET_LONG_BITS - 1));
956e20c2592SRichard Henderson     return true;
957bbe418f2SJia Liu }
958bbe418f2SJia Liu 
9593a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
960bbe418f2SJia Liu {
961cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9628bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
963e720a571SRichard Henderson     return true;
964bbe418f2SJia Liu }
965e720a571SRichard Henderson 
9663a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
967e720a571SRichard Henderson {
968cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9698bba7619SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
970e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
971e720a571SRichard Henderson     return true;
972bbe418f2SJia Liu }
973bbe418f2SJia Liu 
9743a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
975bbe418f2SJia Liu {
9768bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
9778bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
978fbb3e29aSRichard Henderson     return true;
979bbe418f2SJia Liu }
980fbb3e29aSRichard Henderson 
9813a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
982fbb3e29aSRichard Henderson {
9838bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
9848bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
985fbb3e29aSRichard Henderson     return true;
986fbb3e29aSRichard Henderson }
987fbb3e29aSRichard Henderson 
9883a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
989fbb3e29aSRichard Henderson {
9908bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
9918bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
992fbb3e29aSRichard Henderson     return true;
993fbb3e29aSRichard Henderson }
994fbb3e29aSRichard Henderson 
9953a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
996fbb3e29aSRichard Henderson {
9978bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
9988bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
999fbb3e29aSRichard Henderson     return true;
1000fbb3e29aSRichard Henderson }
1001fbb3e29aSRichard Henderson 
10023a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
1003fbb3e29aSRichard Henderson {
10048bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
10058bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1006fbb3e29aSRichard Henderson     return true;
1007fbb3e29aSRichard Henderson }
1008fbb3e29aSRichard Henderson 
10093a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
1010fbb3e29aSRichard Henderson {
10118bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
10128bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1013fbb3e29aSRichard Henderson     return true;
1014fbb3e29aSRichard Henderson }
1015fbb3e29aSRichard Henderson 
10163a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
1017fbb3e29aSRichard Henderson {
10188bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
10198bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1020fbb3e29aSRichard Henderson     return true;
1021fbb3e29aSRichard Henderson }
1022fbb3e29aSRichard Henderson 
10233a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
1024fbb3e29aSRichard Henderson {
10258bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
10268bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1027fbb3e29aSRichard Henderson     return true;
1028fbb3e29aSRichard Henderson }
1029fbb3e29aSRichard Henderson 
10303a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
1031fbb3e29aSRichard Henderson {
10328bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
10338bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
1034fbb3e29aSRichard Henderson     return true;
1035fbb3e29aSRichard Henderson }
1036fbb3e29aSRichard Henderson 
10373a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1038fbb3e29aSRichard Henderson {
10398bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE,
10408bba7619SRichard Henderson                        cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1041fbb3e29aSRichard Henderson     return true;
1042bbe418f2SJia Liu }
1043bbe418f2SJia Liu 
10443a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1045bbe418f2SJia Liu {
10468bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1047032de4fcSRichard Henderson     return true;
1048bbe418f2SJia Liu }
1049032de4fcSRichard Henderson 
10503a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1051032de4fcSRichard Henderson {
10528bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1053032de4fcSRichard Henderson     return true;
1054032de4fcSRichard Henderson }
1055032de4fcSRichard Henderson 
10563a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1057032de4fcSRichard Henderson {
10588bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1059032de4fcSRichard Henderson     return true;
1060032de4fcSRichard Henderson }
1061032de4fcSRichard Henderson 
10623a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1063032de4fcSRichard Henderson {
10648bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1065032de4fcSRichard Henderson     return true;
1066032de4fcSRichard Henderson }
1067032de4fcSRichard Henderson 
10683a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1069032de4fcSRichard Henderson {
10708bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1071032de4fcSRichard Henderson     return true;
1072032de4fcSRichard Henderson }
1073032de4fcSRichard Henderson 
10743a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1075032de4fcSRichard Henderson {
10768bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1077032de4fcSRichard Henderson     return true;
1078032de4fcSRichard Henderson }
1079032de4fcSRichard Henderson 
10803a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1081032de4fcSRichard Henderson {
10828bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1083032de4fcSRichard Henderson     return true;
1084032de4fcSRichard Henderson }
1085032de4fcSRichard Henderson 
10863a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1087032de4fcSRichard Henderson {
10888bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1089032de4fcSRichard Henderson     return true;
1090032de4fcSRichard Henderson }
1091032de4fcSRichard Henderson 
10923a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1093032de4fcSRichard Henderson {
10948bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1095032de4fcSRichard Henderson     return true;
1096032de4fcSRichard Henderson }
1097032de4fcSRichard Henderson 
10983a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1099032de4fcSRichard Henderson {
11008bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1101032de4fcSRichard Henderson     return true;
1102bbe418f2SJia Liu }
1103bbe418f2SJia Liu 
11043a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1105bbe418f2SJia Liu {
11061ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1107bbe418f2SJia Liu     gen_exception(dc, EXCP_SYSCALL);
11081ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11097de9729fSRichard Henderson     return true;
11107de9729fSRichard Henderson }
1111bbe418f2SJia Liu 
11123a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
11137de9729fSRichard Henderson {
11141ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1115bbe418f2SJia Liu     gen_exception(dc, EXCP_TRAP);
11161ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
11177de9729fSRichard Henderson     return true;
11187de9729fSRichard Henderson }
1119bbe418f2SJia Liu 
11203a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
11217de9729fSRichard Henderson {
112224fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
11237de9729fSRichard Henderson     return true;
1124bbe418f2SJia Liu }
11257de9729fSRichard Henderson 
11263a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
11277de9729fSRichard Henderson {
11287de9729fSRichard Henderson     return true;
11297de9729fSRichard Henderson }
11307de9729fSRichard Henderson 
11313a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
11327de9729fSRichard Henderson {
11337de9729fSRichard Henderson     return true;
1134bbe418f2SJia Liu }
1135bbe418f2SJia Liu 
11363a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11378816f70bSRichard Henderson {
11382ba65417SRichard Henderson     if (is_user(dc)) {
11398816f70bSRichard Henderson         gen_illegal_exception(dc);
11408816f70bSRichard Henderson     } else {
11418816f70bSRichard Henderson         gen_helper_rfe(cpu_env);
114264e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11438816f70bSRichard Henderson     }
11448816f70bSRichard Henderson     return true;
11458816f70bSRichard Henderson }
11468816f70bSRichard Henderson 
1147fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a,
11486fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1149bbe418f2SJia Liu {
1150fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1151fe636d37SRichard Henderson         return false;
1152fe636d37SRichard Henderson     }
1153cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
11548bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a));
11554e2d3007SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1156fe636d37SRichard Henderson     return true;
1157bbe418f2SJia Liu }
11586fd204a2SRichard Henderson 
1159fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a,
11606fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11616fd204a2SRichard Henderson {
1162fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1163fe636d37SRichard Henderson         return false;
1164fe636d37SRichard Henderson     }
1165cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
11668bba7619SRichard Henderson     fn(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11676fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1168fe636d37SRichard Henderson     return true;
11696fd204a2SRichard Henderson }
11706fd204a2SRichard Henderson 
1171fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a,
11726fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11736fd204a2SRichard Henderson                      bool inv, bool swap)
11746fd204a2SRichard Henderson {
1175fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1176fe636d37SRichard Henderson         return false;
1177fe636d37SRichard Henderson     }
11786fd204a2SRichard Henderson     if (swap) {
11798bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
11806fd204a2SRichard Henderson     } else {
11818bba7619SRichard Henderson         fn(cpu_sr_f, cpu_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11826fd204a2SRichard Henderson     }
11836fd204a2SRichard Henderson     if (inv) {
11846fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11856fd204a2SRichard Henderson     }
11866fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1187fe636d37SRichard Henderson     return true;
11886fd204a2SRichard Henderson }
11896fd204a2SRichard Henderson 
11903a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11916fd204a2SRichard Henderson {
1192fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_add_s);
11936fd204a2SRichard Henderson }
11946fd204a2SRichard Henderson 
11953a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11966fd204a2SRichard Henderson {
1197fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_sub_s);
11986fd204a2SRichard Henderson }
11996fd204a2SRichard Henderson 
12003a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
12016fd204a2SRichard Henderson {
1202fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_mul_s);
12036fd204a2SRichard Henderson }
12046fd204a2SRichard Henderson 
12053a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
12066fd204a2SRichard Henderson {
1207fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_div_s);
12086fd204a2SRichard Henderson }
12096fd204a2SRichard Henderson 
12103a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
12116fd204a2SRichard Henderson {
1212fe636d37SRichard Henderson     return 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 {
1218fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_itofs);
12196fd204a2SRichard Henderson }
12206fd204a2SRichard Henderson 
12213a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
12226fd204a2SRichard Henderson {
1223fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_ftois);
12246fd204a2SRichard Henderson }
12256fd204a2SRichard Henderson 
12263a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
12276fd204a2SRichard Henderson {
1228fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1229fe636d37SRichard Henderson         return false;
1230fe636d37SRichard Henderson     }
1231cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
12328bba7619SRichard Henderson     gen_helper_float_madd_s(cpu_R(dc, a->d), cpu_env, cpu_R(dc, a->d),
12338bba7619SRichard Henderson                             cpu_R(dc, a->a), cpu_R(dc, a->b));
12346fd204a2SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
12356fd204a2SRichard Henderson     return true;
12366fd204a2SRichard Henderson }
12376fd204a2SRichard Henderson 
12383a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12396fd204a2SRichard Henderson {
1240fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12416fd204a2SRichard Henderson }
12426fd204a2SRichard Henderson 
12433a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12446fd204a2SRichard Henderson {
1245fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12466fd204a2SRichard Henderson }
12476fd204a2SRichard Henderson 
12483a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12496fd204a2SRichard Henderson {
1250fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12516fd204a2SRichard Henderson }
12526fd204a2SRichard Henderson 
12533a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12546fd204a2SRichard Henderson {
1255fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12566fd204a2SRichard Henderson }
12576fd204a2SRichard Henderson 
12583a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12596fd204a2SRichard Henderson {
1260fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12616fd204a2SRichard Henderson }
12626fd204a2SRichard Henderson 
12633a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12646fd204a2SRichard Henderson {
1265fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1266bbe418f2SJia Liu }
1267bbe418f2SJia Liu 
1268*62f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p)
1269*62f2b038SRichard Henderson {
1270*62f2b038SRichard Henderson     return r + 1 + p < 32;
1271*62f2b038SRichard Henderson }
1272*62f2b038SRichard Henderson 
1273*62f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
1274*62f2b038SRichard Henderson {
1275*62f2b038SRichard Henderson     tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r));
1276*62f2b038SRichard Henderson }
1277*62f2b038SRichard Henderson 
1278*62f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
1279*62f2b038SRichard Henderson {
1280*62f2b038SRichard Henderson     tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t);
1281*62f2b038SRichard Henderson }
1282*62f2b038SRichard Henderson 
1283*62f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a,
1284*62f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1285*62f2b038SRichard Henderson {
1286*62f2b038SRichard Henderson     TCGv_i64 t0, t1;
1287*62f2b038SRichard Henderson 
1288*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1289*62f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
1290*62f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
1291*62f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
1292*62f2b038SRichard Henderson         return false;
1293*62f2b038SRichard Henderson     }
1294*62f2b038SRichard Henderson     check_r0_write(dc, a->d);
1295*62f2b038SRichard Henderson 
1296*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1297*62f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
1298*62f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1299*62f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
1300*62f2b038SRichard Henderson     fn(t0, cpu_env, t0, t1);
1301*62f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
1302*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1303*62f2b038SRichard Henderson     tcg_temp_free_i64(t1);
1304*62f2b038SRichard Henderson 
1305*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1306*62f2b038SRichard Henderson     return true;
1307*62f2b038SRichard Henderson }
1308*62f2b038SRichard Henderson 
1309*62f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a,
1310*62f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64))
1311*62f2b038SRichard Henderson {
1312*62f2b038SRichard Henderson     TCGv_i64 t0;
1313*62f2b038SRichard Henderson 
1314*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1315*62f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
1316*62f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
1317*62f2b038SRichard Henderson         return false;
1318*62f2b038SRichard Henderson     }
1319*62f2b038SRichard Henderson     check_r0_write(dc, a->d);
1320*62f2b038SRichard Henderson 
1321*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1322*62f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1323*62f2b038SRichard Henderson     fn(t0, cpu_env, t0);
1324*62f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
1325*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1326*62f2b038SRichard Henderson 
1327*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1328*62f2b038SRichard Henderson     return true;
1329*62f2b038SRichard Henderson }
1330*62f2b038SRichard Henderson 
1331*62f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a,
1332*62f2b038SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64),
1333*62f2b038SRichard Henderson                      bool inv, bool swap)
1334*62f2b038SRichard Henderson {
1335*62f2b038SRichard Henderson     TCGv_i64 t0, t1;
1336*62f2b038SRichard Henderson 
1337*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1338*62f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
1339*62f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp)) {
1340*62f2b038SRichard Henderson         return false;
1341*62f2b038SRichard Henderson     }
1342*62f2b038SRichard Henderson 
1343*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1344*62f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
1345*62f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1346*62f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
1347*62f2b038SRichard Henderson     if (swap) {
1348*62f2b038SRichard Henderson         fn(cpu_sr_f, cpu_env, t1, t0);
1349*62f2b038SRichard Henderson     } else {
1350*62f2b038SRichard Henderson         fn(cpu_sr_f, cpu_env, t0, t1);
1351*62f2b038SRichard Henderson     }
1352*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1353*62f2b038SRichard Henderson     tcg_temp_free_i64(t1);
1354*62f2b038SRichard Henderson 
1355*62f2b038SRichard Henderson     if (inv) {
1356*62f2b038SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
1357*62f2b038SRichard Henderson     }
1358*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1359*62f2b038SRichard Henderson     return true;
1360*62f2b038SRichard Henderson }
1361*62f2b038SRichard Henderson 
1362*62f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a)
1363*62f2b038SRichard Henderson {
1364*62f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_add_d);
1365*62f2b038SRichard Henderson }
1366*62f2b038SRichard Henderson 
1367*62f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a)
1368*62f2b038SRichard Henderson {
1369*62f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_sub_d);
1370*62f2b038SRichard Henderson }
1371*62f2b038SRichard Henderson 
1372*62f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a)
1373*62f2b038SRichard Henderson {
1374*62f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_mul_d);
1375*62f2b038SRichard Henderson }
1376*62f2b038SRichard Henderson 
1377*62f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a)
1378*62f2b038SRichard Henderson {
1379*62f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_div_d);
1380*62f2b038SRichard Henderson }
1381*62f2b038SRichard Henderson 
1382*62f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a)
1383*62f2b038SRichard Henderson {
1384*62f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_rem_d);
1385*62f2b038SRichard Henderson }
1386*62f2b038SRichard Henderson 
1387*62f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a)
1388*62f2b038SRichard Henderson {
1389*62f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_itofd);
1390*62f2b038SRichard Henderson }
1391*62f2b038SRichard Henderson 
1392*62f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a)
1393*62f2b038SRichard Henderson {
1394*62f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_ftoid);
1395*62f2b038SRichard Henderson }
1396*62f2b038SRichard Henderson 
1397*62f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a)
1398*62f2b038SRichard Henderson {
1399*62f2b038SRichard Henderson     TCGv_i64 t0;
1400*62f2b038SRichard Henderson 
1401*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1402*62f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
1403*62f2b038SRichard Henderson         return false;
1404*62f2b038SRichard Henderson     }
1405*62f2b038SRichard Henderson     check_r0_write(dc, a->d);
1406*62f2b038SRichard Henderson 
1407*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1408*62f2b038SRichard Henderson     gen_helper_stod(t0, cpu_env, cpu_R(dc, a->a));
1409*62f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
1410*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1411*62f2b038SRichard Henderson 
1412*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1413*62f2b038SRichard Henderson     return true;
1414*62f2b038SRichard Henderson }
1415*62f2b038SRichard Henderson 
1416*62f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a)
1417*62f2b038SRichard Henderson {
1418*62f2b038SRichard Henderson     TCGv_i64 t0;
1419*62f2b038SRichard Henderson 
1420*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1421*62f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap)) {
1422*62f2b038SRichard Henderson         return false;
1423*62f2b038SRichard Henderson     }
1424*62f2b038SRichard Henderson     check_r0_write(dc, a->d);
1425*62f2b038SRichard Henderson 
1426*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1427*62f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1428*62f2b038SRichard Henderson     gen_helper_dtos(cpu_R(dc, a->d), cpu_env, t0);
1429*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1430*62f2b038SRichard Henderson 
1431*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1432*62f2b038SRichard Henderson     return true;
1433*62f2b038SRichard Henderson }
1434*62f2b038SRichard Henderson 
1435*62f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a)
1436*62f2b038SRichard Henderson {
1437*62f2b038SRichard Henderson     TCGv_i64 t0, t1, t2;
1438*62f2b038SRichard Henderson 
1439*62f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
1440*62f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
1441*62f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
1442*62f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
1443*62f2b038SRichard Henderson         return false;
1444*62f2b038SRichard Henderson     }
1445*62f2b038SRichard Henderson     check_r0_write(dc, a->d);
1446*62f2b038SRichard Henderson 
1447*62f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1448*62f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
1449*62f2b038SRichard Henderson     t2 = tcg_temp_new_i64();
1450*62f2b038SRichard Henderson     load_pair(dc, t0, a->d, a->dp);
1451*62f2b038SRichard Henderson     load_pair(dc, t1, a->a, a->ap);
1452*62f2b038SRichard Henderson     load_pair(dc, t2, a->b, a->bp);
1453*62f2b038SRichard Henderson     gen_helper_float_madd_d(t0, cpu_env, t0, t1, t2);
1454*62f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
1455*62f2b038SRichard Henderson     tcg_temp_free_i64(t0);
1456*62f2b038SRichard Henderson     tcg_temp_free_i64(t1);
1457*62f2b038SRichard Henderson     tcg_temp_free_i64(t2);
1458*62f2b038SRichard Henderson 
1459*62f2b038SRichard Henderson     gen_helper_update_fpcsr(cpu_env);
1460*62f2b038SRichard Henderson     return true;
1461*62f2b038SRichard Henderson }
1462*62f2b038SRichard Henderson 
1463*62f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a)
1464*62f2b038SRichard Henderson {
1465*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false);
1466*62f2b038SRichard Henderson }
1467*62f2b038SRichard Henderson 
1468*62f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a)
1469*62f2b038SRichard Henderson {
1470*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false);
1471*62f2b038SRichard Henderson }
1472*62f2b038SRichard Henderson 
1473*62f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a)
1474*62f2b038SRichard Henderson {
1475*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true);
1476*62f2b038SRichard Henderson }
1477*62f2b038SRichard Henderson 
1478*62f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a)
1479*62f2b038SRichard Henderson {
1480*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, true);
1481*62f2b038SRichard Henderson }
1482*62f2b038SRichard Henderson 
1483*62f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a)
1484*62f2b038SRichard Henderson {
1485*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false);
1486*62f2b038SRichard Henderson }
1487*62f2b038SRichard Henderson 
1488*62f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a)
1489*62f2b038SRichard Henderson {
1490*62f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, false);
1491*62f2b038SRichard Henderson }
1492*62f2b038SRichard Henderson 
1493a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1494e67db06eSJia Liu {
1495a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
14969c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1497a4fd3ec3SEmilio G. Cota     int bound;
1498bbe418f2SJia Liu 
1499a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
15001ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1501a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1502fe636d37SRichard Henderson     dc->cpucfgr = env->cpucfgr;
15038000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
15048000ba56SRichard Henderson 
1505a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1506a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1507190ce7fbSRichard Henderson }
1508bbe418f2SJia Liu 
1509a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1510a4fd3ec3SEmilio G. Cota {
1511a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1512bbe418f2SJia Liu 
15136597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15146597c28dSRichard Henderson        when it's true, which is the common case.  */
15156597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1516d29f4368SRichard Henderson         dc->R0 = tcg_const_tl(0);
15176597c28dSRichard Henderson     } else {
1518d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
15196597c28dSRichard Henderson     }
1520a4fd3ec3SEmilio G. Cota }
15216597c28dSRichard Henderson 
1522a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1523a4fd3ec3SEmilio G. Cota {
1524a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1525a4fd3ec3SEmilio G. Cota 
15261ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1527a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1528a4fd3ec3SEmilio G. Cota }
1529bbe418f2SJia Liu 
1530a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1531a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1532a4fd3ec3SEmilio G. Cota {
1533a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1534a4fd3ec3SEmilio G. Cota 
15351ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1536b933066aSRichard Henderson     gen_exception(dc, EXCP_DEBUG);
15371ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1538522a0d4eSRichard Henderson     /* The address covered by the breakpoint must be included in
1539522a0d4eSRichard Henderson        [tb->pc, tb->pc + tb->size) in order to for it to be
1540522a0d4eSRichard Henderson        properly cleared -- thus we increment the PC here so that
1541522a0d4eSRichard Henderson        the logic setting tb->size below does the right thing.  */
15421ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1543a4fd3ec3SEmilio G. Cota     return true;
1544b933066aSRichard Henderson }
1545b933066aSRichard Henderson 
1546a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1547a4fd3ec3SEmilio G. Cota {
1548a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1549a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1550c7b6f54bSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1551a4fd3ec3SEmilio G. Cota 
1552c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1553c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1554c7b6f54bSRichard Henderson     }
15551ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
155624c32852SRichard Henderson 
15578000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
15588000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
15598000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
15608000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
15618000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
15628000ba56SRichard Henderson      */
15638000ba56SRichard Henderson     if (dc->delayed_branch
15648000ba56SRichard Henderson         && --dc->delayed_branch == 0
15658000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
15668000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1567bbe418f2SJia Liu     }
1568a4fd3ec3SEmilio G. Cota }
1569bbe418f2SJia Liu 
1570a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1571a4fd3ec3SEmilio G. Cota {
1572a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
15738000ba56SRichard Henderson     target_ulong jmp_dest;
157424c32852SRichard Henderson 
1575e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1576e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1577e0a369cfSRichard Henderson         return;
1578e0a369cfSRichard Henderson     }
1579e0a369cfSRichard Henderson 
15808000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1581a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1582a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1583a01deb36SRichard Henderson     }
1584a01deb36SRichard Henderson 
15858000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
15868000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
15878000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
15888000ba56SRichard Henderson 
15891ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
15908000ba56SRichard Henderson     case DISAS_JUMP:
15918000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
15928000ba56SRichard Henderson         if (jmp_dest == -1) {
15938000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
15948000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
15958000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
15968000ba56SRichard Henderson             if (unlikely(dc->base.singlestep_enabled)) {
15978000ba56SRichard Henderson                 gen_exception(dc, EXCP_DEBUG);
15988000ba56SRichard Henderson             } else {
15998000ba56SRichard Henderson                 tcg_gen_lookup_and_goto_ptr();
16008000ba56SRichard Henderson             }
1601bbe418f2SJia Liu             break;
16028000ba56SRichard Henderson         }
16038000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
16048000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
16058000ba56SRichard Henderson            we know now that it wasn't needed.  */
16068000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
16078000ba56SRichard Henderson         /* fallthru */
16088000ba56SRichard Henderson 
16098000ba56SRichard Henderson     case DISAS_TOO_MANY:
16108000ba56SRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
16118000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
16128000ba56SRichard Henderson             gen_exception(dc, EXCP_DEBUG);
16138000ba56SRichard Henderson         } else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
16148000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
16158000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
16168000ba56SRichard Henderson         } else {
16178000ba56SRichard Henderson             tcg_gen_goto_tb(0);
16188000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
16198000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
16208000ba56SRichard Henderson         }
16218000ba56SRichard Henderson         break;
16228000ba56SRichard Henderson 
162364e46c95SRichard Henderson     case DISAS_EXIT:
1624e0a369cfSRichard Henderson         if (unlikely(dc->base.singlestep_enabled)) {
1625e0a369cfSRichard Henderson             gen_exception(dc, EXCP_DEBUG);
1626e0a369cfSRichard Henderson         } else {
162707ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
1628e0a369cfSRichard Henderson         }
1629bbe418f2SJia Liu         break;
1630a4fd3ec3SEmilio G. Cota     default:
1631a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1632a4fd3ec3SEmilio G. Cota     }
1633bbe418f2SJia Liu }
1634bbe418f2SJia Liu 
1635a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1636a4fd3ec3SEmilio G. Cota {
1637a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
16380a7df5daSRichard Henderson 
1639a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1640a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1641bbe418f2SJia Liu }
1642a4fd3ec3SEmilio G. Cota 
1643a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1644a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1645a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1646a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1647a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1648a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1649a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1650a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1651a4fd3ec3SEmilio G. Cota };
1652a4fd3ec3SEmilio G. Cota 
16538b86d6d2SRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
1654a4fd3ec3SEmilio G. Cota {
1655a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1656a4fd3ec3SEmilio G. Cota 
16578b86d6d2SRichard Henderson     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
1658e67db06eSJia Liu }
1659e67db06eSJia Liu 
166090c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1661e67db06eSJia Liu {
1662878096eeSAndreas Färber     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1663878096eeSAndreas Färber     CPUOpenRISCState *env = &cpu->env;
1664e67db06eSJia Liu     int i;
1665878096eeSAndreas Färber 
166690c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1667e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
166890c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1669e67db06eSJia Liu                      (i % 4) == 3 ? '\n' : ' ');
1670e67db06eSJia Liu     }
1671e67db06eSJia Liu }
1672e67db06eSJia Liu 
1673e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1674bad729e2SRichard Henderson                           target_ulong *data)
1675e67db06eSJia Liu {
1676bad729e2SRichard Henderson     env->pc = data[0];
1677a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1678a01deb36SRichard Henderson     if (data[1] & 2) {
167924c32852SRichard Henderson         env->ppc = env->pc - 4;
168024c32852SRichard Henderson     }
1681e67db06eSJia Liu }
1682