xref: /qemu/target/openrisc/translate.c (revision 962a145c)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  * OpenRISC translation
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5fcf5ef2aSThomas Huth  *                         Feng Gao <gf91597@gmail.com>
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
10779fc6adSThomas Huth  * version 2.1 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15fcf5ef2aSThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth 
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "cpu.h"
23fcf5ef2aSThomas Huth #include "exec/exec-all.h"
24dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
25fcf5ef2aSThomas Huth #include "qemu/log.h"
26fcf5ef2aSThomas Huth #include "qemu/bitops.h"
2790c84c56SMarkus Armbruster #include "qemu/qemu-print.h"
2877fc6f5eSLluís Vilanova #include "exec/translator.h"
29fcf5ef2aSThomas Huth 
30fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
31fcf5ef2aSThomas Huth #include "exec/helper-gen.h"
32fcf5ef2aSThomas Huth 
33fcf5ef2aSThomas Huth #include "exec/log.h"
34fcf5ef2aSThomas Huth 
35d53106c9SRichard Henderson #define HELPER_H "helper.h"
36d53106c9SRichard Henderson #include "exec/helper-info.c.inc"
37d53106c9SRichard Henderson #undef  HELPER_H
38d53106c9SRichard Henderson 
39d53106c9SRichard Henderson 
4077fc6f5eSLluís Vilanova /* is_jmp field values */
4164e46c95SRichard Henderson #define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
428000ba56SRichard Henderson #define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
4377fc6f5eSLluís Vilanova 
44fcf5ef2aSThomas Huth typedef struct DisasContext {
451ffa4bceSEmilio G. Cota     DisasContextBase base;
46fcf5ef2aSThomas Huth     uint32_t mem_idx;
47a01deb36SRichard Henderson     uint32_t tb_flags;
48fcf5ef2aSThomas Huth     uint32_t delayed_branch;
49fe636d37SRichard Henderson     uint32_t cpucfgr;
502b13b4b9SRichard Henderson     uint32_t avr;
518000ba56SRichard Henderson 
528000ba56SRichard Henderson     /* If not -1, jmp_pc contains this value and so is a direct jump.  */
538000ba56SRichard Henderson     target_ulong jmp_pc_imm;
54d29f4368SRichard Henderson 
55d29f4368SRichard Henderson     /* The temporary corresponding to register 0 for this compilation.  */
56d29f4368SRichard Henderson     TCGv R0;
57118671f0SRichard Henderson     /* The constant zero. */
58118671f0SRichard Henderson     TCGv zero;
59fcf5ef2aSThomas Huth } DisasContext;
60fcf5ef2aSThomas Huth 
is_user(DisasContext * dc)612ba65417SRichard Henderson static inline bool is_user(DisasContext *dc)
622ba65417SRichard Henderson {
632ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY
642ba65417SRichard Henderson     return true;
652ba65417SRichard Henderson #else
66b9bed1b9SRichard Henderson     return !(dc->tb_flags & TB_FLAGS_SM);
672ba65417SRichard Henderson #endif
682ba65417SRichard Henderson }
692ba65417SRichard Henderson 
707de9729fSRichard Henderson /* Include the auto-generated decoder.  */
71abff1abfSPaolo Bonzini #include "decode-insns.c.inc"
727de9729fSRichard Henderson 
73fcf5ef2aSThomas Huth static TCGv cpu_sr;
748bba7619SRichard Henderson static TCGv cpu_regs[32];
75fcf5ef2aSThomas Huth static TCGv cpu_pc;
76fcf5ef2aSThomas Huth static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
77fcf5ef2aSThomas Huth static TCGv cpu_ppc;
7884775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
7997458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
8097458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
81930c3d00SRichard Henderson static TCGv cpu_lock_addr;
82930c3d00SRichard Henderson static TCGv cpu_lock_value;
83fcf5ef2aSThomas Huth static TCGv_i32 fpcsr;
846f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
85a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
86fcf5ef2aSThomas Huth 
openrisc_translate_init(void)87fcf5ef2aSThomas Huth void openrisc_translate_init(void)
88fcf5ef2aSThomas Huth {
89fcf5ef2aSThomas Huth     static const char * const regnames[] = {
90fcf5ef2aSThomas Huth         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
91fcf5ef2aSThomas Huth         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
92fcf5ef2aSThomas Huth         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
93fcf5ef2aSThomas Huth         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
94fcf5ef2aSThomas Huth     };
95fcf5ef2aSThomas Huth     int i;
96fcf5ef2aSThomas Huth 
97ad75a51eSRichard Henderson     cpu_sr = tcg_global_mem_new(tcg_env,
98fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, sr), "sr");
99ad75a51eSRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(tcg_env,
100a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
101a01deb36SRichard Henderson                                        "dflag");
102ad75a51eSRichard Henderson     cpu_pc = tcg_global_mem_new(tcg_env,
103fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, pc), "pc");
104ad75a51eSRichard Henderson     cpu_ppc = tcg_global_mem_new(tcg_env,
105fcf5ef2aSThomas Huth                                  offsetof(CPUOpenRISCState, ppc), "ppc");
106ad75a51eSRichard Henderson     jmp_pc = tcg_global_mem_new(tcg_env,
107fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
108ad75a51eSRichard Henderson     cpu_sr_f = tcg_global_mem_new(tcg_env,
10984775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
110ad75a51eSRichard Henderson     cpu_sr_cy = tcg_global_mem_new(tcg_env,
11197458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
112ad75a51eSRichard Henderson     cpu_sr_ov = tcg_global_mem_new(tcg_env,
11397458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
114ad75a51eSRichard Henderson     cpu_lock_addr = tcg_global_mem_new(tcg_env,
115930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
116930c3d00SRichard Henderson                                        "lock_addr");
117ad75a51eSRichard Henderson     cpu_lock_value = tcg_global_mem_new(tcg_env,
118930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
119930c3d00SRichard Henderson                                         "lock_value");
120ad75a51eSRichard Henderson     fpcsr = tcg_global_mem_new_i32(tcg_env,
121fcf5ef2aSThomas Huth                                    offsetof(CPUOpenRISCState, fpcsr),
122fcf5ef2aSThomas Huth                                    "fpcsr");
123ad75a51eSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(tcg_env,
1246f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1256f7332baSRichard Henderson                                      "mac");
126fcf5ef2aSThomas Huth     for (i = 0; i < 32; i++) {
127ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
128d89e71e8SStafford Horne                                          offsetof(CPUOpenRISCState,
129d89e71e8SStafford Horne                                                   shadow_gpr[0][i]),
130fcf5ef2aSThomas Huth                                          regnames[i]);
131fcf5ef2aSThomas Huth     }
132fcf5ef2aSThomas Huth }
133fcf5ef2aSThomas Huth 
gen_exception(DisasContext * dc,unsigned int excp)134fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, unsigned int excp)
135fcf5ef2aSThomas Huth {
136ad75a51eSRichard Henderson     gen_helper_exception(tcg_env, tcg_constant_i32(excp));
137fcf5ef2aSThomas Huth }
138fcf5ef2aSThomas Huth 
gen_illegal_exception(DisasContext * dc)139fcf5ef2aSThomas Huth static void gen_illegal_exception(DisasContext *dc)
140fcf5ef2aSThomas Huth {
1411ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
142fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_ILLEGAL);
1431ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
144fcf5ef2aSThomas Huth }
145fcf5ef2aSThomas Huth 
check_v1_3(DisasContext * dc)1462b13b4b9SRichard Henderson static bool check_v1_3(DisasContext *dc)
1472b13b4b9SRichard Henderson {
1482b13b4b9SRichard Henderson     return dc->avr >= 0x01030000;
1492b13b4b9SRichard Henderson }
1502b13b4b9SRichard Henderson 
check_of32s(DisasContext * dc)151fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc)
152fcf5ef2aSThomas Huth {
153fe636d37SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF32S;
154fcf5ef2aSThomas Huth }
155fcf5ef2aSThomas Huth 
check_of64a32s(DisasContext * dc)15662f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc)
15762f2b038SRichard Henderson {
15862f2b038SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF64A32S;
15962f2b038SRichard Henderson }
16062f2b038SRichard Henderson 
cpu_R(DisasContext * dc,int reg)1618bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg)
1628bba7619SRichard Henderson {
163d29f4368SRichard Henderson     if (reg == 0) {
164d29f4368SRichard Henderson         return dc->R0;
165d29f4368SRichard Henderson     } else {
1668bba7619SRichard Henderson         return cpu_regs[reg];
1678bba7619SRichard Henderson     }
168d29f4368SRichard Henderson }
1698bba7619SRichard Henderson 
170cdd0f459SRichard Henderson /*
171cdd0f459SRichard Henderson  * We're about to write to REG.  On the off-chance that the user is
172cdd0f459SRichard Henderson  * writing to R0, re-instate the architectural register.
173cdd0f459SRichard Henderson  */
check_r0_write(DisasContext * dc,int reg)174cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg)
175cdd0f459SRichard Henderson {
176cdd0f459SRichard Henderson     if (unlikely(reg == 0)) {
177d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
178cdd0f459SRichard Henderson     }
179cdd0f459SRichard Henderson }
1806597c28dSRichard Henderson 
gen_ove_cy(DisasContext * dc)18197458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1829ecaa27eSRichard Henderson {
1830c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
184ad75a51eSRichard Henderson         gen_helper_ove_cy(tcg_env);
1859ecaa27eSRichard Henderson     }
1860c53d734SRichard Henderson }
1879ecaa27eSRichard Henderson 
gen_ove_ov(DisasContext * dc)18897458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1899ecaa27eSRichard Henderson {
1900c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
191ad75a51eSRichard Henderson         gen_helper_ove_ov(tcg_env);
1929ecaa27eSRichard Henderson     }
1930c53d734SRichard Henderson }
1949ecaa27eSRichard Henderson 
gen_ove_cyov(DisasContext * dc)19597458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1969ecaa27eSRichard Henderson {
1970c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
198ad75a51eSRichard Henderson         gen_helper_ove_cyov(tcg_env);
1999ecaa27eSRichard Henderson     }
2000c53d734SRichard Henderson }
2019ecaa27eSRichard Henderson 
gen_add(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)2029ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2039ecaa27eSRichard Henderson {
204e0efc48fSRichard Henderson     TCGv t0 = tcg_temp_new();
2059ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2069ecaa27eSRichard Henderson 
207e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero);
20897458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2099ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
21097458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2119ecaa27eSRichard Henderson 
2129ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2139ecaa27eSRichard Henderson 
21497458071SRichard Henderson     gen_ove_cyov(dc);
2159ecaa27eSRichard Henderson }
2169ecaa27eSRichard Henderson 
gen_addc(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)2179ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2189ecaa27eSRichard Henderson {
219e0efc48fSRichard Henderson     TCGv t0 = tcg_temp_new();
2209ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2219ecaa27eSRichard Henderson 
222e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero);
223e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero);
22497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2259ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22697458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2279ecaa27eSRichard Henderson 
2289ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2299ecaa27eSRichard Henderson 
23097458071SRichard Henderson     gen_ove_cyov(dc);
2319ecaa27eSRichard Henderson }
2329ecaa27eSRichard Henderson 
gen_sub(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)2339ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2349ecaa27eSRichard Henderson {
2359ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2369ecaa27eSRichard Henderson 
2379ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
23897458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
23997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
24097458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
24197458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2429ecaa27eSRichard Henderson 
2439ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2449ecaa27eSRichard Henderson 
24597458071SRichard Henderson     gen_ove_cyov(dc);
2469ecaa27eSRichard Henderson }
2479ecaa27eSRichard Henderson 
gen_mul(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)2489ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2499ecaa27eSRichard Henderson {
2509ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2519ecaa27eSRichard Henderson 
25297458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2539ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
254cfe15887SRichard Henderson     tcg_gen_negsetcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2559ecaa27eSRichard Henderson 
25697458071SRichard Henderson     gen_ove_ov(dc);
2579ecaa27eSRichard Henderson }
2589ecaa27eSRichard Henderson 
gen_mulu(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)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 
gen_div(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)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.
2738b81968cSMichael Tokarev        Suppress 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 
27797458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
27897458071SRichard Henderson     gen_ove_ov(dc);
2799ecaa27eSRichard Henderson }
2809ecaa27eSRichard Henderson 
gen_divu(DisasContext * dc,TCGv dest,TCGv srca,TCGv srcb)2819ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2829ecaa27eSRichard Henderson {
2839ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2849ecaa27eSRichard Henderson 
28597458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2869ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2878b81968cSMichael Tokarev        Suppress the host-side exception by dividing by 1. */
28897458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2899ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2909ecaa27eSRichard Henderson 
29197458071SRichard Henderson     gen_ove_cy(dc);
2929ecaa27eSRichard Henderson }
293fcf5ef2aSThomas Huth 
gen_muld(DisasContext * dc,TCGv srca,TCGv srcb)294cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
295cc5de49eSRichard Henderson {
296cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
297cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
298cc5de49eSRichard Henderson 
299cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
300cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
301cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
302cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
303cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
304cc5de49eSRichard Henderson     } else {
305cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
306cc5de49eSRichard Henderson 
307cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
308cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
309cfe15887SRichard Henderson         tcg_gen_negsetcond_i64(TCG_COND_NE, t1, t1, high);
310cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
311cc5de49eSRichard Henderson 
312cc5de49eSRichard Henderson         gen_ove_ov(dc);
313cc5de49eSRichard Henderson     }
314cc5de49eSRichard Henderson }
315cc5de49eSRichard Henderson 
gen_muldu(DisasContext * dc,TCGv srca,TCGv srcb)316cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
317cc5de49eSRichard Henderson {
318cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
319cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
320cc5de49eSRichard Henderson 
321cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
322cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
323cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
324cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
325cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
326cc5de49eSRichard Henderson     } else {
327cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
328cc5de49eSRichard Henderson 
329cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
330cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
331cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
332cc5de49eSRichard Henderson 
333cc5de49eSRichard Henderson         gen_ove_cy(dc);
334cc5de49eSRichard Henderson     }
335cc5de49eSRichard Henderson }
336cc5de49eSRichard Henderson 
gen_mac(DisasContext * dc,TCGv srca,TCGv srcb)3376f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3386f7332baSRichard Henderson {
3396f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3406f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3416f7332baSRichard Henderson 
3426f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3436f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3446f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3456f7332baSRichard Henderson 
3466f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3476f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3486f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3496f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3506f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3516f7332baSRichard Henderson 
3526f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3536f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3546f7332baSRichard Henderson #else
3556f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3566f7332baSRichard Henderson #endif
3576f7332baSRichard Henderson 
3586f7332baSRichard Henderson     gen_ove_ov(dc);
3596f7332baSRichard Henderson }
3606f7332baSRichard Henderson 
gen_macu(DisasContext * dc,TCGv srca,TCGv srcb)361cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
362cc5de49eSRichard Henderson {
363cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
364cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
365cc5de49eSRichard Henderson 
366cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
367cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
368cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
369cc5de49eSRichard Henderson 
370cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
371cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
372cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
373cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
374cc5de49eSRichard Henderson 
375cc5de49eSRichard Henderson     gen_ove_cy(dc);
376cc5de49eSRichard Henderson }
377cc5de49eSRichard Henderson 
gen_msb(DisasContext * dc,TCGv srca,TCGv srcb)3786f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
3796f7332baSRichard Henderson {
3806f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3816f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3826f7332baSRichard Henderson 
3836f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3846f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3856f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3866f7332baSRichard Henderson 
3876f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
3886f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3896f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
3906f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3916f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
3926f7332baSRichard Henderson 
3936f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3946f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3956f7332baSRichard Henderson #else
3966f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3976f7332baSRichard Henderson #endif
3986f7332baSRichard Henderson 
3996f7332baSRichard Henderson     gen_ove_ov(dc);
4006f7332baSRichard Henderson }
4016f7332baSRichard Henderson 
gen_msbu(DisasContext * dc,TCGv srca,TCGv srcb)402cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
403cc5de49eSRichard Henderson {
404cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
405cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
406cc5de49eSRichard Henderson 
407cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
408cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
409cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
410cc5de49eSRichard Henderson 
411cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
412cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
413cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
414cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
415cc5de49eSRichard Henderson 
416cc5de49eSRichard Henderson     gen_ove_cy(dc);
417cc5de49eSRichard Henderson }
418cc5de49eSRichard Henderson 
trans_l_add(DisasContext * dc,arg_dab * a)4193a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
420fcf5ef2aSThomas Huth {
421cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4228bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4236ad216abSRichard Henderson     return true;
424fcf5ef2aSThomas Huth }
425fcf5ef2aSThomas Huth 
trans_l_addc(DisasContext * dc,arg_dab * a)4263a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
427fcf5ef2aSThomas Huth {
428cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4298bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4306ad216abSRichard Henderson     return true;
4316ad216abSRichard Henderson }
4326ad216abSRichard Henderson 
trans_l_sub(DisasContext * dc,arg_dab * a)4333a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4346ad216abSRichard Henderson {
435cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4368bba7619SRichard Henderson     gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4376ad216abSRichard Henderson     return true;
4386ad216abSRichard Henderson }
4396ad216abSRichard Henderson 
trans_l_and(DisasContext * dc,arg_dab * a)4403a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4416ad216abSRichard Henderson {
442cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4438bba7619SRichard Henderson     tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4446ad216abSRichard Henderson     return true;
4456ad216abSRichard Henderson }
4466ad216abSRichard Henderson 
trans_l_or(DisasContext * dc,arg_dab * a)4473a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4486ad216abSRichard Henderson {
449cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4508bba7619SRichard Henderson     tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4516ad216abSRichard Henderson     return true;
4526ad216abSRichard Henderson }
4536ad216abSRichard Henderson 
trans_l_xor(DisasContext * dc,arg_dab * a)4543a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4556ad216abSRichard Henderson {
456cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4578bba7619SRichard Henderson     tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4586ad216abSRichard Henderson     return true;
4596ad216abSRichard Henderson }
4606ad216abSRichard Henderson 
trans_l_sll(DisasContext * dc,arg_dab * a)4613a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4626ad216abSRichard Henderson {
463cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4648bba7619SRichard Henderson     tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4656ad216abSRichard Henderson     return true;
4666ad216abSRichard Henderson }
4676ad216abSRichard Henderson 
trans_l_srl(DisasContext * dc,arg_dab * a)4683a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4696ad216abSRichard Henderson {
470cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4718bba7619SRichard Henderson     tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4726ad216abSRichard Henderson     return true;
4736ad216abSRichard Henderson }
4746ad216abSRichard Henderson 
trans_l_sra(DisasContext * dc,arg_dab * a)4753a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
4766ad216abSRichard Henderson {
477cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4788bba7619SRichard Henderson     tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4796ad216abSRichard Henderson     return true;
4806ad216abSRichard Henderson }
4816ad216abSRichard Henderson 
trans_l_ror(DisasContext * dc,arg_dab * a)4823a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
4836ad216abSRichard Henderson {
484cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4858bba7619SRichard Henderson     tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4866ad216abSRichard Henderson     return true;
4876ad216abSRichard Henderson }
4886ad216abSRichard Henderson 
trans_l_exths(DisasContext * dc,arg_da * a)4893a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
4906ad216abSRichard Henderson {
491cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4928bba7619SRichard Henderson     tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
4936ad216abSRichard Henderson     return true;
4946ad216abSRichard Henderson }
4956ad216abSRichard Henderson 
trans_l_extbs(DisasContext * dc,arg_da * a)4963a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
4976ad216abSRichard Henderson {
498cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4998bba7619SRichard Henderson     tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5006ad216abSRichard Henderson     return true;
5016ad216abSRichard Henderson }
5026ad216abSRichard Henderson 
trans_l_exthz(DisasContext * dc,arg_da * a)5033a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5046ad216abSRichard Henderson {
505cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5068bba7619SRichard Henderson     tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5076ad216abSRichard Henderson     return true;
5086ad216abSRichard Henderson }
5096ad216abSRichard Henderson 
trans_l_extbz(DisasContext * dc,arg_da * a)5103a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5116ad216abSRichard Henderson {
512cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5138bba7619SRichard Henderson     tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5146ad216abSRichard Henderson     return true;
5156ad216abSRichard Henderson }
5166ad216abSRichard Henderson 
trans_l_cmov(DisasContext * dc,arg_dab * a)5173a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5186ad216abSRichard Henderson {
519cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
520118671f0SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero,
5218bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
5226ad216abSRichard Henderson     return true;
523fcf5ef2aSThomas Huth }
524fcf5ef2aSThomas Huth 
trans_l_ff1(DisasContext * dc,arg_da * a)5253a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5266ad216abSRichard Henderson {
527cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5288bba7619SRichard Henderson     tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
5298bba7619SRichard Henderson     tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
5306ad216abSRichard Henderson     return true;
531cf2ae442SRichard Henderson }
532cf2ae442SRichard Henderson 
trans_l_fl1(DisasContext * dc,arg_da * a)5333a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5346ad216abSRichard Henderson {
535cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5368bba7619SRichard Henderson     tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
5378bba7619SRichard Henderson     tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
5386ad216abSRichard Henderson     return true;
539fcf5ef2aSThomas Huth }
540fcf5ef2aSThomas Huth 
trans_l_mul(DisasContext * dc,arg_dab * a)5413a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5426ad216abSRichard Henderson {
543cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5448bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5456ad216abSRichard Henderson     return true;
546fcf5ef2aSThomas Huth }
5476ad216abSRichard Henderson 
trans_l_mulu(DisasContext * dc,arg_dab * a)5483a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5496ad216abSRichard Henderson {
550cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5518bba7619SRichard Henderson     gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5526ad216abSRichard Henderson     return true;
553fcf5ef2aSThomas Huth }
5546ad216abSRichard Henderson 
trans_l_div(DisasContext * dc,arg_dab * a)5553a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5566ad216abSRichard Henderson {
557cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5588bba7619SRichard Henderson     gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5596ad216abSRichard Henderson     return true;
5606ad216abSRichard Henderson }
5616ad216abSRichard Henderson 
trans_l_divu(DisasContext * dc,arg_dab * a)5623a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5636ad216abSRichard Henderson {
564cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5658bba7619SRichard Henderson     gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5666ad216abSRichard Henderson     return true;
5676ad216abSRichard Henderson }
5686ad216abSRichard Henderson 
trans_l_muld(DisasContext * dc,arg_ab * a)5693a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5706ad216abSRichard Henderson {
5718bba7619SRichard Henderson     gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5726ad216abSRichard Henderson     return true;
5736ad216abSRichard Henderson }
5746ad216abSRichard Henderson 
trans_l_muldu(DisasContext * dc,arg_ab * a)5753a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
5766ad216abSRichard Henderson {
5778bba7619SRichard Henderson     gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5786ad216abSRichard Henderson     return true;
579fcf5ef2aSThomas Huth }
580fcf5ef2aSThomas Huth 
trans_l_j(DisasContext * dc,arg_l_j * a)5813a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
582136e13aeSRichard Henderson {
583136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
584136e13aeSRichard Henderson 
585136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
5868000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
587136e13aeSRichard Henderson     dc->delayed_branch = 2;
588136e13aeSRichard Henderson     return true;
589136e13aeSRichard Henderson }
590136e13aeSRichard Henderson 
trans_l_jal(DisasContext * dc,arg_l_jal * a)5913a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
592136e13aeSRichard Henderson {
593136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
594136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
595136e13aeSRichard Henderson 
5968bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], ret_pc);
597136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
598136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
599136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6008000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
601136e13aeSRichard Henderson         dc->delayed_branch = 2;
602136e13aeSRichard Henderson     }
603136e13aeSRichard Henderson     return true;
604136e13aeSRichard Henderson }
605136e13aeSRichard Henderson 
do_bf(DisasContext * dc,arg_l_bf * a,TCGCond cond)606136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
607136e13aeSRichard Henderson {
608136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
609af42d354SRichard Henderson     TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8);
610af42d354SRichard Henderson     TCGv t_true = tcg_constant_tl(tmp_pc);
611136e13aeSRichard Henderson 
612118671f0SRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next);
613136e13aeSRichard Henderson     dc->delayed_branch = 2;
614136e13aeSRichard Henderson }
615136e13aeSRichard Henderson 
trans_l_bf(DisasContext * dc,arg_l_bf * a)6163a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
617136e13aeSRichard Henderson {
618136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
619136e13aeSRichard Henderson     return true;
620136e13aeSRichard Henderson }
621136e13aeSRichard Henderson 
trans_l_bnf(DisasContext * dc,arg_l_bf * a)6223a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
623136e13aeSRichard Henderson {
624136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
625136e13aeSRichard Henderson     return true;
626136e13aeSRichard Henderson }
627136e13aeSRichard Henderson 
trans_l_jr(DisasContext * dc,arg_l_jr * a)6283a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
629136e13aeSRichard Henderson {
6308bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
631136e13aeSRichard Henderson     dc->delayed_branch = 2;
632136e13aeSRichard Henderson     return true;
633136e13aeSRichard Henderson }
634136e13aeSRichard Henderson 
trans_l_jalr(DisasContext * dc,arg_l_jalr * a)6353a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
636136e13aeSRichard Henderson {
6378bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
6388bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
639136e13aeSRichard Henderson     dc->delayed_branch = 2;
640136e13aeSRichard Henderson     return true;
641136e13aeSRichard Henderson }
642136e13aeSRichard Henderson 
trans_l_lwa(DisasContext * dc,arg_load * a)6433a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
644d80bff19SRichard Henderson {
645d80bff19SRichard Henderson     TCGv ea;
646d80bff19SRichard Henderson 
647cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
648d80bff19SRichard Henderson     ea = tcg_temp_new();
6498bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6508bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
651d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
6528bba7619SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
653d80bff19SRichard Henderson     return true;
654d80bff19SRichard Henderson }
655d80bff19SRichard Henderson 
do_load(DisasContext * dc,arg_load * a,MemOp mop)65614776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
657d80bff19SRichard Henderson {
658d80bff19SRichard Henderson     TCGv ea;
659d80bff19SRichard Henderson 
660cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
661d80bff19SRichard Henderson     ea = tcg_temp_new();
6628bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6638bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
664d80bff19SRichard Henderson }
665d80bff19SRichard Henderson 
trans_l_lwz(DisasContext * dc,arg_load * a)6663a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
667d80bff19SRichard Henderson {
668d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
669d80bff19SRichard Henderson     return true;
670d80bff19SRichard Henderson }
671d80bff19SRichard Henderson 
trans_l_lws(DisasContext * dc,arg_load * a)6723a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
673d80bff19SRichard Henderson {
674d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
675d80bff19SRichard Henderson     return true;
676d80bff19SRichard Henderson }
677d80bff19SRichard Henderson 
trans_l_lbz(DisasContext * dc,arg_load * a)6783a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
679d80bff19SRichard Henderson {
680d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
681d80bff19SRichard Henderson     return true;
682d80bff19SRichard Henderson }
683d80bff19SRichard Henderson 
trans_l_lbs(DisasContext * dc,arg_load * a)6843a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
685d80bff19SRichard Henderson {
686d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
687d80bff19SRichard Henderson     return true;
688d80bff19SRichard Henderson }
689d80bff19SRichard Henderson 
trans_l_lhz(DisasContext * dc,arg_load * a)6903a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
691d80bff19SRichard Henderson {
692d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
693d80bff19SRichard Henderson     return true;
694d80bff19SRichard Henderson }
695d80bff19SRichard Henderson 
trans_l_lhs(DisasContext * dc,arg_load * a)6963a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
697d80bff19SRichard Henderson {
698d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
699d80bff19SRichard Henderson     return true;
700d80bff19SRichard Henderson }
701d80bff19SRichard Henderson 
trans_l_swa(DisasContext * dc,arg_store * a)7023a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
703d80bff19SRichard Henderson {
704d80bff19SRichard Henderson     TCGv ea, val;
705d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
706d80bff19SRichard Henderson 
707d80bff19SRichard Henderson     ea = tcg_temp_new();
7088bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
709d80bff19SRichard Henderson 
710d80bff19SRichard Henderson     lab_fail = gen_new_label();
711d80bff19SRichard Henderson     lab_done = gen_new_label();
712d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
713d80bff19SRichard Henderson 
714d80bff19SRichard Henderson     val = tcg_temp_new();
715d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
7164d10fa0fSRichard Henderson                               cpu_R(dc, a->b), dc->mem_idx, MO_TEUL);
717d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
718d80bff19SRichard Henderson 
719d80bff19SRichard Henderson     tcg_gen_br(lab_done);
720d80bff19SRichard Henderson 
721d80bff19SRichard Henderson     gen_set_label(lab_fail);
722d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
723d80bff19SRichard Henderson 
724d80bff19SRichard Henderson     gen_set_label(lab_done);
725d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
726d80bff19SRichard Henderson     return true;
727d80bff19SRichard Henderson }
728d80bff19SRichard Henderson 
do_store(DisasContext * dc,arg_store * a,MemOp mop)72914776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
730d80bff19SRichard Henderson {
731d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
7328bba7619SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
7338bba7619SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
734d80bff19SRichard Henderson }
735d80bff19SRichard Henderson 
trans_l_sw(DisasContext * dc,arg_store * a)7363a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
737d80bff19SRichard Henderson {
738d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
739d80bff19SRichard Henderson     return true;
740d80bff19SRichard Henderson }
741d80bff19SRichard Henderson 
trans_l_sb(DisasContext * dc,arg_store * a)7423a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
743d80bff19SRichard Henderson {
744d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
745d80bff19SRichard Henderson     return true;
746d80bff19SRichard Henderson }
747d80bff19SRichard Henderson 
trans_l_sh(DisasContext * dc,arg_store * a)7483a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
749d80bff19SRichard Henderson {
750d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
751d80bff19SRichard Henderson     return true;
752d80bff19SRichard Henderson }
753d80bff19SRichard Henderson 
trans_l_nop(DisasContext * dc,arg_l_nop * a)7543a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
755fcf5ef2aSThomas Huth {
7568816f70bSRichard Henderson     return true;
7578816f70bSRichard Henderson }
7588816f70bSRichard Henderson 
trans_l_adrp(DisasContext * dc,arg_l_adrp * a)7593e0e41efSRichard Henderson static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a)
7603e0e41efSRichard Henderson {
7613e0e41efSRichard Henderson     if (!check_v1_3(dc)) {
7623e0e41efSRichard Henderson         return false;
7633e0e41efSRichard Henderson     }
7643e0e41efSRichard Henderson     check_r0_write(dc, a->d);
7653e0e41efSRichard Henderson 
7663e0e41efSRichard Henderson     tcg_gen_movi_i32(cpu_R(dc, a->d),
7673e0e41efSRichard Henderson                      (dc->base.pc_next & TARGET_PAGE_MASK) +
7683e0e41efSRichard Henderson                      ((target_long)a->i << TARGET_PAGE_BITS));
7693e0e41efSRichard Henderson     return true;
7703e0e41efSRichard Henderson }
7713e0e41efSRichard Henderson 
trans_l_addi(DisasContext * dc,arg_rri * a)7723a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
7738816f70bSRichard Henderson {
774cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
775af42d354SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7768816f70bSRichard Henderson     return true;
7778816f70bSRichard Henderson }
778fcf5ef2aSThomas Huth 
trans_l_addic(DisasContext * dc,arg_rri * a)7793a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
780fcf5ef2aSThomas Huth {
781cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
782af42d354SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7838816f70bSRichard Henderson     return true;
7848816f70bSRichard Henderson }
7858816f70bSRichard Henderson 
trans_l_muli(DisasContext * dc,arg_rri * a)7863a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
7878816f70bSRichard Henderson {
788cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
789af42d354SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7908816f70bSRichard Henderson     return true;
7918816f70bSRichard Henderson }
7928816f70bSRichard Henderson 
trans_l_maci(DisasContext * dc,arg_l_maci * a)7933a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
7948816f70bSRichard Henderson {
795af42d354SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i));
7968816f70bSRichard Henderson     return true;
7978816f70bSRichard Henderson }
7988816f70bSRichard Henderson 
trans_l_andi(DisasContext * dc,arg_rrk * a)7993a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8008816f70bSRichard Henderson {
801cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8028bba7619SRichard Henderson     tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8038816f70bSRichard Henderson     return true;
8048816f70bSRichard Henderson }
8058816f70bSRichard Henderson 
trans_l_ori(DisasContext * dc,arg_rrk * a)8063a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8078816f70bSRichard Henderson {
808cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8098bba7619SRichard Henderson     tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8108816f70bSRichard Henderson     return true;
8118816f70bSRichard Henderson }
8128816f70bSRichard Henderson 
trans_l_xori(DisasContext * dc,arg_rri * a)8133a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8148816f70bSRichard Henderson {
815cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8168bba7619SRichard Henderson     tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
8178816f70bSRichard Henderson     return true;
8188816f70bSRichard Henderson }
8198816f70bSRichard Henderson 
trans_l_mfspr(DisasContext * dc,arg_l_mfspr * a)8203a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8218816f70bSRichard Henderson {
822c28fa81fSRichard Henderson     TCGv spr = tcg_temp_new();
823b9e40bacSPavel Dovgalyuk 
82408f021deSStafford Horne     check_r0_write(dc, a->d);
82508f021deSStafford Horne 
826dfd1b812SRichard Henderson     if (translator_io_start(&dc->base)) {
827b9e40bacSPavel Dovgalyuk         if (dc->delayed_branch) {
828b9e40bacSPavel Dovgalyuk             tcg_gen_mov_tl(cpu_pc, jmp_pc);
829b9e40bacSPavel Dovgalyuk             tcg_gen_discard_tl(jmp_pc);
830b9e40bacSPavel Dovgalyuk         } else {
831b9e40bacSPavel Dovgalyuk             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
832b9e40bacSPavel Dovgalyuk         }
833b9e40bacSPavel Dovgalyuk         dc->base.is_jmp = DISAS_EXIT;
834b9e40bacSPavel Dovgalyuk     }
835b9e40bacSPavel Dovgalyuk 
8368bba7619SRichard Henderson     tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
837ad75a51eSRichard Henderson     gen_helper_mfspr(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d), spr);
8388816f70bSRichard Henderson     return true;
8398816f70bSRichard Henderson }
840fcf5ef2aSThomas Huth 
trans_l_mtspr(DisasContext * dc,arg_l_mtspr * a)8413a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
842fcf5ef2aSThomas Huth {
84308f021deSStafford Horne     TCGv spr = tcg_temp_new();
84401ec3ec9SRichard Henderson 
845dfd1b812SRichard Henderson     translator_io_start(&dc->base);
846dfd1b812SRichard Henderson 
84708f021deSStafford Horne     /*
84808f021deSStafford Horne      * For SR, we will need to exit the TB to recognize the new
84901ec3ec9SRichard Henderson      * exception state.  For NPC, in theory this counts as a branch
85001ec3ec9SRichard Henderson      * (although the SPR only exists for use by an ICE).  Save all
85101ec3ec9SRichard Henderson      * of the cpu state first, allowing it to be overwritten.
85201ec3ec9SRichard Henderson      */
85301ec3ec9SRichard Henderson     if (dc->delayed_branch) {
85401ec3ec9SRichard Henderson         tcg_gen_mov_tl(cpu_pc, jmp_pc);
85501ec3ec9SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
85601ec3ec9SRichard Henderson     } else {
85701ec3ec9SRichard Henderson         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
85801ec3ec9SRichard Henderson     }
85901ec3ec9SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
86001ec3ec9SRichard Henderson 
8618bba7619SRichard Henderson     tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
862ad75a51eSRichard Henderson     gen_helper_mtspr(tcg_env, spr, cpu_R(dc, a->b));
8638816f70bSRichard Henderson     return true;
864fcf5ef2aSThomas Huth }
865fcf5ef2aSThomas Huth 
trans_l_mac(DisasContext * dc,arg_ab * a)8663a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
867fcf5ef2aSThomas Huth {
8688bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
86999d863d6SRichard Henderson     return true;
870fcf5ef2aSThomas Huth }
87199d863d6SRichard Henderson 
trans_l_msb(DisasContext * dc,arg_ab * a)8723a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
87399d863d6SRichard Henderson {
8748bba7619SRichard Henderson     gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
87599d863d6SRichard Henderson     return true;
87699d863d6SRichard Henderson }
87799d863d6SRichard Henderson 
trans_l_macu(DisasContext * dc,arg_ab * a)8783a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
87999d863d6SRichard Henderson {
8808bba7619SRichard Henderson     gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
88199d863d6SRichard Henderson     return true;
88299d863d6SRichard Henderson }
88399d863d6SRichard Henderson 
trans_l_msbu(DisasContext * dc,arg_ab * a)8843a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
88599d863d6SRichard Henderson {
8868bba7619SRichard Henderson     gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
88799d863d6SRichard Henderson     return true;
888fcf5ef2aSThomas Huth }
889fcf5ef2aSThomas Huth 
trans_l_slli(DisasContext * dc,arg_dal * a)8903a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
891fcf5ef2aSThomas Huth {
892cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8938bba7619SRichard Henderson     tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
8948bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
895e20c2592SRichard Henderson     return true;
896fcf5ef2aSThomas Huth }
897e20c2592SRichard Henderson 
trans_l_srli(DisasContext * dc,arg_dal * a)8983a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
899e20c2592SRichard Henderson {
900cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9018bba7619SRichard Henderson     tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9028bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
903e20c2592SRichard Henderson     return true;
904e20c2592SRichard Henderson }
905e20c2592SRichard Henderson 
trans_l_srai(DisasContext * dc,arg_dal * a)9063a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
907e20c2592SRichard Henderson {
908cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9098bba7619SRichard Henderson     tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9108bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
911e20c2592SRichard Henderson     return true;
912e20c2592SRichard Henderson }
913e20c2592SRichard Henderson 
trans_l_rori(DisasContext * dc,arg_dal * a)9143a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
915e20c2592SRichard Henderson {
916cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9178bba7619SRichard Henderson     tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9188bba7619SRichard Henderson                      a->l & (TARGET_LONG_BITS - 1));
919e20c2592SRichard Henderson     return true;
920fcf5ef2aSThomas Huth }
921fcf5ef2aSThomas Huth 
trans_l_movhi(DisasContext * dc,arg_l_movhi * a)9223a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
923fcf5ef2aSThomas Huth {
924cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9258bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
926e720a571SRichard Henderson     return true;
927fcf5ef2aSThomas Huth }
928e720a571SRichard Henderson 
trans_l_macrc(DisasContext * dc,arg_l_macrc * a)9293a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
930e720a571SRichard Henderson {
931cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9328bba7619SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
933e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
934e720a571SRichard Henderson     return true;
935fcf5ef2aSThomas Huth }
936fcf5ef2aSThomas Huth 
trans_l_sfeq(DisasContext * dc,arg_ab * a)9373a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
938fcf5ef2aSThomas Huth {
9398bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
9408bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
941fbb3e29aSRichard Henderson     return true;
942fcf5ef2aSThomas Huth }
943fbb3e29aSRichard Henderson 
trans_l_sfne(DisasContext * dc,arg_ab * a)9443a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
945fbb3e29aSRichard Henderson {
9468bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
9478bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
948fbb3e29aSRichard Henderson     return true;
949fbb3e29aSRichard Henderson }
950fbb3e29aSRichard Henderson 
trans_l_sfgtu(DisasContext * dc,arg_ab * a)9513a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
952fbb3e29aSRichard Henderson {
9538bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
9548bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
955fbb3e29aSRichard Henderson     return true;
956fbb3e29aSRichard Henderson }
957fbb3e29aSRichard Henderson 
trans_l_sfgeu(DisasContext * dc,arg_ab * a)9583a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
959fbb3e29aSRichard Henderson {
9608bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
9618bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
962fbb3e29aSRichard Henderson     return true;
963fbb3e29aSRichard Henderson }
964fbb3e29aSRichard Henderson 
trans_l_sfltu(DisasContext * dc,arg_ab * a)9653a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
966fbb3e29aSRichard Henderson {
9678bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
9688bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
969fbb3e29aSRichard Henderson     return true;
970fbb3e29aSRichard Henderson }
971fbb3e29aSRichard Henderson 
trans_l_sfleu(DisasContext * dc,arg_ab * a)9723a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
973fbb3e29aSRichard Henderson {
9748bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
9758bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
976fbb3e29aSRichard Henderson     return true;
977fbb3e29aSRichard Henderson }
978fbb3e29aSRichard Henderson 
trans_l_sfgts(DisasContext * dc,arg_ab * a)9793a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
980fbb3e29aSRichard Henderson {
9818bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
9828bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
983fbb3e29aSRichard Henderson     return true;
984fbb3e29aSRichard Henderson }
985fbb3e29aSRichard Henderson 
trans_l_sfges(DisasContext * dc,arg_ab * a)9863a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
987fbb3e29aSRichard Henderson {
9888bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
9898bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
990fbb3e29aSRichard Henderson     return true;
991fbb3e29aSRichard Henderson }
992fbb3e29aSRichard Henderson 
trans_l_sflts(DisasContext * dc,arg_ab * a)9933a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
994fbb3e29aSRichard Henderson {
9958bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
9968bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
997fbb3e29aSRichard Henderson     return true;
998fbb3e29aSRichard Henderson }
999fbb3e29aSRichard Henderson 
trans_l_sfles(DisasContext * dc,arg_ab * a)10003a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1001fbb3e29aSRichard Henderson {
10028bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE,
10038bba7619SRichard Henderson                        cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1004fbb3e29aSRichard Henderson     return true;
1005fcf5ef2aSThomas Huth }
1006fcf5ef2aSThomas Huth 
trans_l_sfeqi(DisasContext * dc,arg_ai * a)10073a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1008fcf5ef2aSThomas Huth {
10098bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1010032de4fcSRichard Henderson     return true;
1011fcf5ef2aSThomas Huth }
1012032de4fcSRichard Henderson 
trans_l_sfnei(DisasContext * dc,arg_ai * a)10133a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1014032de4fcSRichard Henderson {
10158bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1016032de4fcSRichard Henderson     return true;
1017032de4fcSRichard Henderson }
1018032de4fcSRichard Henderson 
trans_l_sfgtui(DisasContext * dc,arg_ai * a)10193a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1020032de4fcSRichard Henderson {
10218bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1022032de4fcSRichard Henderson     return true;
1023032de4fcSRichard Henderson }
1024032de4fcSRichard Henderson 
trans_l_sfgeui(DisasContext * dc,arg_ai * a)10253a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1026032de4fcSRichard Henderson {
10278bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1028032de4fcSRichard Henderson     return true;
1029032de4fcSRichard Henderson }
1030032de4fcSRichard Henderson 
trans_l_sfltui(DisasContext * dc,arg_ai * a)10313a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1032032de4fcSRichard Henderson {
10338bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1034032de4fcSRichard Henderson     return true;
1035032de4fcSRichard Henderson }
1036032de4fcSRichard Henderson 
trans_l_sfleui(DisasContext * dc,arg_ai * a)10373a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1038032de4fcSRichard Henderson {
10398bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1040032de4fcSRichard Henderson     return true;
1041032de4fcSRichard Henderson }
1042032de4fcSRichard Henderson 
trans_l_sfgtsi(DisasContext * dc,arg_ai * a)10433a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1044032de4fcSRichard Henderson {
10458bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1046032de4fcSRichard Henderson     return true;
1047032de4fcSRichard Henderson }
1048032de4fcSRichard Henderson 
trans_l_sfgesi(DisasContext * dc,arg_ai * a)10493a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1050032de4fcSRichard Henderson {
10518bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1052032de4fcSRichard Henderson     return true;
1053032de4fcSRichard Henderson }
1054032de4fcSRichard Henderson 
trans_l_sfltsi(DisasContext * dc,arg_ai * a)10553a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1056032de4fcSRichard Henderson {
10578bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1058032de4fcSRichard Henderson     return true;
1059032de4fcSRichard Henderson }
1060032de4fcSRichard Henderson 
trans_l_sflesi(DisasContext * dc,arg_ai * a)10613a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1062032de4fcSRichard Henderson {
10638bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1064032de4fcSRichard Henderson     return true;
1065fcf5ef2aSThomas Huth }
1066fcf5ef2aSThomas Huth 
trans_l_sys(DisasContext * dc,arg_l_sys * a)10673a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1068fcf5ef2aSThomas Huth {
10691ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1070fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_SYSCALL);
10711ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
10727de9729fSRichard Henderson     return true;
10737de9729fSRichard Henderson }
1074fcf5ef2aSThomas Huth 
trans_l_trap(DisasContext * dc,arg_l_trap * a)10753a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
10767de9729fSRichard Henderson {
10771ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1078fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_TRAP);
10791ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
10807de9729fSRichard Henderson     return true;
10817de9729fSRichard Henderson }
1082fcf5ef2aSThomas Huth 
trans_l_msync(DisasContext * dc,arg_l_msync * a)10833a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
10847de9729fSRichard Henderson {
108524fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
10867de9729fSRichard Henderson     return true;
1087fcf5ef2aSThomas Huth }
10887de9729fSRichard Henderson 
trans_l_psync(DisasContext * dc,arg_l_psync * a)10893a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
10907de9729fSRichard Henderson {
10917de9729fSRichard Henderson     return true;
10927de9729fSRichard Henderson }
10937de9729fSRichard Henderson 
trans_l_csync(DisasContext * dc,arg_l_csync * a)10943a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
10957de9729fSRichard Henderson {
10967de9729fSRichard Henderson     return true;
1097fcf5ef2aSThomas Huth }
1098fcf5ef2aSThomas Huth 
trans_l_rfe(DisasContext * dc,arg_l_rfe * a)10993a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11008816f70bSRichard Henderson {
11012ba65417SRichard Henderson     if (is_user(dc)) {
11028816f70bSRichard Henderson         gen_illegal_exception(dc);
11038816f70bSRichard Henderson     } else {
1104ad75a51eSRichard Henderson         gen_helper_rfe(tcg_env);
110564e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11068816f70bSRichard Henderson     }
11078816f70bSRichard Henderson     return true;
11088816f70bSRichard Henderson }
11098816f70bSRichard Henderson 
do_fp2(DisasContext * dc,arg_da * a,void (* fn)(TCGv,TCGv_env,TCGv))1110fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a,
11116fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1112fcf5ef2aSThomas Huth {
1113fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1114fe636d37SRichard Henderson         return false;
1115fe636d37SRichard Henderson     }
1116cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1117ad75a51eSRichard Henderson     fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a));
1118ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1119fe636d37SRichard Henderson     return true;
1120fcf5ef2aSThomas Huth }
11216fd204a2SRichard Henderson 
do_fp3(DisasContext * dc,arg_dab * a,void (* fn)(TCGv,TCGv_env,TCGv,TCGv))1122fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a,
11236fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11246fd204a2SRichard Henderson {
1125fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1126fe636d37SRichard Henderson         return false;
1127fe636d37SRichard Henderson     }
1128cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1129ad75a51eSRichard Henderson     fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
1130ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1131fe636d37SRichard Henderson     return true;
11326fd204a2SRichard Henderson }
11336fd204a2SRichard Henderson 
do_fpcmp(DisasContext * dc,arg_ab * a,void (* fn)(TCGv,TCGv_env,TCGv,TCGv),bool inv,bool swap)1134fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a,
11356fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11366fd204a2SRichard Henderson                      bool inv, bool swap)
11376fd204a2SRichard Henderson {
1138fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1139fe636d37SRichard Henderson         return false;
1140fe636d37SRichard Henderson     }
11416fd204a2SRichard Henderson     if (swap) {
1142ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
11436fd204a2SRichard Henderson     } else {
1144ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11456fd204a2SRichard Henderson     }
11466fd204a2SRichard Henderson     if (inv) {
11476fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11486fd204a2SRichard Henderson     }
1149ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1150fe636d37SRichard Henderson     return true;
11516fd204a2SRichard Henderson }
11526fd204a2SRichard Henderson 
trans_lf_add_s(DisasContext * dc,arg_dab * a)11533a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11546fd204a2SRichard Henderson {
1155fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_add_s);
11566fd204a2SRichard Henderson }
11576fd204a2SRichard Henderson 
trans_lf_sub_s(DisasContext * dc,arg_dab * a)11583a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11596fd204a2SRichard Henderson {
1160fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_sub_s);
11616fd204a2SRichard Henderson }
11626fd204a2SRichard Henderson 
trans_lf_mul_s(DisasContext * dc,arg_dab * a)11633a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
11646fd204a2SRichard Henderson {
1165fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_mul_s);
11666fd204a2SRichard Henderson }
11676fd204a2SRichard Henderson 
trans_lf_div_s(DisasContext * dc,arg_dab * a)11683a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
11696fd204a2SRichard Henderson {
1170fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_div_s);
11716fd204a2SRichard Henderson }
11726fd204a2SRichard Henderson 
trans_lf_rem_s(DisasContext * dc,arg_dab * a)11733a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
11746fd204a2SRichard Henderson {
1175fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_rem_s);
11766fd204a2SRichard Henderson     return true;
11776fd204a2SRichard Henderson }
11786fd204a2SRichard Henderson 
trans_lf_itof_s(DisasContext * dc,arg_da * a)11793a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
11806fd204a2SRichard Henderson {
1181fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_itofs);
11826fd204a2SRichard Henderson }
11836fd204a2SRichard Henderson 
trans_lf_ftoi_s(DisasContext * dc,arg_da * a)11843a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
11856fd204a2SRichard Henderson {
1186fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_ftois);
11876fd204a2SRichard Henderson }
11886fd204a2SRichard Henderson 
trans_lf_madd_s(DisasContext * dc,arg_dab * a)11893a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
11906fd204a2SRichard Henderson {
1191fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1192fe636d37SRichard Henderson         return false;
1193fe636d37SRichard Henderson     }
1194cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1195ad75a51eSRichard Henderson     gen_helper_float_madd_s(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d),
11968bba7619SRichard Henderson                             cpu_R(dc, a->a), cpu_R(dc, a->b));
1197ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
11986fd204a2SRichard Henderson     return true;
11996fd204a2SRichard Henderson }
12006fd204a2SRichard Henderson 
trans_lf_sfeq_s(DisasContext * dc,arg_ab * a)12013a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12026fd204a2SRichard Henderson {
1203fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12046fd204a2SRichard Henderson }
12056fd204a2SRichard Henderson 
trans_lf_sfne_s(DisasContext * dc,arg_ab * a)12063a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12076fd204a2SRichard Henderson {
1208fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12096fd204a2SRichard Henderson }
12106fd204a2SRichard Henderson 
trans_lf_sfgt_s(DisasContext * dc,arg_ab * a)12113a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12126fd204a2SRichard Henderson {
1213fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12146fd204a2SRichard Henderson }
12156fd204a2SRichard Henderson 
trans_lf_sfge_s(DisasContext * dc,arg_ab * a)12163a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12176fd204a2SRichard Henderson {
1218fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12196fd204a2SRichard Henderson }
12206fd204a2SRichard Henderson 
trans_lf_sflt_s(DisasContext * dc,arg_ab * a)12213a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12226fd204a2SRichard Henderson {
1223fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12246fd204a2SRichard Henderson }
12256fd204a2SRichard Henderson 
trans_lf_sfle_s(DisasContext * dc,arg_ab * a)12263a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12276fd204a2SRichard Henderson {
1228fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1229fcf5ef2aSThomas Huth }
1230fcf5ef2aSThomas Huth 
trans_lf_sfueq_s(DisasContext * dc,arg_ab * a)12312b13b4b9SRichard Henderson static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a)
12322b13b4b9SRichard Henderson {
12332b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12342b13b4b9SRichard Henderson         return false;
12352b13b4b9SRichard Henderson     }
12362b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false);
12372b13b4b9SRichard Henderson }
12382b13b4b9SRichard Henderson 
trans_lf_sfult_s(DisasContext * dc,arg_ab * a)12392b13b4b9SRichard Henderson static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a)
12402b13b4b9SRichard Henderson {
12412b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12422b13b4b9SRichard Henderson         return false;
12432b13b4b9SRichard Henderson     }
12442b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false);
12452b13b4b9SRichard Henderson }
12462b13b4b9SRichard Henderson 
trans_lf_sfugt_s(DisasContext * dc,arg_ab * a)12472b13b4b9SRichard Henderson static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a)
12482b13b4b9SRichard Henderson {
12492b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12502b13b4b9SRichard Henderson         return false;
12512b13b4b9SRichard Henderson     }
12522b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true);
12532b13b4b9SRichard Henderson }
12542b13b4b9SRichard Henderson 
trans_lf_sfule_s(DisasContext * dc,arg_ab * a)12552b13b4b9SRichard Henderson static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a)
12562b13b4b9SRichard Henderson {
12572b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12582b13b4b9SRichard Henderson         return false;
12592b13b4b9SRichard Henderson     }
12602b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false);
12612b13b4b9SRichard Henderson }
12622b13b4b9SRichard Henderson 
trans_lf_sfuge_s(DisasContext * dc,arg_ab * a)12632b13b4b9SRichard Henderson static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a)
12642b13b4b9SRichard Henderson {
12652b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12662b13b4b9SRichard Henderson         return false;
12672b13b4b9SRichard Henderson     }
12682b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true);
12692b13b4b9SRichard Henderson }
12702b13b4b9SRichard Henderson 
trans_lf_sfun_s(DisasContext * dc,arg_ab * a)12712b13b4b9SRichard Henderson static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a)
12722b13b4b9SRichard Henderson {
12732b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12742b13b4b9SRichard Henderson         return false;
12752b13b4b9SRichard Henderson     }
12762b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_un_s, false, false);
12772b13b4b9SRichard Henderson }
12782b13b4b9SRichard Henderson 
check_pair(DisasContext * dc,int r,int p)127962f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p)
128062f2b038SRichard Henderson {
128162f2b038SRichard Henderson     return r + 1 + p < 32;
128262f2b038SRichard Henderson }
128362f2b038SRichard Henderson 
load_pair(DisasContext * dc,TCGv_i64 t,int r,int p)128462f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
128562f2b038SRichard Henderson {
128662f2b038SRichard Henderson     tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r));
128762f2b038SRichard Henderson }
128862f2b038SRichard Henderson 
save_pair(DisasContext * dc,TCGv_i64 t,int r,int p)128962f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
129062f2b038SRichard Henderson {
129162f2b038SRichard Henderson     tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t);
129262f2b038SRichard Henderson }
129362f2b038SRichard Henderson 
do_dp3(DisasContext * dc,arg_dab_pair * a,void (* fn)(TCGv_i64,TCGv_env,TCGv_i64,TCGv_i64))129462f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a,
129562f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
129662f2b038SRichard Henderson {
129762f2b038SRichard Henderson     TCGv_i64 t0, t1;
129862f2b038SRichard Henderson 
129962f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
130062f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
130162f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
130262f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
130362f2b038SRichard Henderson         return false;
130462f2b038SRichard Henderson     }
130562f2b038SRichard Henderson     check_r0_write(dc, a->d);
130662f2b038SRichard Henderson 
130762f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
130862f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
130962f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
131062f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
1311ad75a51eSRichard Henderson     fn(t0, tcg_env, t0, t1);
131262f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
131362f2b038SRichard Henderson 
1314ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
131562f2b038SRichard Henderson     return true;
131662f2b038SRichard Henderson }
131762f2b038SRichard Henderson 
do_dp2(DisasContext * dc,arg_da_pair * a,void (* fn)(TCGv_i64,TCGv_env,TCGv_i64))131862f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a,
131962f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64))
132062f2b038SRichard Henderson {
132162f2b038SRichard Henderson     TCGv_i64 t0;
132262f2b038SRichard Henderson 
132362f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
132462f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
132562f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
132662f2b038SRichard Henderson         return false;
132762f2b038SRichard Henderson     }
132862f2b038SRichard Henderson     check_r0_write(dc, a->d);
132962f2b038SRichard Henderson 
133062f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
133162f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1332ad75a51eSRichard Henderson     fn(t0, tcg_env, t0);
133362f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
133462f2b038SRichard Henderson 
1335ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
133662f2b038SRichard Henderson     return true;
133762f2b038SRichard Henderson }
133862f2b038SRichard Henderson 
do_dpcmp(DisasContext * dc,arg_ab_pair * a,void (* fn)(TCGv,TCGv_env,TCGv_i64,TCGv_i64),bool inv,bool swap)133962f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a,
134062f2b038SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64),
134162f2b038SRichard Henderson                      bool inv, bool swap)
134262f2b038SRichard Henderson {
134362f2b038SRichard Henderson     TCGv_i64 t0, t1;
134462f2b038SRichard Henderson 
134562f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
134662f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
134762f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp)) {
134862f2b038SRichard Henderson         return false;
134962f2b038SRichard Henderson     }
135062f2b038SRichard Henderson 
135162f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
135262f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
135362f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
135462f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
135562f2b038SRichard Henderson     if (swap) {
1356ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, t1, t0);
135762f2b038SRichard Henderson     } else {
1358ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, t0, t1);
135962f2b038SRichard Henderson     }
136062f2b038SRichard Henderson 
136162f2b038SRichard Henderson     if (inv) {
136262f2b038SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
136362f2b038SRichard Henderson     }
1364ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
136562f2b038SRichard Henderson     return true;
136662f2b038SRichard Henderson }
136762f2b038SRichard Henderson 
trans_lf_add_d(DisasContext * dc,arg_dab_pair * a)136862f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a)
136962f2b038SRichard Henderson {
137062f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_add_d);
137162f2b038SRichard Henderson }
137262f2b038SRichard Henderson 
trans_lf_sub_d(DisasContext * dc,arg_dab_pair * a)137362f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a)
137462f2b038SRichard Henderson {
137562f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_sub_d);
137662f2b038SRichard Henderson }
137762f2b038SRichard Henderson 
trans_lf_mul_d(DisasContext * dc,arg_dab_pair * a)137862f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a)
137962f2b038SRichard Henderson {
138062f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_mul_d);
138162f2b038SRichard Henderson }
138262f2b038SRichard Henderson 
trans_lf_div_d(DisasContext * dc,arg_dab_pair * a)138362f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a)
138462f2b038SRichard Henderson {
138562f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_div_d);
138662f2b038SRichard Henderson }
138762f2b038SRichard Henderson 
trans_lf_rem_d(DisasContext * dc,arg_dab_pair * a)138862f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a)
138962f2b038SRichard Henderson {
139062f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_rem_d);
139162f2b038SRichard Henderson }
139262f2b038SRichard Henderson 
trans_lf_itof_d(DisasContext * dc,arg_da_pair * a)139362f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a)
139462f2b038SRichard Henderson {
139562f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_itofd);
139662f2b038SRichard Henderson }
139762f2b038SRichard Henderson 
trans_lf_ftoi_d(DisasContext * dc,arg_da_pair * a)139862f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a)
139962f2b038SRichard Henderson {
140062f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_ftoid);
140162f2b038SRichard Henderson }
140262f2b038SRichard Henderson 
trans_lf_stod_d(DisasContext * dc,arg_lf_stod_d * a)140362f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a)
140462f2b038SRichard Henderson {
140562f2b038SRichard Henderson     TCGv_i64 t0;
140662f2b038SRichard Henderson 
140762f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
140862f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
140962f2b038SRichard Henderson         return false;
141062f2b038SRichard Henderson     }
141162f2b038SRichard Henderson     check_r0_write(dc, a->d);
141262f2b038SRichard Henderson 
141362f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1414ad75a51eSRichard Henderson     gen_helper_stod(t0, tcg_env, cpu_R(dc, a->a));
141562f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
141662f2b038SRichard Henderson 
1417ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
141862f2b038SRichard Henderson     return true;
141962f2b038SRichard Henderson }
142062f2b038SRichard Henderson 
trans_lf_dtos_d(DisasContext * dc,arg_lf_dtos_d * a)142162f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a)
142262f2b038SRichard Henderson {
142362f2b038SRichard Henderson     TCGv_i64 t0;
142462f2b038SRichard Henderson 
142562f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
142662f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap)) {
142762f2b038SRichard Henderson         return false;
142862f2b038SRichard Henderson     }
142962f2b038SRichard Henderson     check_r0_write(dc, a->d);
143062f2b038SRichard Henderson 
143162f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
143262f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1433ad75a51eSRichard Henderson     gen_helper_dtos(cpu_R(dc, a->d), tcg_env, t0);
143462f2b038SRichard Henderson 
1435ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
143662f2b038SRichard Henderson     return true;
143762f2b038SRichard Henderson }
143862f2b038SRichard Henderson 
trans_lf_madd_d(DisasContext * dc,arg_dab_pair * a)143962f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a)
144062f2b038SRichard Henderson {
144162f2b038SRichard Henderson     TCGv_i64 t0, t1, t2;
144262f2b038SRichard Henderson 
144362f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
144462f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
144562f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
144662f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
144762f2b038SRichard Henderson         return false;
144862f2b038SRichard Henderson     }
144962f2b038SRichard Henderson     check_r0_write(dc, a->d);
145062f2b038SRichard Henderson 
145162f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
145262f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
145362f2b038SRichard Henderson     t2 = tcg_temp_new_i64();
145462f2b038SRichard Henderson     load_pair(dc, t0, a->d, a->dp);
145562f2b038SRichard Henderson     load_pair(dc, t1, a->a, a->ap);
145662f2b038SRichard Henderson     load_pair(dc, t2, a->b, a->bp);
1457ad75a51eSRichard Henderson     gen_helper_float_madd_d(t0, tcg_env, t0, t1, t2);
145862f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
145962f2b038SRichard Henderson 
1460ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
146162f2b038SRichard Henderson     return true;
146262f2b038SRichard Henderson }
146362f2b038SRichard Henderson 
trans_lf_sfeq_d(DisasContext * dc,arg_ab_pair * a)146462f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a)
146562f2b038SRichard Henderson {
146662f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false);
146762f2b038SRichard Henderson }
146862f2b038SRichard Henderson 
trans_lf_sfne_d(DisasContext * dc,arg_ab_pair * a)146962f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a)
147062f2b038SRichard Henderson {
147162f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false);
147262f2b038SRichard Henderson }
147362f2b038SRichard Henderson 
trans_lf_sfgt_d(DisasContext * dc,arg_ab_pair * a)147462f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a)
147562f2b038SRichard Henderson {
147662f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true);
147762f2b038SRichard Henderson }
147862f2b038SRichard Henderson 
trans_lf_sfge_d(DisasContext * dc,arg_ab_pair * a)147962f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a)
148062f2b038SRichard Henderson {
148162f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, true);
148262f2b038SRichard Henderson }
148362f2b038SRichard Henderson 
trans_lf_sflt_d(DisasContext * dc,arg_ab_pair * a)148462f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a)
148562f2b038SRichard Henderson {
148662f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false);
148762f2b038SRichard Henderson }
148862f2b038SRichard Henderson 
trans_lf_sfle_d(DisasContext * dc,arg_ab_pair * a)148962f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a)
149062f2b038SRichard Henderson {
149162f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, false);
149262f2b038SRichard Henderson }
149362f2b038SRichard Henderson 
trans_lf_sfueq_d(DisasContext * dc,arg_ab_pair * a)14942b13b4b9SRichard Henderson static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a)
14952b13b4b9SRichard Henderson {
14962b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false);
14972b13b4b9SRichard Henderson }
14982b13b4b9SRichard Henderson 
trans_lf_sfule_d(DisasContext * dc,arg_ab_pair * a)14992b13b4b9SRichard Henderson static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a)
15002b13b4b9SRichard Henderson {
15012b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false);
15022b13b4b9SRichard Henderson }
15032b13b4b9SRichard Henderson 
trans_lf_sfuge_d(DisasContext * dc,arg_ab_pair * a)15042b13b4b9SRichard Henderson static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a)
15052b13b4b9SRichard Henderson {
15062b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true);
15072b13b4b9SRichard Henderson }
15082b13b4b9SRichard Henderson 
trans_lf_sfult_d(DisasContext * dc,arg_ab_pair * a)15092b13b4b9SRichard Henderson static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a)
15102b13b4b9SRichard Henderson {
15112b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false);
15122b13b4b9SRichard Henderson }
15132b13b4b9SRichard Henderson 
trans_lf_sfugt_d(DisasContext * dc,arg_ab_pair * a)15142b13b4b9SRichard Henderson static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a)
15152b13b4b9SRichard Henderson {
15162b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true);
15172b13b4b9SRichard Henderson }
15182b13b4b9SRichard Henderson 
trans_lf_sfun_d(DisasContext * dc,arg_ab_pair * a)15192b13b4b9SRichard Henderson static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a)
15202b13b4b9SRichard Henderson {
15212b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_un_d, false, false);
15222b13b4b9SRichard Henderson }
15232b13b4b9SRichard Henderson 
openrisc_tr_init_disas_context(DisasContextBase * dcb,CPUState * cs)1524a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1525fcf5ef2aSThomas Huth {
1526a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
1527b77af26eSRichard Henderson     CPUOpenRISCState *env = cpu_env(cs);
1528a4fd3ec3SEmilio G. Cota     int bound;
1529fcf5ef2aSThomas Huth 
15303b916140SRichard Henderson     dc->mem_idx = cpu_mmu_index(cs, false);
15311ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1532a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1533fe636d37SRichard Henderson     dc->cpucfgr = env->cpucfgr;
15342b13b4b9SRichard Henderson     dc->avr = env->avr;
15358000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
15368000ba56SRichard Henderson 
1537a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1538a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1539fcf5ef2aSThomas Huth }
1540fcf5ef2aSThomas Huth 
openrisc_tr_tb_start(DisasContextBase * db,CPUState * cs)1541a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1542a4fd3ec3SEmilio G. Cota {
1543a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1544fcf5ef2aSThomas Huth 
15456597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15466597c28dSRichard Henderson        when it's true, which is the common case.  */
1547118671f0SRichard Henderson     dc->zero = tcg_constant_tl(0);
15486597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1549118671f0SRichard Henderson         dc->R0 = dc->zero;
15506597c28dSRichard Henderson     } else {
1551d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
15526597c28dSRichard Henderson     }
1553a4fd3ec3SEmilio G. Cota }
15546597c28dSRichard Henderson 
openrisc_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)1555a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1556a4fd3ec3SEmilio G. Cota {
1557a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1558a4fd3ec3SEmilio G. Cota 
15591ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1560a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1561a4fd3ec3SEmilio G. Cota }
1562fcf5ef2aSThomas Huth 
openrisc_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)1563a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1564a4fd3ec3SEmilio G. Cota {
1565a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1566074bd799SPhilippe Mathieu-Daudé     uint32_t insn = translator_ldl(cpu_env(cs), &dc->base, dc->base.pc_next);
1567a4fd3ec3SEmilio G. Cota 
1568c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1569c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1570c7b6f54bSRichard Henderson     }
15711ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
157224c32852SRichard Henderson 
15738000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
15748000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
15758000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
15768000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
15778000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
15788000ba56SRichard Henderson      */
15798000ba56SRichard Henderson     if (dc->delayed_branch
15808000ba56SRichard Henderson         && --dc->delayed_branch == 0
15818000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
15828000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1583fcf5ef2aSThomas Huth     }
1584a4fd3ec3SEmilio G. Cota }
1585fcf5ef2aSThomas Huth 
openrisc_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)1586a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1587a4fd3ec3SEmilio G. Cota {
1588a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
15898000ba56SRichard Henderson     target_ulong jmp_dest;
159024c32852SRichard Henderson 
1591e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1592e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1593e0a369cfSRichard Henderson         return;
1594e0a369cfSRichard Henderson     }
1595e0a369cfSRichard Henderson 
15968000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1597a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1598a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1599a01deb36SRichard Henderson     }
1600a01deb36SRichard Henderson 
16018000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
16028000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
16038000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
16048000ba56SRichard Henderson 
16051ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
16068000ba56SRichard Henderson     case DISAS_JUMP:
16078000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
16088000ba56SRichard Henderson         if (jmp_dest == -1) {
16098000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
16108000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
16118000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
16128000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
1613fcf5ef2aSThomas Huth             break;
16148000ba56SRichard Henderson         }
16158000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
16168000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
16178000ba56SRichard Henderson            we know now that it wasn't needed.  */
16188000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
16198000ba56SRichard Henderson         /* fallthru */
16208000ba56SRichard Henderson 
16218000ba56SRichard Henderson     case DISAS_TOO_MANY:
1622adf1f3deSRichard Henderson         if (translator_use_goto_tb(&dc->base, jmp_dest)) {
16238000ba56SRichard Henderson             tcg_gen_goto_tb(0);
16248000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
16258000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
1626adf1f3deSRichard Henderson             break;
1627adf1f3deSRichard Henderson         }
1628adf1f3deSRichard Henderson         tcg_gen_movi_tl(cpu_pc, jmp_dest);
1629adf1f3deSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
16308000ba56SRichard Henderson         break;
16318000ba56SRichard Henderson 
163264e46c95SRichard Henderson     case DISAS_EXIT:
163307ea28b4SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
1634fcf5ef2aSThomas Huth         break;
1635a4fd3ec3SEmilio G. Cota     default:
1636a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1637a4fd3ec3SEmilio G. Cota     }
1638fcf5ef2aSThomas Huth }
1639fcf5ef2aSThomas Huth 
1640a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1641a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1642a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1643a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1644a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1645a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1646a4fd3ec3SEmilio G. Cota };
1647a4fd3ec3SEmilio G. Cota 
gen_intermediate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)1648597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
164932f0c394SAnton Johansson                            vaddr pc, void *host_pc)
1650a4fd3ec3SEmilio G. Cota {
1651a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1652a4fd3ec3SEmilio G. Cota 
1653306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc,
1654306c8721SRichard Henderson                     &openrisc_tr_ops, &ctx.base);
1655fcf5ef2aSThomas Huth }
1656fcf5ef2aSThomas Huth 
openrisc_cpu_dump_state(CPUState * cs,FILE * f,int flags)165790c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1658fcf5ef2aSThomas Huth {
1659074bd799SPhilippe Mathieu-Daudé     CPUOpenRISCState *env = cpu_env(cs);
1660fcf5ef2aSThomas Huth     int i;
1661fcf5ef2aSThomas Huth 
166290c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1663fcf5ef2aSThomas Huth     for (i = 0; i < 32; ++i) {
166490c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1665fcf5ef2aSThomas Huth                      (i % 4) == 3 ? '\n' : ' ');
1666fcf5ef2aSThomas Huth     }
1667fcf5ef2aSThomas Huth }
1668