xref: /qemu/target/openrisc/translate.c (revision 68df8c8dba57f539d24f1a92a8699a179d9bb6fb)
1e67db06eSJia Liu /*
2e67db06eSJia Liu  * OpenRISC translation
3e67db06eSJia Liu  *
4e67db06eSJia Liu  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5e67db06eSJia Liu  *                         Feng Gao <gf91597@gmail.com>
6e67db06eSJia Liu  *
7e67db06eSJia Liu  * This library is free software; you can redistribute it and/or
8e67db06eSJia Liu  * modify it under the terms of the GNU Lesser General Public
9e67db06eSJia Liu  * License as published by the Free Software Foundation; either
10779fc6adSThomas Huth  * version 2.1 of the License, or (at your option) any later version.
11e67db06eSJia Liu  *
12e67db06eSJia Liu  * This library is distributed in the hope that it will be useful,
13e67db06eSJia Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14e67db06eSJia Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15e67db06eSJia Liu  * Lesser General Public License for more details.
16e67db06eSJia Liu  *
17e67db06eSJia Liu  * You should have received a copy of the GNU Lesser General Public
18e67db06eSJia Liu  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19e67db06eSJia Liu  */
20e67db06eSJia Liu 
21ed2decc6SPeter Maydell #include "qemu/osdep.h"
22e67db06eSJia Liu #include "cpu.h"
23022c62cbSPaolo Bonzini #include "exec/exec-all.h"
24dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
251de7afc9SPaolo Bonzini #include "qemu/log.h"
261de7afc9SPaolo Bonzini #include "qemu/bitops.h"
2790c84c56SMarkus Armbruster #include "qemu/qemu-print.h"
2877fc6f5eSLluís Vilanova #include "exec/translator.h"
29*68df8c8dSPhilippe Mathieu-Daudé #include "exec/translation-block.h"
30bbe418f2SJia Liu 
312ef6175aSRichard Henderson #include "exec/helper-proto.h"
322ef6175aSRichard Henderson #include "exec/helper-gen.h"
33e67db06eSJia Liu 
34508127e2SPaolo Bonzini #include "exec/log.h"
35a7e30d84SLluís Vilanova 
36d53106c9SRichard Henderson #define HELPER_H "helper.h"
37d53106c9SRichard Henderson #include "exec/helper-info.c.inc"
38d53106c9SRichard Henderson #undef  HELPER_H
39d53106c9SRichard Henderson 
40d53106c9SRichard Henderson 
4177fc6f5eSLluís Vilanova /* is_jmp field values */
4264e46c95SRichard Henderson #define DISAS_EXIT    DISAS_TARGET_0  /* force exit to main loop */
438000ba56SRichard Henderson #define DISAS_JUMP    DISAS_TARGET_1  /* exit via jmp_pc/jmp_pc_imm */
4477fc6f5eSLluís Vilanova 
45bbe418f2SJia Liu typedef struct DisasContext {
461ffa4bceSEmilio G. Cota     DisasContextBase base;
47bbe418f2SJia Liu     uint32_t mem_idx;
48a01deb36SRichard Henderson     uint32_t tb_flags;
49bbe418f2SJia Liu     uint32_t delayed_branch;
50fe636d37SRichard Henderson     uint32_t cpucfgr;
512b13b4b9SRichard Henderson     uint32_t avr;
528000ba56SRichard Henderson 
538000ba56SRichard Henderson     /* If not -1, jmp_pc contains this value and so is a direct jump.  */
548000ba56SRichard Henderson     target_ulong jmp_pc_imm;
55d29f4368SRichard Henderson 
56d29f4368SRichard Henderson     /* The temporary corresponding to register 0 for this compilation.  */
57d29f4368SRichard Henderson     TCGv R0;
58118671f0SRichard Henderson     /* The constant zero. */
59118671f0SRichard Henderson     TCGv zero;
60bbe418f2SJia Liu } DisasContext;
61bbe418f2SJia Liu 
622ba65417SRichard Henderson static inline bool is_user(DisasContext *dc)
632ba65417SRichard Henderson {
642ba65417SRichard Henderson #ifdef CONFIG_USER_ONLY
652ba65417SRichard Henderson     return true;
662ba65417SRichard Henderson #else
67b9bed1b9SRichard Henderson     return !(dc->tb_flags & TB_FLAGS_SM);
682ba65417SRichard Henderson #endif
692ba65417SRichard Henderson }
702ba65417SRichard Henderson 
717de9729fSRichard Henderson /* Include the auto-generated decoder.  */
72abff1abfSPaolo Bonzini #include "decode-insns.c.inc"
737de9729fSRichard Henderson 
74bbe418f2SJia Liu static TCGv cpu_sr;
758bba7619SRichard Henderson static TCGv cpu_regs[32];
76bbe418f2SJia Liu static TCGv cpu_pc;
77bbe418f2SJia Liu static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
78bbe418f2SJia Liu static TCGv cpu_ppc;
7984775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
8097458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
8197458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
82930c3d00SRichard Henderson static TCGv cpu_lock_addr;
83930c3d00SRichard Henderson static TCGv cpu_lock_value;
84bbe418f2SJia Liu static TCGv_i32 fpcsr;
856f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
86a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
87bbe418f2SJia Liu 
88e67db06eSJia Liu void openrisc_translate_init(void)
89e67db06eSJia Liu {
90bbe418f2SJia Liu     static const char * const regnames[] = {
91bbe418f2SJia Liu         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
92bbe418f2SJia Liu         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
93bbe418f2SJia Liu         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
94bbe418f2SJia Liu         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
95bbe418f2SJia Liu     };
96bbe418f2SJia Liu     int i;
97bbe418f2SJia Liu 
98ad75a51eSRichard Henderson     cpu_sr = tcg_global_mem_new(tcg_env,
99bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, sr), "sr");
100ad75a51eSRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(tcg_env,
101a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
102a01deb36SRichard Henderson                                        "dflag");
103ad75a51eSRichard Henderson     cpu_pc = tcg_global_mem_new(tcg_env,
104bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, pc), "pc");
105ad75a51eSRichard Henderson     cpu_ppc = tcg_global_mem_new(tcg_env,
106bbe418f2SJia Liu                                  offsetof(CPUOpenRISCState, ppc), "ppc");
107ad75a51eSRichard Henderson     jmp_pc = tcg_global_mem_new(tcg_env,
108bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
109ad75a51eSRichard Henderson     cpu_sr_f = tcg_global_mem_new(tcg_env,
11084775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
111ad75a51eSRichard Henderson     cpu_sr_cy = tcg_global_mem_new(tcg_env,
11297458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
113ad75a51eSRichard Henderson     cpu_sr_ov = tcg_global_mem_new(tcg_env,
11497458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
115ad75a51eSRichard Henderson     cpu_lock_addr = tcg_global_mem_new(tcg_env,
116930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
117930c3d00SRichard Henderson                                        "lock_addr");
118ad75a51eSRichard Henderson     cpu_lock_value = tcg_global_mem_new(tcg_env,
119930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
120930c3d00SRichard Henderson                                         "lock_value");
121ad75a51eSRichard Henderson     fpcsr = tcg_global_mem_new_i32(tcg_env,
122bbe418f2SJia Liu                                    offsetof(CPUOpenRISCState, fpcsr),
123bbe418f2SJia Liu                                    "fpcsr");
124ad75a51eSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(tcg_env,
1256f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1266f7332baSRichard Henderson                                      "mac");
127bbe418f2SJia Liu     for (i = 0; i < 32; i++) {
128ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
129d89e71e8SStafford Horne                                          offsetof(CPUOpenRISCState,
130d89e71e8SStafford Horne                                                   shadow_gpr[0][i]),
131bbe418f2SJia Liu                                          regnames[i]);
132bbe418f2SJia Liu     }
133bbe418f2SJia Liu }
134bbe418f2SJia Liu 
135bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp)
136bbe418f2SJia Liu {
137ad75a51eSRichard Henderson     gen_helper_exception(tcg_env, tcg_constant_i32(excp));
138bbe418f2SJia Liu }
139bbe418f2SJia Liu 
140bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc)
141bbe418f2SJia Liu {
1421ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
143bbe418f2SJia Liu     gen_exception(dc, EXCP_ILLEGAL);
1441ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
145bbe418f2SJia Liu }
146bbe418f2SJia Liu 
1472b13b4b9SRichard Henderson static bool check_v1_3(DisasContext *dc)
1482b13b4b9SRichard Henderson {
1492b13b4b9SRichard Henderson     return dc->avr >= 0x01030000;
1502b13b4b9SRichard Henderson }
1512b13b4b9SRichard Henderson 
152fe636d37SRichard Henderson static bool check_of32s(DisasContext *dc)
153bbe418f2SJia Liu {
154fe636d37SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF32S;
155bbe418f2SJia Liu }
156bbe418f2SJia Liu 
15762f2b038SRichard Henderson static bool check_of64a32s(DisasContext *dc)
15862f2b038SRichard Henderson {
15962f2b038SRichard Henderson     return dc->cpucfgr & CPUCFGR_OF64A32S;
16062f2b038SRichard Henderson }
16162f2b038SRichard Henderson 
1628bba7619SRichard Henderson static TCGv cpu_R(DisasContext *dc, int reg)
1638bba7619SRichard Henderson {
164d29f4368SRichard Henderson     if (reg == 0) {
165d29f4368SRichard Henderson         return dc->R0;
166d29f4368SRichard Henderson     } else {
1678bba7619SRichard Henderson         return cpu_regs[reg];
1688bba7619SRichard Henderson     }
169d29f4368SRichard Henderson }
1708bba7619SRichard Henderson 
171cdd0f459SRichard Henderson /*
172cdd0f459SRichard Henderson  * We're about to write to REG.  On the off-chance that the user is
173cdd0f459SRichard Henderson  * writing to R0, re-instate the architectural register.
174cdd0f459SRichard Henderson  */
175cdd0f459SRichard Henderson static void check_r0_write(DisasContext *dc, int reg)
176cdd0f459SRichard Henderson {
177cdd0f459SRichard Henderson     if (unlikely(reg == 0)) {
178d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
179cdd0f459SRichard Henderson     }
180cdd0f459SRichard Henderson }
1816597c28dSRichard Henderson 
18297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
1839ecaa27eSRichard Henderson {
1840c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
185ad75a51eSRichard Henderson         gen_helper_ove_cy(tcg_env);
1869ecaa27eSRichard Henderson     }
1870c53d734SRichard Henderson }
1889ecaa27eSRichard Henderson 
18997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
1909ecaa27eSRichard Henderson {
1910c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
192ad75a51eSRichard Henderson         gen_helper_ove_ov(tcg_env);
1939ecaa27eSRichard Henderson     }
1940c53d734SRichard Henderson }
1959ecaa27eSRichard Henderson 
19697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
1979ecaa27eSRichard Henderson {
1980c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
199ad75a51eSRichard Henderson         gen_helper_ove_cyov(tcg_env);
2009ecaa27eSRichard Henderson     }
2010c53d734SRichard Henderson }
2029ecaa27eSRichard Henderson 
2039ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2049ecaa27eSRichard Henderson {
205e0efc48fSRichard Henderson     TCGv t0 = tcg_temp_new();
2069ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2079ecaa27eSRichard Henderson 
208e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, srcb, dc->zero);
20997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2109ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
21197458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2129ecaa27eSRichard Henderson 
2139ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2149ecaa27eSRichard Henderson 
21597458071SRichard Henderson     gen_ove_cyov(dc);
2169ecaa27eSRichard Henderson }
2179ecaa27eSRichard Henderson 
2189ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2199ecaa27eSRichard Henderson {
220e0efc48fSRichard Henderson     TCGv t0 = tcg_temp_new();
2219ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2229ecaa27eSRichard Henderson 
223e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, dc->zero, cpu_sr_cy, dc->zero);
224e0efc48fSRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, dc->zero);
22597458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2269ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
22797458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2289ecaa27eSRichard Henderson 
2299ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2309ecaa27eSRichard Henderson 
23197458071SRichard Henderson     gen_ove_cyov(dc);
2329ecaa27eSRichard Henderson }
2339ecaa27eSRichard Henderson 
2349ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2359ecaa27eSRichard Henderson {
2369ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2379ecaa27eSRichard Henderson 
2389ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
23997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
24097458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
24197458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
24297458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
2439ecaa27eSRichard Henderson 
2449ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2459ecaa27eSRichard Henderson 
24697458071SRichard Henderson     gen_ove_cyov(dc);
2479ecaa27eSRichard Henderson }
2489ecaa27eSRichard Henderson 
2499ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2509ecaa27eSRichard Henderson {
2519ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2529ecaa27eSRichard Henderson 
25397458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
2549ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
255cfe15887SRichard Henderson     tcg_gen_negsetcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
2569ecaa27eSRichard Henderson 
25797458071SRichard Henderson     gen_ove_ov(dc);
2589ecaa27eSRichard Henderson }
2599ecaa27eSRichard Henderson 
2609ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2619ecaa27eSRichard Henderson {
26297458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
26397458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
2649ecaa27eSRichard Henderson 
26597458071SRichard Henderson     gen_ove_cy(dc);
2669ecaa27eSRichard Henderson }
2679ecaa27eSRichard Henderson 
2689ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2699ecaa27eSRichard Henderson {
2709ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2719ecaa27eSRichard Henderson 
27297458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
2739ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2748b81968cSMichael Tokarev        Suppress the host-side exception by dividing by 1. */
27597458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
2769ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
2779ecaa27eSRichard Henderson 
27897458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
27997458071SRichard Henderson     gen_ove_ov(dc);
2809ecaa27eSRichard Henderson }
2819ecaa27eSRichard Henderson 
2829ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2839ecaa27eSRichard Henderson {
2849ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
2859ecaa27eSRichard Henderson 
28697458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
2879ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
2888b81968cSMichael Tokarev        Suppress the host-side exception by dividing by 1. */
28997458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
2909ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
2919ecaa27eSRichard Henderson 
29297458071SRichard Henderson     gen_ove_cy(dc);
2939ecaa27eSRichard Henderson }
294da1d7759SSebastian Macke 
295cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
296cc5de49eSRichard Henderson {
297cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
298cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
299cc5de49eSRichard Henderson 
300cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
301cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
302cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
303cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
304cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
305cc5de49eSRichard Henderson     } else {
306cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
307cc5de49eSRichard Henderson 
308cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
309cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
310cfe15887SRichard Henderson         tcg_gen_negsetcond_i64(TCG_COND_NE, t1, t1, high);
311cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
312cc5de49eSRichard Henderson 
313cc5de49eSRichard Henderson         gen_ove_ov(dc);
314cc5de49eSRichard Henderson     }
315cc5de49eSRichard Henderson }
316cc5de49eSRichard Henderson 
317cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
318cc5de49eSRichard Henderson {
319cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
320cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
321cc5de49eSRichard Henderson 
322cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
323cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
324cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
325cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
326cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
327cc5de49eSRichard Henderson     } else {
328cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
329cc5de49eSRichard Henderson 
330cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
331cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
332cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
333cc5de49eSRichard Henderson 
334cc5de49eSRichard Henderson         gen_ove_cy(dc);
335cc5de49eSRichard Henderson     }
336cc5de49eSRichard Henderson }
337cc5de49eSRichard Henderson 
3386f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
3396f7332baSRichard Henderson {
3406f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3416f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3426f7332baSRichard Henderson 
3436f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3446f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3456f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3466f7332baSRichard Henderson 
3476f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
3486f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3496f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
3506f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3516f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
3526f7332baSRichard Henderson 
3536f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3546f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3556f7332baSRichard Henderson #else
3566f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3576f7332baSRichard Henderson #endif
3586f7332baSRichard Henderson 
3596f7332baSRichard Henderson     gen_ove_ov(dc);
3606f7332baSRichard Henderson }
3616f7332baSRichard Henderson 
362cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
363cc5de49eSRichard Henderson {
364cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
365cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
366cc5de49eSRichard Henderson 
367cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
368cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
369cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
370cc5de49eSRichard Henderson 
371cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
372cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
373cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
374cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
375cc5de49eSRichard Henderson 
376cc5de49eSRichard Henderson     gen_ove_cy(dc);
377cc5de49eSRichard Henderson }
378cc5de49eSRichard Henderson 
3796f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
3806f7332baSRichard Henderson {
3816f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
3826f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
3836f7332baSRichard Henderson 
3846f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
3856f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
3866f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
3876f7332baSRichard Henderson 
3886f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
3896f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
3906f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
3916f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
3926f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
3936f7332baSRichard Henderson 
3946f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
3956f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
3966f7332baSRichard Henderson #else
3976f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
3986f7332baSRichard Henderson #endif
3996f7332baSRichard Henderson 
4006f7332baSRichard Henderson     gen_ove_ov(dc);
4016f7332baSRichard Henderson }
4026f7332baSRichard Henderson 
403cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
404cc5de49eSRichard Henderson {
405cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
406cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
407cc5de49eSRichard Henderson 
408cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
409cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
410cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
411cc5de49eSRichard Henderson 
412cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
413cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
414cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
415cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
416cc5de49eSRichard Henderson 
417cc5de49eSRichard Henderson     gen_ove_cy(dc);
418cc5de49eSRichard Henderson }
419cc5de49eSRichard Henderson 
4203a7be554SRichard Henderson static bool trans_l_add(DisasContext *dc, arg_dab *a)
421bbe418f2SJia Liu {
422cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4238bba7619SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4246ad216abSRichard Henderson     return true;
425bbe418f2SJia Liu }
426bbe418f2SJia Liu 
4273a7be554SRichard Henderson static bool trans_l_addc(DisasContext *dc, arg_dab *a)
428bbe418f2SJia Liu {
429cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4308bba7619SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4316ad216abSRichard Henderson     return true;
4326ad216abSRichard Henderson }
4336ad216abSRichard Henderson 
4343a7be554SRichard Henderson static bool trans_l_sub(DisasContext *dc, arg_dab *a)
4356ad216abSRichard Henderson {
436cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4378bba7619SRichard Henderson     gen_sub(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4386ad216abSRichard Henderson     return true;
4396ad216abSRichard Henderson }
4406ad216abSRichard Henderson 
4413a7be554SRichard Henderson static bool trans_l_and(DisasContext *dc, arg_dab *a)
4426ad216abSRichard Henderson {
443cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4448bba7619SRichard Henderson     tcg_gen_and_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4456ad216abSRichard Henderson     return true;
4466ad216abSRichard Henderson }
4476ad216abSRichard Henderson 
4483a7be554SRichard Henderson static bool trans_l_or(DisasContext *dc, arg_dab *a)
4496ad216abSRichard Henderson {
450cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4518bba7619SRichard Henderson     tcg_gen_or_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4526ad216abSRichard Henderson     return true;
4536ad216abSRichard Henderson }
4546ad216abSRichard Henderson 
4553a7be554SRichard Henderson static bool trans_l_xor(DisasContext *dc, arg_dab *a)
4566ad216abSRichard Henderson {
457cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4588bba7619SRichard Henderson     tcg_gen_xor_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4596ad216abSRichard Henderson     return true;
4606ad216abSRichard Henderson }
4616ad216abSRichard Henderson 
4623a7be554SRichard Henderson static bool trans_l_sll(DisasContext *dc, arg_dab *a)
4636ad216abSRichard Henderson {
464cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4658bba7619SRichard Henderson     tcg_gen_shl_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4666ad216abSRichard Henderson     return true;
4676ad216abSRichard Henderson }
4686ad216abSRichard Henderson 
4693a7be554SRichard Henderson static bool trans_l_srl(DisasContext *dc, arg_dab *a)
4706ad216abSRichard Henderson {
471cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4728bba7619SRichard Henderson     tcg_gen_shr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4736ad216abSRichard Henderson     return true;
4746ad216abSRichard Henderson }
4756ad216abSRichard Henderson 
4763a7be554SRichard Henderson static bool trans_l_sra(DisasContext *dc, arg_dab *a)
4776ad216abSRichard Henderson {
478cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4798bba7619SRichard Henderson     tcg_gen_sar_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4806ad216abSRichard Henderson     return true;
4816ad216abSRichard Henderson }
4826ad216abSRichard Henderson 
4833a7be554SRichard Henderson static bool trans_l_ror(DisasContext *dc, arg_dab *a)
4846ad216abSRichard Henderson {
485cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4868bba7619SRichard Henderson     tcg_gen_rotr_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
4876ad216abSRichard Henderson     return true;
4886ad216abSRichard Henderson }
4896ad216abSRichard Henderson 
4903a7be554SRichard Henderson static bool trans_l_exths(DisasContext *dc, arg_da *a)
4916ad216abSRichard Henderson {
492cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
4938bba7619SRichard Henderson     tcg_gen_ext16s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
4946ad216abSRichard Henderson     return true;
4956ad216abSRichard Henderson }
4966ad216abSRichard Henderson 
4973a7be554SRichard Henderson static bool trans_l_extbs(DisasContext *dc, arg_da *a)
4986ad216abSRichard Henderson {
499cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5008bba7619SRichard Henderson     tcg_gen_ext8s_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5016ad216abSRichard Henderson     return true;
5026ad216abSRichard Henderson }
5036ad216abSRichard Henderson 
5043a7be554SRichard Henderson static bool trans_l_exthz(DisasContext *dc, arg_da *a)
5056ad216abSRichard Henderson {
506cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5078bba7619SRichard Henderson     tcg_gen_ext16u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5086ad216abSRichard Henderson     return true;
5096ad216abSRichard Henderson }
5106ad216abSRichard Henderson 
5113a7be554SRichard Henderson static bool trans_l_extbz(DisasContext *dc, arg_da *a)
5126ad216abSRichard Henderson {
513cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5148bba7619SRichard Henderson     tcg_gen_ext8u_tl(cpu_R(dc, a->d), cpu_R(dc, a->a));
5156ad216abSRichard Henderson     return true;
5166ad216abSRichard Henderson }
5176ad216abSRichard Henderson 
5183a7be554SRichard Henderson static bool trans_l_cmov(DisasContext *dc, arg_dab *a)
5196ad216abSRichard Henderson {
520cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
521118671f0SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_NE, cpu_R(dc, a->d), cpu_sr_f, dc->zero,
5228bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
5236ad216abSRichard Henderson     return true;
524bbe418f2SJia Liu }
525bbe418f2SJia Liu 
5263a7be554SRichard Henderson static bool trans_l_ff1(DisasContext *dc, arg_da *a)
5276ad216abSRichard Henderson {
528cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5298bba7619SRichard Henderson     tcg_gen_ctzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), -1);
5308bba7619SRichard Henderson     tcg_gen_addi_tl(cpu_R(dc, a->d), cpu_R(dc, a->d), 1);
5316ad216abSRichard Henderson     return true;
532cf2ae442SRichard Henderson }
533cf2ae442SRichard Henderson 
5343a7be554SRichard Henderson static bool trans_l_fl1(DisasContext *dc, arg_da *a)
5356ad216abSRichard Henderson {
536cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5378bba7619SRichard Henderson     tcg_gen_clzi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), TARGET_LONG_BITS);
5388bba7619SRichard Henderson     tcg_gen_subfi_tl(cpu_R(dc, a->d), TARGET_LONG_BITS, cpu_R(dc, a->d));
5396ad216abSRichard Henderson     return true;
540bbe418f2SJia Liu }
541bbe418f2SJia Liu 
5423a7be554SRichard Henderson static bool trans_l_mul(DisasContext *dc, arg_dab *a)
5436ad216abSRichard Henderson {
544cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5458bba7619SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5466ad216abSRichard Henderson     return true;
547bbe418f2SJia Liu }
5486ad216abSRichard Henderson 
5493a7be554SRichard Henderson static bool trans_l_mulu(DisasContext *dc, arg_dab *a)
5506ad216abSRichard Henderson {
551cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5528bba7619SRichard Henderson     gen_mulu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5536ad216abSRichard Henderson     return true;
554bbe418f2SJia Liu }
5556ad216abSRichard Henderson 
5563a7be554SRichard Henderson static bool trans_l_div(DisasContext *dc, arg_dab *a)
5576ad216abSRichard Henderson {
558cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5598bba7619SRichard Henderson     gen_div(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5606ad216abSRichard Henderson     return true;
5616ad216abSRichard Henderson }
5626ad216abSRichard Henderson 
5633a7be554SRichard Henderson static bool trans_l_divu(DisasContext *dc, arg_dab *a)
5646ad216abSRichard Henderson {
565cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
5668bba7619SRichard Henderson     gen_divu(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), cpu_R(dc, a->b));
5676ad216abSRichard Henderson     return true;
5686ad216abSRichard Henderson }
5696ad216abSRichard Henderson 
5703a7be554SRichard Henderson static bool trans_l_muld(DisasContext *dc, arg_ab *a)
5716ad216abSRichard Henderson {
5728bba7619SRichard Henderson     gen_muld(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5736ad216abSRichard Henderson     return true;
5746ad216abSRichard Henderson }
5756ad216abSRichard Henderson 
5763a7be554SRichard Henderson static bool trans_l_muldu(DisasContext *dc, arg_ab *a)
5776ad216abSRichard Henderson {
5788bba7619SRichard Henderson     gen_muldu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
5796ad216abSRichard Henderson     return true;
580bbe418f2SJia Liu }
581bbe418f2SJia Liu 
5823a7be554SRichard Henderson static bool trans_l_j(DisasContext *dc, arg_l_j *a)
583136e13aeSRichard Henderson {
584136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
585136e13aeSRichard Henderson 
586136e13aeSRichard Henderson     tcg_gen_movi_tl(jmp_pc, tmp_pc);
5878000ba56SRichard Henderson     dc->jmp_pc_imm = tmp_pc;
588136e13aeSRichard Henderson     dc->delayed_branch = 2;
589136e13aeSRichard Henderson     return true;
590136e13aeSRichard Henderson }
591136e13aeSRichard Henderson 
5923a7be554SRichard Henderson static bool trans_l_jal(DisasContext *dc, arg_l_jal *a)
593136e13aeSRichard Henderson {
594136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
595136e13aeSRichard Henderson     target_ulong ret_pc = dc->base.pc_next + 8;
596136e13aeSRichard Henderson 
5978bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], ret_pc);
598136e13aeSRichard Henderson     /* Optimize jal being used to load the PC for PIC.  */
599136e13aeSRichard Henderson     if (tmp_pc != ret_pc) {
600136e13aeSRichard Henderson         tcg_gen_movi_tl(jmp_pc, tmp_pc);
6018000ba56SRichard Henderson         dc->jmp_pc_imm = tmp_pc;
602136e13aeSRichard Henderson         dc->delayed_branch = 2;
603136e13aeSRichard Henderson     }
604136e13aeSRichard Henderson     return true;
605136e13aeSRichard Henderson }
606136e13aeSRichard Henderson 
607136e13aeSRichard Henderson static void do_bf(DisasContext *dc, arg_l_bf *a, TCGCond cond)
608136e13aeSRichard Henderson {
609136e13aeSRichard Henderson     target_ulong tmp_pc = dc->base.pc_next + a->n * 4;
610af42d354SRichard Henderson     TCGv t_next = tcg_constant_tl(dc->base.pc_next + 8);
611af42d354SRichard Henderson     TCGv t_true = tcg_constant_tl(tmp_pc);
612136e13aeSRichard Henderson 
613118671f0SRichard Henderson     tcg_gen_movcond_tl(cond, jmp_pc, cpu_sr_f, dc->zero, t_true, t_next);
614136e13aeSRichard Henderson     dc->delayed_branch = 2;
615136e13aeSRichard Henderson }
616136e13aeSRichard Henderson 
6173a7be554SRichard Henderson static bool trans_l_bf(DisasContext *dc, arg_l_bf *a)
618136e13aeSRichard Henderson {
619136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_NE);
620136e13aeSRichard Henderson     return true;
621136e13aeSRichard Henderson }
622136e13aeSRichard Henderson 
6233a7be554SRichard Henderson static bool trans_l_bnf(DisasContext *dc, arg_l_bf *a)
624136e13aeSRichard Henderson {
625136e13aeSRichard Henderson     do_bf(dc, a, TCG_COND_EQ);
626136e13aeSRichard Henderson     return true;
627136e13aeSRichard Henderson }
628136e13aeSRichard Henderson 
6293a7be554SRichard Henderson static bool trans_l_jr(DisasContext *dc, arg_l_jr *a)
630136e13aeSRichard Henderson {
6318bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
632136e13aeSRichard Henderson     dc->delayed_branch = 2;
633136e13aeSRichard Henderson     return true;
634136e13aeSRichard Henderson }
635136e13aeSRichard Henderson 
6363a7be554SRichard Henderson static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a)
637136e13aeSRichard Henderson {
6388bba7619SRichard Henderson     tcg_gen_mov_tl(jmp_pc, cpu_R(dc, a->b));
6398bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_regs[9], dc->base.pc_next + 8);
640136e13aeSRichard Henderson     dc->delayed_branch = 2;
641136e13aeSRichard Henderson     return true;
642136e13aeSRichard Henderson }
643136e13aeSRichard Henderson 
6443a7be554SRichard Henderson static bool trans_l_lwa(DisasContext *dc, arg_load *a)
645d80bff19SRichard Henderson {
646d80bff19SRichard Henderson     TCGv ea;
647d80bff19SRichard Henderson 
648cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
649d80bff19SRichard Henderson     ea = tcg_temp_new();
6508bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6518bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, MO_TEUL);
652d80bff19SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
6538bba7619SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, cpu_R(dc, a->d));
654d80bff19SRichard Henderson     return true;
655d80bff19SRichard Henderson }
656d80bff19SRichard Henderson 
65714776ab5STony Nguyen static void do_load(DisasContext *dc, arg_load *a, MemOp mop)
658d80bff19SRichard Henderson {
659d80bff19SRichard Henderson     TCGv ea;
660d80bff19SRichard Henderson 
661cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
662d80bff19SRichard Henderson     ea = tcg_temp_new();
6638bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
6648bba7619SRichard Henderson     tcg_gen_qemu_ld_tl(cpu_R(dc, a->d), ea, dc->mem_idx, mop);
665d80bff19SRichard Henderson }
666d80bff19SRichard Henderson 
6673a7be554SRichard Henderson static bool trans_l_lwz(DisasContext *dc, arg_load *a)
668d80bff19SRichard Henderson {
669d80bff19SRichard Henderson     do_load(dc, a, MO_TEUL);
670d80bff19SRichard Henderson     return true;
671d80bff19SRichard Henderson }
672d80bff19SRichard Henderson 
6733a7be554SRichard Henderson static bool trans_l_lws(DisasContext *dc, arg_load *a)
674d80bff19SRichard Henderson {
675d80bff19SRichard Henderson     do_load(dc, a, MO_TESL);
676d80bff19SRichard Henderson     return true;
677d80bff19SRichard Henderson }
678d80bff19SRichard Henderson 
6793a7be554SRichard Henderson static bool trans_l_lbz(DisasContext *dc, arg_load *a)
680d80bff19SRichard Henderson {
681d80bff19SRichard Henderson     do_load(dc, a, MO_UB);
682d80bff19SRichard Henderson     return true;
683d80bff19SRichard Henderson }
684d80bff19SRichard Henderson 
6853a7be554SRichard Henderson static bool trans_l_lbs(DisasContext *dc, arg_load *a)
686d80bff19SRichard Henderson {
687d80bff19SRichard Henderson     do_load(dc, a, MO_SB);
688d80bff19SRichard Henderson     return true;
689d80bff19SRichard Henderson }
690d80bff19SRichard Henderson 
6913a7be554SRichard Henderson static bool trans_l_lhz(DisasContext *dc, arg_load *a)
692d80bff19SRichard Henderson {
693d80bff19SRichard Henderson     do_load(dc, a, MO_TEUW);
694d80bff19SRichard Henderson     return true;
695d80bff19SRichard Henderson }
696d80bff19SRichard Henderson 
6973a7be554SRichard Henderson static bool trans_l_lhs(DisasContext *dc, arg_load *a)
698d80bff19SRichard Henderson {
699d80bff19SRichard Henderson     do_load(dc, a, MO_TESW);
700d80bff19SRichard Henderson     return true;
701d80bff19SRichard Henderson }
702d80bff19SRichard Henderson 
7033a7be554SRichard Henderson static bool trans_l_swa(DisasContext *dc, arg_store *a)
704d80bff19SRichard Henderson {
705d80bff19SRichard Henderson     TCGv ea, val;
706d80bff19SRichard Henderson     TCGLabel *lab_fail, *lab_done;
707d80bff19SRichard Henderson 
708d80bff19SRichard Henderson     ea = tcg_temp_new();
7098bba7619SRichard Henderson     tcg_gen_addi_tl(ea, cpu_R(dc, a->a), a->i);
710d80bff19SRichard Henderson 
711d80bff19SRichard Henderson     lab_fail = gen_new_label();
712d80bff19SRichard Henderson     lab_done = gen_new_label();
713d80bff19SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
714d80bff19SRichard Henderson 
715d80bff19SRichard Henderson     val = tcg_temp_new();
716d80bff19SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
7174d10fa0fSRichard Henderson                               cpu_R(dc, a->b), dc->mem_idx, MO_TEUL);
718d80bff19SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
719d80bff19SRichard Henderson 
720d80bff19SRichard Henderson     tcg_gen_br(lab_done);
721d80bff19SRichard Henderson 
722d80bff19SRichard Henderson     gen_set_label(lab_fail);
723d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
724d80bff19SRichard Henderson 
725d80bff19SRichard Henderson     gen_set_label(lab_done);
726d80bff19SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
727d80bff19SRichard Henderson     return true;
728d80bff19SRichard Henderson }
729d80bff19SRichard Henderson 
73014776ab5STony Nguyen static void do_store(DisasContext *dc, arg_store *a, MemOp mop)
731d80bff19SRichard Henderson {
732d80bff19SRichard Henderson     TCGv t0 = tcg_temp_new();
7338bba7619SRichard Henderson     tcg_gen_addi_tl(t0, cpu_R(dc, a->a), a->i);
7348bba7619SRichard Henderson     tcg_gen_qemu_st_tl(cpu_R(dc, a->b), t0, dc->mem_idx, mop);
735d80bff19SRichard Henderson }
736d80bff19SRichard Henderson 
7373a7be554SRichard Henderson static bool trans_l_sw(DisasContext *dc, arg_store *a)
738d80bff19SRichard Henderson {
739d80bff19SRichard Henderson     do_store(dc, a, MO_TEUL);
740d80bff19SRichard Henderson     return true;
741d80bff19SRichard Henderson }
742d80bff19SRichard Henderson 
7433a7be554SRichard Henderson static bool trans_l_sb(DisasContext *dc, arg_store *a)
744d80bff19SRichard Henderson {
745d80bff19SRichard Henderson     do_store(dc, a, MO_UB);
746d80bff19SRichard Henderson     return true;
747d80bff19SRichard Henderson }
748d80bff19SRichard Henderson 
7493a7be554SRichard Henderson static bool trans_l_sh(DisasContext *dc, arg_store *a)
750d80bff19SRichard Henderson {
751d80bff19SRichard Henderson     do_store(dc, a, MO_TEUW);
752d80bff19SRichard Henderson     return true;
753d80bff19SRichard Henderson }
754d80bff19SRichard Henderson 
7553a7be554SRichard Henderson static bool trans_l_nop(DisasContext *dc, arg_l_nop *a)
756bbe418f2SJia Liu {
7578816f70bSRichard Henderson     return true;
7588816f70bSRichard Henderson }
7598816f70bSRichard Henderson 
7603e0e41efSRichard Henderson static bool trans_l_adrp(DisasContext *dc, arg_l_adrp *a)
7613e0e41efSRichard Henderson {
7623e0e41efSRichard Henderson     if (!check_v1_3(dc)) {
7633e0e41efSRichard Henderson         return false;
7643e0e41efSRichard Henderson     }
7653e0e41efSRichard Henderson     check_r0_write(dc, a->d);
7663e0e41efSRichard Henderson 
7673e0e41efSRichard Henderson     tcg_gen_movi_i32(cpu_R(dc, a->d),
7683e0e41efSRichard Henderson                      (dc->base.pc_next & TARGET_PAGE_MASK) +
7693e0e41efSRichard Henderson                      ((target_long)a->i << TARGET_PAGE_BITS));
7703e0e41efSRichard Henderson     return true;
7713e0e41efSRichard Henderson }
7723e0e41efSRichard Henderson 
7733a7be554SRichard Henderson static bool trans_l_addi(DisasContext *dc, arg_rri *a)
7748816f70bSRichard Henderson {
775cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
776af42d354SRichard Henderson     gen_add(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7778816f70bSRichard Henderson     return true;
7788816f70bSRichard Henderson }
779bbe418f2SJia Liu 
7803a7be554SRichard Henderson static bool trans_l_addic(DisasContext *dc, arg_rri *a)
781bbe418f2SJia Liu {
782cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
783af42d354SRichard Henderson     gen_addc(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7848816f70bSRichard Henderson     return true;
7858816f70bSRichard Henderson }
7868816f70bSRichard Henderson 
7873a7be554SRichard Henderson static bool trans_l_muli(DisasContext *dc, arg_rri *a)
7888816f70bSRichard Henderson {
789cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
790af42d354SRichard Henderson     gen_mul(dc, cpu_R(dc, a->d), cpu_R(dc, a->a), tcg_constant_tl(a->i));
7918816f70bSRichard Henderson     return true;
7928816f70bSRichard Henderson }
7938816f70bSRichard Henderson 
7943a7be554SRichard Henderson static bool trans_l_maci(DisasContext *dc, arg_l_maci *a)
7958816f70bSRichard Henderson {
796af42d354SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), tcg_constant_tl(a->i));
7978816f70bSRichard Henderson     return true;
7988816f70bSRichard Henderson }
7998816f70bSRichard Henderson 
8003a7be554SRichard Henderson static bool trans_l_andi(DisasContext *dc, arg_rrk *a)
8018816f70bSRichard Henderson {
802cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8038bba7619SRichard Henderson     tcg_gen_andi_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8048816f70bSRichard Henderson     return true;
8058816f70bSRichard Henderson }
8068816f70bSRichard Henderson 
8073a7be554SRichard Henderson static bool trans_l_ori(DisasContext *dc, arg_rrk *a)
8088816f70bSRichard Henderson {
809cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8108bba7619SRichard Henderson     tcg_gen_ori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->k);
8118816f70bSRichard Henderson     return true;
8128816f70bSRichard Henderson }
8138816f70bSRichard Henderson 
8143a7be554SRichard Henderson static bool trans_l_xori(DisasContext *dc, arg_rri *a)
8158816f70bSRichard Henderson {
816cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8178bba7619SRichard Henderson     tcg_gen_xori_tl(cpu_R(dc, a->d), cpu_R(dc, a->a), a->i);
8188816f70bSRichard Henderson     return true;
8198816f70bSRichard Henderson }
8208816f70bSRichard Henderson 
8213a7be554SRichard Henderson static bool trans_l_mfspr(DisasContext *dc, arg_l_mfspr *a)
8228816f70bSRichard Henderson {
823c28fa81fSRichard Henderson     TCGv spr = tcg_temp_new();
824b9e40bacSPavel Dovgalyuk 
82508f021deSStafford Horne     check_r0_write(dc, a->d);
82608f021deSStafford Horne 
827dfd1b812SRichard Henderson     if (translator_io_start(&dc->base)) {
828b9e40bacSPavel Dovgalyuk         if (dc->delayed_branch) {
829b9e40bacSPavel Dovgalyuk             tcg_gen_mov_tl(cpu_pc, jmp_pc);
830b9e40bacSPavel Dovgalyuk             tcg_gen_discard_tl(jmp_pc);
831b9e40bacSPavel Dovgalyuk         } else {
832b9e40bacSPavel Dovgalyuk             tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
833b9e40bacSPavel Dovgalyuk         }
834b9e40bacSPavel Dovgalyuk         dc->base.is_jmp = DISAS_EXIT;
835b9e40bacSPavel Dovgalyuk     }
836b9e40bacSPavel Dovgalyuk 
8378bba7619SRichard Henderson     tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
838ad75a51eSRichard Henderson     gen_helper_mfspr(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d), spr);
8398816f70bSRichard Henderson     return true;
8408816f70bSRichard Henderson }
841bbe418f2SJia Liu 
8423a7be554SRichard Henderson static bool trans_l_mtspr(DisasContext *dc, arg_l_mtspr *a)
8434dd044c6SJia Liu {
84408f021deSStafford Horne     TCGv spr = tcg_temp_new();
84501ec3ec9SRichard Henderson 
846dfd1b812SRichard Henderson     translator_io_start(&dc->base);
847dfd1b812SRichard Henderson 
84808f021deSStafford Horne     /*
84908f021deSStafford Horne      * For SR, we will need to exit the TB to recognize the new
85001ec3ec9SRichard Henderson      * exception state.  For NPC, in theory this counts as a branch
85101ec3ec9SRichard Henderson      * (although the SPR only exists for use by an ICE).  Save all
85201ec3ec9SRichard Henderson      * of the cpu state first, allowing it to be overwritten.
85301ec3ec9SRichard Henderson      */
85401ec3ec9SRichard Henderson     if (dc->delayed_branch) {
85501ec3ec9SRichard Henderson         tcg_gen_mov_tl(cpu_pc, jmp_pc);
85601ec3ec9SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
85701ec3ec9SRichard Henderson     } else {
85801ec3ec9SRichard Henderson         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next + 4);
85901ec3ec9SRichard Henderson     }
86001ec3ec9SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
86101ec3ec9SRichard Henderson 
8628bba7619SRichard Henderson     tcg_gen_ori_tl(spr, cpu_R(dc, a->a), a->k);
863ad75a51eSRichard Henderson     gen_helper_mtspr(tcg_env, spr, cpu_R(dc, a->b));
8648816f70bSRichard Henderson     return true;
865bbe418f2SJia Liu }
866bbe418f2SJia Liu 
8673a7be554SRichard Henderson static bool trans_l_mac(DisasContext *dc, arg_ab *a)
868bbe418f2SJia Liu {
8698bba7619SRichard Henderson     gen_mac(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
87099d863d6SRichard Henderson     return true;
871bbe418f2SJia Liu }
87299d863d6SRichard Henderson 
8733a7be554SRichard Henderson static bool trans_l_msb(DisasContext *dc, arg_ab *a)
87499d863d6SRichard Henderson {
8758bba7619SRichard Henderson     gen_msb(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
87699d863d6SRichard Henderson     return true;
87799d863d6SRichard Henderson }
87899d863d6SRichard Henderson 
8793a7be554SRichard Henderson static bool trans_l_macu(DisasContext *dc, arg_ab *a)
88099d863d6SRichard Henderson {
8818bba7619SRichard Henderson     gen_macu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
88299d863d6SRichard Henderson     return true;
88399d863d6SRichard Henderson }
88499d863d6SRichard Henderson 
8853a7be554SRichard Henderson static bool trans_l_msbu(DisasContext *dc, arg_ab *a)
88699d863d6SRichard Henderson {
8878bba7619SRichard Henderson     gen_msbu(dc, cpu_R(dc, a->a), cpu_R(dc, a->b));
88899d863d6SRichard Henderson     return true;
889bbe418f2SJia Liu }
890bbe418f2SJia Liu 
8913a7be554SRichard Henderson static bool trans_l_slli(DisasContext *dc, arg_dal *a)
892bbe418f2SJia Liu {
893cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
8948bba7619SRichard Henderson     tcg_gen_shli_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
8958bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
896e20c2592SRichard Henderson     return true;
897bbe418f2SJia Liu }
898e20c2592SRichard Henderson 
8993a7be554SRichard Henderson static bool trans_l_srli(DisasContext *dc, arg_dal *a)
900e20c2592SRichard Henderson {
901cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9028bba7619SRichard Henderson     tcg_gen_shri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9038bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
904e20c2592SRichard Henderson     return true;
905e20c2592SRichard Henderson }
906e20c2592SRichard Henderson 
9073a7be554SRichard Henderson static bool trans_l_srai(DisasContext *dc, arg_dal *a)
908e20c2592SRichard Henderson {
909cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9108bba7619SRichard Henderson     tcg_gen_sari_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9118bba7619SRichard Henderson                     a->l & (TARGET_LONG_BITS - 1));
912e20c2592SRichard Henderson     return true;
913e20c2592SRichard Henderson }
914e20c2592SRichard Henderson 
9153a7be554SRichard Henderson static bool trans_l_rori(DisasContext *dc, arg_dal *a)
916e20c2592SRichard Henderson {
917cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9188bba7619SRichard Henderson     tcg_gen_rotri_tl(cpu_R(dc, a->d), cpu_R(dc, a->a),
9198bba7619SRichard Henderson                      a->l & (TARGET_LONG_BITS - 1));
920e20c2592SRichard Henderson     return true;
921bbe418f2SJia Liu }
922bbe418f2SJia Liu 
9233a7be554SRichard Henderson static bool trans_l_movhi(DisasContext *dc, arg_l_movhi *a)
924bbe418f2SJia Liu {
925cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9268bba7619SRichard Henderson     tcg_gen_movi_tl(cpu_R(dc, a->d), a->k << 16);
927e720a571SRichard Henderson     return true;
928bbe418f2SJia Liu }
929e720a571SRichard Henderson 
9303a7be554SRichard Henderson static bool trans_l_macrc(DisasContext *dc, arg_l_macrc *a)
931e720a571SRichard Henderson {
932cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
9338bba7619SRichard Henderson     tcg_gen_trunc_i64_tl(cpu_R(dc, a->d), cpu_mac);
934e720a571SRichard Henderson     tcg_gen_movi_i64(cpu_mac, 0);
935e720a571SRichard Henderson     return true;
936bbe418f2SJia Liu }
937bbe418f2SJia Liu 
9383a7be554SRichard Henderson static bool trans_l_sfeq(DisasContext *dc, arg_ab *a)
939bbe418f2SJia Liu {
9408bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f,
9418bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
942fbb3e29aSRichard Henderson     return true;
943bbe418f2SJia Liu }
944fbb3e29aSRichard Henderson 
9453a7be554SRichard Henderson static bool trans_l_sfne(DisasContext *dc, arg_ab *a)
946fbb3e29aSRichard Henderson {
9478bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f,
9488bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
949fbb3e29aSRichard Henderson     return true;
950fbb3e29aSRichard Henderson }
951fbb3e29aSRichard Henderson 
9523a7be554SRichard Henderson static bool trans_l_sfgtu(DisasContext *dc, arg_ab *a)
953fbb3e29aSRichard Henderson {
9548bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f,
9558bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
956fbb3e29aSRichard Henderson     return true;
957fbb3e29aSRichard Henderson }
958fbb3e29aSRichard Henderson 
9593a7be554SRichard Henderson static bool trans_l_sfgeu(DisasContext *dc, arg_ab *a)
960fbb3e29aSRichard Henderson {
9618bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f,
9628bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
963fbb3e29aSRichard Henderson     return true;
964fbb3e29aSRichard Henderson }
965fbb3e29aSRichard Henderson 
9663a7be554SRichard Henderson static bool trans_l_sfltu(DisasContext *dc, arg_ab *a)
967fbb3e29aSRichard Henderson {
9688bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f,
9698bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
970fbb3e29aSRichard Henderson     return true;
971fbb3e29aSRichard Henderson }
972fbb3e29aSRichard Henderson 
9733a7be554SRichard Henderson static bool trans_l_sfleu(DisasContext *dc, arg_ab *a)
974fbb3e29aSRichard Henderson {
9758bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f,
9768bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
977fbb3e29aSRichard Henderson     return true;
978fbb3e29aSRichard Henderson }
979fbb3e29aSRichard Henderson 
9803a7be554SRichard Henderson static bool trans_l_sfgts(DisasContext *dc, arg_ab *a)
981fbb3e29aSRichard Henderson {
9828bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f,
9838bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
984fbb3e29aSRichard Henderson     return true;
985fbb3e29aSRichard Henderson }
986fbb3e29aSRichard Henderson 
9873a7be554SRichard Henderson static bool trans_l_sfges(DisasContext *dc, arg_ab *a)
988fbb3e29aSRichard Henderson {
9898bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f,
9908bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
991fbb3e29aSRichard Henderson     return true;
992fbb3e29aSRichard Henderson }
993fbb3e29aSRichard Henderson 
9943a7be554SRichard Henderson static bool trans_l_sflts(DisasContext *dc, arg_ab *a)
995fbb3e29aSRichard Henderson {
9968bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f,
9978bba7619SRichard Henderson                        cpu_R(dc, a->a), cpu_R(dc, a->b));
998fbb3e29aSRichard Henderson     return true;
999fbb3e29aSRichard Henderson }
1000fbb3e29aSRichard Henderson 
10013a7be554SRichard Henderson static bool trans_l_sfles(DisasContext *dc, arg_ab *a)
1002fbb3e29aSRichard Henderson {
10038bba7619SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LE,
10048bba7619SRichard Henderson                        cpu_sr_f, cpu_R(dc, a->a), cpu_R(dc, a->b));
1005fbb3e29aSRichard Henderson     return true;
1006bbe418f2SJia Liu }
1007bbe418f2SJia Liu 
10083a7be554SRichard Henderson static bool trans_l_sfeqi(DisasContext *dc, arg_ai *a)
1009bbe418f2SJia Liu {
10108bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R(dc, a->a), a->i);
1011032de4fcSRichard Henderson     return true;
1012bbe418f2SJia Liu }
1013032de4fcSRichard Henderson 
10143a7be554SRichard Henderson static bool trans_l_sfnei(DisasContext *dc, arg_ai *a)
1015032de4fcSRichard Henderson {
10168bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1017032de4fcSRichard Henderson     return true;
1018032de4fcSRichard Henderson }
1019032de4fcSRichard Henderson 
10203a7be554SRichard Henderson static bool trans_l_sfgtui(DisasContext *dc, arg_ai *a)
1021032de4fcSRichard Henderson {
10228bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1023032de4fcSRichard Henderson     return true;
1024032de4fcSRichard Henderson }
1025032de4fcSRichard Henderson 
10263a7be554SRichard Henderson static bool trans_l_sfgeui(DisasContext *dc, arg_ai *a)
1027032de4fcSRichard Henderson {
10288bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1029032de4fcSRichard Henderson     return true;
1030032de4fcSRichard Henderson }
1031032de4fcSRichard Henderson 
10323a7be554SRichard Henderson static bool trans_l_sfltui(DisasContext *dc, arg_ai *a)
1033032de4fcSRichard Henderson {
10348bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1035032de4fcSRichard Henderson     return true;
1036032de4fcSRichard Henderson }
1037032de4fcSRichard Henderson 
10383a7be554SRichard Henderson static bool trans_l_sfleui(DisasContext *dc, arg_ai *a)
1039032de4fcSRichard Henderson {
10408bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R(dc, a->a), a->i);
1041032de4fcSRichard Henderson     return true;
1042032de4fcSRichard Henderson }
1043032de4fcSRichard Henderson 
10443a7be554SRichard Henderson static bool trans_l_sfgtsi(DisasContext *dc, arg_ai *a)
1045032de4fcSRichard Henderson {
10468bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1047032de4fcSRichard Henderson     return true;
1048032de4fcSRichard Henderson }
1049032de4fcSRichard Henderson 
10503a7be554SRichard Henderson static bool trans_l_sfgesi(DisasContext *dc, arg_ai *a)
1051032de4fcSRichard Henderson {
10528bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1053032de4fcSRichard Henderson     return true;
1054032de4fcSRichard Henderson }
1055032de4fcSRichard Henderson 
10563a7be554SRichard Henderson static bool trans_l_sfltsi(DisasContext *dc, arg_ai *a)
1057032de4fcSRichard Henderson {
10588bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R(dc, a->a), a->i);
1059032de4fcSRichard Henderson     return true;
1060032de4fcSRichard Henderson }
1061032de4fcSRichard Henderson 
10623a7be554SRichard Henderson static bool trans_l_sflesi(DisasContext *dc, arg_ai *a)
1063032de4fcSRichard Henderson {
10648bba7619SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R(dc, a->a), a->i);
1065032de4fcSRichard Henderson     return true;
1066bbe418f2SJia Liu }
1067bbe418f2SJia Liu 
10683a7be554SRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a)
1069bbe418f2SJia Liu {
10701ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1071bbe418f2SJia Liu     gen_exception(dc, EXCP_SYSCALL);
10721ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
10737de9729fSRichard Henderson     return true;
10747de9729fSRichard Henderson }
1075bbe418f2SJia Liu 
10763a7be554SRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a)
10777de9729fSRichard Henderson {
10781ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1079bbe418f2SJia Liu     gen_exception(dc, EXCP_TRAP);
10801ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
10817de9729fSRichard Henderson     return true;
10827de9729fSRichard Henderson }
1083bbe418f2SJia Liu 
10843a7be554SRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a)
10857de9729fSRichard Henderson {
108624fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
10877de9729fSRichard Henderson     return true;
1088bbe418f2SJia Liu }
10897de9729fSRichard Henderson 
10903a7be554SRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a)
10917de9729fSRichard Henderson {
10927de9729fSRichard Henderson     return true;
10937de9729fSRichard Henderson }
10947de9729fSRichard Henderson 
10953a7be554SRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a)
10967de9729fSRichard Henderson {
10977de9729fSRichard Henderson     return true;
1098bbe418f2SJia Liu }
1099bbe418f2SJia Liu 
11003a7be554SRichard Henderson static bool trans_l_rfe(DisasContext *dc, arg_l_rfe *a)
11018816f70bSRichard Henderson {
11022ba65417SRichard Henderson     if (is_user(dc)) {
11038816f70bSRichard Henderson         gen_illegal_exception(dc);
11048816f70bSRichard Henderson     } else {
1105ad75a51eSRichard Henderson         gen_helper_rfe(tcg_env);
110664e46c95SRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
11078816f70bSRichard Henderson     }
11088816f70bSRichard Henderson     return true;
11098816f70bSRichard Henderson }
11108816f70bSRichard Henderson 
1111fe636d37SRichard Henderson static bool do_fp2(DisasContext *dc, arg_da *a,
11126fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv))
1113bbe418f2SJia Liu {
1114fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1115fe636d37SRichard Henderson         return false;
1116fe636d37SRichard Henderson     }
1117cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1118ad75a51eSRichard Henderson     fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a));
1119ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1120fe636d37SRichard Henderson     return true;
1121bbe418f2SJia Liu }
11226fd204a2SRichard Henderson 
1123fe636d37SRichard Henderson static bool do_fp3(DisasContext *dc, arg_dab *a,
11246fd204a2SRichard Henderson                    void (*fn)(TCGv, TCGv_env, TCGv, TCGv))
11256fd204a2SRichard Henderson {
1126fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1127fe636d37SRichard Henderson         return false;
1128fe636d37SRichard Henderson     }
1129cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1130ad75a51eSRichard Henderson     fn(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
1131ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1132fe636d37SRichard Henderson     return true;
11336fd204a2SRichard Henderson }
11346fd204a2SRichard Henderson 
1135fe636d37SRichard Henderson static bool do_fpcmp(DisasContext *dc, arg_ab *a,
11366fd204a2SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv, TCGv),
11376fd204a2SRichard Henderson                      bool inv, bool swap)
11386fd204a2SRichard Henderson {
1139fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1140fe636d37SRichard Henderson         return false;
1141fe636d37SRichard Henderson     }
11426fd204a2SRichard Henderson     if (swap) {
1143ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, cpu_R(dc, a->b), cpu_R(dc, a->a));
11446fd204a2SRichard Henderson     } else {
1145ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, cpu_R(dc, a->a), cpu_R(dc, a->b));
11466fd204a2SRichard Henderson     }
11476fd204a2SRichard Henderson     if (inv) {
11486fd204a2SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
11496fd204a2SRichard Henderson     }
1150ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
1151fe636d37SRichard Henderson     return true;
11526fd204a2SRichard Henderson }
11536fd204a2SRichard Henderson 
11543a7be554SRichard Henderson static bool trans_lf_add_s(DisasContext *dc, arg_dab *a)
11556fd204a2SRichard Henderson {
1156fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_add_s);
11576fd204a2SRichard Henderson }
11586fd204a2SRichard Henderson 
11593a7be554SRichard Henderson static bool trans_lf_sub_s(DisasContext *dc, arg_dab *a)
11606fd204a2SRichard Henderson {
1161fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_sub_s);
11626fd204a2SRichard Henderson }
11636fd204a2SRichard Henderson 
11643a7be554SRichard Henderson static bool trans_lf_mul_s(DisasContext *dc, arg_dab *a)
11656fd204a2SRichard Henderson {
1166fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_mul_s);
11676fd204a2SRichard Henderson }
11686fd204a2SRichard Henderson 
11693a7be554SRichard Henderson static bool trans_lf_div_s(DisasContext *dc, arg_dab *a)
11706fd204a2SRichard Henderson {
1171fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_div_s);
11726fd204a2SRichard Henderson }
11736fd204a2SRichard Henderson 
11743a7be554SRichard Henderson static bool trans_lf_rem_s(DisasContext *dc, arg_dab *a)
11756fd204a2SRichard Henderson {
1176fe636d37SRichard Henderson     return do_fp3(dc, a, gen_helper_float_rem_s);
11776fd204a2SRichard Henderson     return true;
11786fd204a2SRichard Henderson }
11796fd204a2SRichard Henderson 
11803a7be554SRichard Henderson static bool trans_lf_itof_s(DisasContext *dc, arg_da *a)
11816fd204a2SRichard Henderson {
1182fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_itofs);
11836fd204a2SRichard Henderson }
11846fd204a2SRichard Henderson 
11853a7be554SRichard Henderson static bool trans_lf_ftoi_s(DisasContext *dc, arg_da *a)
11866fd204a2SRichard Henderson {
1187fe636d37SRichard Henderson     return do_fp2(dc, a, gen_helper_ftois);
11886fd204a2SRichard Henderson }
11896fd204a2SRichard Henderson 
11903a7be554SRichard Henderson static bool trans_lf_madd_s(DisasContext *dc, arg_dab *a)
11916fd204a2SRichard Henderson {
1192fe636d37SRichard Henderson     if (!check_of32s(dc)) {
1193fe636d37SRichard Henderson         return false;
1194fe636d37SRichard Henderson     }
1195cdd0f459SRichard Henderson     check_r0_write(dc, a->d);
1196ad75a51eSRichard Henderson     gen_helper_float_madd_s(cpu_R(dc, a->d), tcg_env, cpu_R(dc, a->d),
11978bba7619SRichard Henderson                             cpu_R(dc, a->a), cpu_R(dc, a->b));
1198ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
11996fd204a2SRichard Henderson     return true;
12006fd204a2SRichard Henderson }
12016fd204a2SRichard Henderson 
12023a7be554SRichard Henderson static bool trans_lf_sfeq_s(DisasContext *dc, arg_ab *a)
12036fd204a2SRichard Henderson {
1204fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, false, false);
12056fd204a2SRichard Henderson }
12066fd204a2SRichard Henderson 
12073a7be554SRichard Henderson static bool trans_lf_sfne_s(DisasContext *dc, arg_ab *a)
12086fd204a2SRichard Henderson {
1209fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_eq_s, true, false);
12106fd204a2SRichard Henderson }
12116fd204a2SRichard Henderson 
12123a7be554SRichard Henderson static bool trans_lf_sfgt_s(DisasContext *dc, arg_ab *a)
12136fd204a2SRichard Henderson {
1214fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, true);
12156fd204a2SRichard Henderson }
12166fd204a2SRichard Henderson 
12173a7be554SRichard Henderson static bool trans_lf_sfge_s(DisasContext *dc, arg_ab *a)
12186fd204a2SRichard Henderson {
1219fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, true);
12206fd204a2SRichard Henderson }
12216fd204a2SRichard Henderson 
12223a7be554SRichard Henderson static bool trans_lf_sflt_s(DisasContext *dc, arg_ab *a)
12236fd204a2SRichard Henderson {
1224fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_lt_s, false, false);
12256fd204a2SRichard Henderson }
12266fd204a2SRichard Henderson 
12273a7be554SRichard Henderson static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a)
12286fd204a2SRichard Henderson {
1229fe636d37SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_le_s, false, false);
1230bbe418f2SJia Liu }
1231bbe418f2SJia Liu 
12322b13b4b9SRichard Henderson static bool trans_lf_sfueq_s(DisasContext *dc, arg_ab *a)
12332b13b4b9SRichard Henderson {
12342b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12352b13b4b9SRichard Henderson         return false;
12362b13b4b9SRichard Henderson     }
12372b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ueq_s, false, false);
12382b13b4b9SRichard Henderson }
12392b13b4b9SRichard Henderson 
12402b13b4b9SRichard Henderson static bool trans_lf_sfult_s(DisasContext *dc, arg_ab *a)
12412b13b4b9SRichard Henderson {
12422b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12432b13b4b9SRichard Henderson         return false;
12442b13b4b9SRichard Henderson     }
12452b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ult_s, false, false);
12462b13b4b9SRichard Henderson }
12472b13b4b9SRichard Henderson 
12482b13b4b9SRichard Henderson static bool trans_lf_sfugt_s(DisasContext *dc, arg_ab *a)
12492b13b4b9SRichard Henderson {
12502b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12512b13b4b9SRichard Henderson         return false;
12522b13b4b9SRichard Henderson     }
12532b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ult_s, false, true);
12542b13b4b9SRichard Henderson }
12552b13b4b9SRichard Henderson 
12562b13b4b9SRichard Henderson static bool trans_lf_sfule_s(DisasContext *dc, arg_ab *a)
12572b13b4b9SRichard Henderson {
12582b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12592b13b4b9SRichard Henderson         return false;
12602b13b4b9SRichard Henderson     }
12612b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ule_s, false, false);
12622b13b4b9SRichard Henderson }
12632b13b4b9SRichard Henderson 
12642b13b4b9SRichard Henderson static bool trans_lf_sfuge_s(DisasContext *dc, arg_ab *a)
12652b13b4b9SRichard Henderson {
12662b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12672b13b4b9SRichard Henderson         return false;
12682b13b4b9SRichard Henderson     }
12692b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_ule_s, false, true);
12702b13b4b9SRichard Henderson }
12712b13b4b9SRichard Henderson 
12722b13b4b9SRichard Henderson static bool trans_lf_sfun_s(DisasContext *dc, arg_ab *a)
12732b13b4b9SRichard Henderson {
12742b13b4b9SRichard Henderson     if (!check_v1_3(dc)) {
12752b13b4b9SRichard Henderson         return false;
12762b13b4b9SRichard Henderson     }
12772b13b4b9SRichard Henderson     return do_fpcmp(dc, a, gen_helper_float_un_s, false, false);
12782b13b4b9SRichard Henderson }
12792b13b4b9SRichard Henderson 
128062f2b038SRichard Henderson static bool check_pair(DisasContext *dc, int r, int p)
128162f2b038SRichard Henderson {
128262f2b038SRichard Henderson     return r + 1 + p < 32;
128362f2b038SRichard Henderson }
128462f2b038SRichard Henderson 
128562f2b038SRichard Henderson static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
128662f2b038SRichard Henderson {
128762f2b038SRichard Henderson     tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r));
128862f2b038SRichard Henderson }
128962f2b038SRichard Henderson 
129062f2b038SRichard Henderson static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p)
129162f2b038SRichard Henderson {
129262f2b038SRichard Henderson     tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t);
129362f2b038SRichard Henderson }
129462f2b038SRichard Henderson 
129562f2b038SRichard Henderson static bool do_dp3(DisasContext *dc, arg_dab_pair *a,
129662f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
129762f2b038SRichard Henderson {
129862f2b038SRichard Henderson     TCGv_i64 t0, t1;
129962f2b038SRichard Henderson 
130062f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
130162f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
130262f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
130362f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
130462f2b038SRichard Henderson         return false;
130562f2b038SRichard Henderson     }
130662f2b038SRichard Henderson     check_r0_write(dc, a->d);
130762f2b038SRichard Henderson 
130862f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
130962f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
131062f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
131162f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
1312ad75a51eSRichard Henderson     fn(t0, tcg_env, t0, t1);
131362f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
131462f2b038SRichard Henderson 
1315ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
131662f2b038SRichard Henderson     return true;
131762f2b038SRichard Henderson }
131862f2b038SRichard Henderson 
131962f2b038SRichard Henderson static bool do_dp2(DisasContext *dc, arg_da_pair *a,
132062f2b038SRichard Henderson                    void (*fn)(TCGv_i64, TCGv_env, TCGv_i64))
132162f2b038SRichard Henderson {
132262f2b038SRichard Henderson     TCGv_i64 t0;
132362f2b038SRichard Henderson 
132462f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
132562f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
132662f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
132762f2b038SRichard Henderson         return false;
132862f2b038SRichard Henderson     }
132962f2b038SRichard Henderson     check_r0_write(dc, a->d);
133062f2b038SRichard Henderson 
133162f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
133262f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1333ad75a51eSRichard Henderson     fn(t0, tcg_env, t0);
133462f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
133562f2b038SRichard Henderson 
1336ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
133762f2b038SRichard Henderson     return true;
133862f2b038SRichard Henderson }
133962f2b038SRichard Henderson 
134062f2b038SRichard Henderson static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a,
134162f2b038SRichard Henderson                      void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64),
134262f2b038SRichard Henderson                      bool inv, bool swap)
134362f2b038SRichard Henderson {
134462f2b038SRichard Henderson     TCGv_i64 t0, t1;
134562f2b038SRichard Henderson 
134662f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
134762f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
134862f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp)) {
134962f2b038SRichard Henderson         return false;
135062f2b038SRichard Henderson     }
135162f2b038SRichard Henderson 
135262f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
135362f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
135462f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
135562f2b038SRichard Henderson     load_pair(dc, t1, a->b, a->bp);
135662f2b038SRichard Henderson     if (swap) {
1357ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, t1, t0);
135862f2b038SRichard Henderson     } else {
1359ad75a51eSRichard Henderson         fn(cpu_sr_f, tcg_env, t0, t1);
136062f2b038SRichard Henderson     }
136162f2b038SRichard Henderson 
136262f2b038SRichard Henderson     if (inv) {
136362f2b038SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
136462f2b038SRichard Henderson     }
1365ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
136662f2b038SRichard Henderson     return true;
136762f2b038SRichard Henderson }
136862f2b038SRichard Henderson 
136962f2b038SRichard Henderson static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a)
137062f2b038SRichard Henderson {
137162f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_add_d);
137262f2b038SRichard Henderson }
137362f2b038SRichard Henderson 
137462f2b038SRichard Henderson static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a)
137562f2b038SRichard Henderson {
137662f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_sub_d);
137762f2b038SRichard Henderson }
137862f2b038SRichard Henderson 
137962f2b038SRichard Henderson static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a)
138062f2b038SRichard Henderson {
138162f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_mul_d);
138262f2b038SRichard Henderson }
138362f2b038SRichard Henderson 
138462f2b038SRichard Henderson static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a)
138562f2b038SRichard Henderson {
138662f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_div_d);
138762f2b038SRichard Henderson }
138862f2b038SRichard Henderson 
138962f2b038SRichard Henderson static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a)
139062f2b038SRichard Henderson {
139162f2b038SRichard Henderson     return do_dp3(dc, a, gen_helper_float_rem_d);
139262f2b038SRichard Henderson }
139362f2b038SRichard Henderson 
139462f2b038SRichard Henderson static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a)
139562f2b038SRichard Henderson {
139662f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_itofd);
139762f2b038SRichard Henderson }
139862f2b038SRichard Henderson 
139962f2b038SRichard Henderson static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a)
140062f2b038SRichard Henderson {
140162f2b038SRichard Henderson     return do_dp2(dc, a, gen_helper_ftoid);
140262f2b038SRichard Henderson }
140362f2b038SRichard Henderson 
140462f2b038SRichard Henderson static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a)
140562f2b038SRichard Henderson {
140662f2b038SRichard Henderson     TCGv_i64 t0;
140762f2b038SRichard Henderson 
140862f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
140962f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
141062f2b038SRichard Henderson         return false;
141162f2b038SRichard Henderson     }
141262f2b038SRichard Henderson     check_r0_write(dc, a->d);
141362f2b038SRichard Henderson 
141462f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
1415ad75a51eSRichard Henderson     gen_helper_stod(t0, tcg_env, cpu_R(dc, a->a));
141662f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
141762f2b038SRichard Henderson 
1418ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
141962f2b038SRichard Henderson     return true;
142062f2b038SRichard Henderson }
142162f2b038SRichard Henderson 
142262f2b038SRichard Henderson static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a)
142362f2b038SRichard Henderson {
142462f2b038SRichard Henderson     TCGv_i64 t0;
142562f2b038SRichard Henderson 
142662f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
142762f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap)) {
142862f2b038SRichard Henderson         return false;
142962f2b038SRichard Henderson     }
143062f2b038SRichard Henderson     check_r0_write(dc, a->d);
143162f2b038SRichard Henderson 
143262f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
143362f2b038SRichard Henderson     load_pair(dc, t0, a->a, a->ap);
1434ad75a51eSRichard Henderson     gen_helper_dtos(cpu_R(dc, a->d), tcg_env, t0);
143562f2b038SRichard Henderson 
1436ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
143762f2b038SRichard Henderson     return true;
143862f2b038SRichard Henderson }
143962f2b038SRichard Henderson 
144062f2b038SRichard Henderson static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a)
144162f2b038SRichard Henderson {
144262f2b038SRichard Henderson     TCGv_i64 t0, t1, t2;
144362f2b038SRichard Henderson 
144462f2b038SRichard Henderson     if (!check_of64a32s(dc) ||
144562f2b038SRichard Henderson         !check_pair(dc, a->a, a->ap) ||
144662f2b038SRichard Henderson         !check_pair(dc, a->b, a->bp) ||
144762f2b038SRichard Henderson         !check_pair(dc, a->d, a->dp)) {
144862f2b038SRichard Henderson         return false;
144962f2b038SRichard Henderson     }
145062f2b038SRichard Henderson     check_r0_write(dc, a->d);
145162f2b038SRichard Henderson 
145262f2b038SRichard Henderson     t0 = tcg_temp_new_i64();
145362f2b038SRichard Henderson     t1 = tcg_temp_new_i64();
145462f2b038SRichard Henderson     t2 = tcg_temp_new_i64();
145562f2b038SRichard Henderson     load_pair(dc, t0, a->d, a->dp);
145662f2b038SRichard Henderson     load_pair(dc, t1, a->a, a->ap);
145762f2b038SRichard Henderson     load_pair(dc, t2, a->b, a->bp);
1458ad75a51eSRichard Henderson     gen_helper_float_madd_d(t0, tcg_env, t0, t1, t2);
145962f2b038SRichard Henderson     save_pair(dc, t0, a->d, a->dp);
146062f2b038SRichard Henderson 
1461ad75a51eSRichard Henderson     gen_helper_update_fpcsr(tcg_env);
146262f2b038SRichard Henderson     return true;
146362f2b038SRichard Henderson }
146462f2b038SRichard Henderson 
146562f2b038SRichard Henderson static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a)
146662f2b038SRichard Henderson {
146762f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false);
146862f2b038SRichard Henderson }
146962f2b038SRichard Henderson 
147062f2b038SRichard Henderson static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a)
147162f2b038SRichard Henderson {
147262f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false);
147362f2b038SRichard Henderson }
147462f2b038SRichard Henderson 
147562f2b038SRichard Henderson static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a)
147662f2b038SRichard Henderson {
147762f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true);
147862f2b038SRichard Henderson }
147962f2b038SRichard Henderson 
148062f2b038SRichard Henderson static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a)
148162f2b038SRichard Henderson {
148262f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, true);
148362f2b038SRichard Henderson }
148462f2b038SRichard Henderson 
148562f2b038SRichard Henderson static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a)
148662f2b038SRichard Henderson {
148762f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false);
148862f2b038SRichard Henderson }
148962f2b038SRichard Henderson 
149062f2b038SRichard Henderson static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a)
149162f2b038SRichard Henderson {
149262f2b038SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_le_d, false, false);
149362f2b038SRichard Henderson }
149462f2b038SRichard Henderson 
14952b13b4b9SRichard Henderson static bool trans_lf_sfueq_d(DisasContext *dc, arg_ab_pair *a)
14962b13b4b9SRichard Henderson {
14972b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ueq_d, false, false);
14982b13b4b9SRichard Henderson }
14992b13b4b9SRichard Henderson 
15002b13b4b9SRichard Henderson static bool trans_lf_sfule_d(DisasContext *dc, arg_ab_pair *a)
15012b13b4b9SRichard Henderson {
15022b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ule_d, false, false);
15032b13b4b9SRichard Henderson }
15042b13b4b9SRichard Henderson 
15052b13b4b9SRichard Henderson static bool trans_lf_sfuge_d(DisasContext *dc, arg_ab_pair *a)
15062b13b4b9SRichard Henderson {
15072b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ule_d, false, true);
15082b13b4b9SRichard Henderson }
15092b13b4b9SRichard Henderson 
15102b13b4b9SRichard Henderson static bool trans_lf_sfult_d(DisasContext *dc, arg_ab_pair *a)
15112b13b4b9SRichard Henderson {
15122b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ult_d, false, false);
15132b13b4b9SRichard Henderson }
15142b13b4b9SRichard Henderson 
15152b13b4b9SRichard Henderson static bool trans_lf_sfugt_d(DisasContext *dc, arg_ab_pair *a)
15162b13b4b9SRichard Henderson {
15172b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_ult_d, false, true);
15182b13b4b9SRichard Henderson }
15192b13b4b9SRichard Henderson 
15202b13b4b9SRichard Henderson static bool trans_lf_sfun_d(DisasContext *dc, arg_ab_pair *a)
15212b13b4b9SRichard Henderson {
15222b13b4b9SRichard Henderson     return do_dpcmp(dc, a, gen_helper_float_un_d, false, false);
15232b13b4b9SRichard Henderson }
15242b13b4b9SRichard Henderson 
1525a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1526e67db06eSJia Liu {
1527a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
1528b77af26eSRichard Henderson     CPUOpenRISCState *env = cpu_env(cs);
1529a4fd3ec3SEmilio G. Cota     int bound;
1530bbe418f2SJia Liu 
15313b916140SRichard Henderson     dc->mem_idx = cpu_mmu_index(cs, false);
15321ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1533a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1534fe636d37SRichard Henderson     dc->cpucfgr = env->cpucfgr;
15352b13b4b9SRichard Henderson     dc->avr = env->avr;
15368000ba56SRichard Henderson     dc->jmp_pc_imm = -1;
15378000ba56SRichard Henderson 
1538a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1539a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1540190ce7fbSRichard Henderson }
1541bbe418f2SJia Liu 
1542a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1543a4fd3ec3SEmilio G. Cota {
1544a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1545bbe418f2SJia Liu 
15466597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15476597c28dSRichard Henderson        when it's true, which is the common case.  */
1548118671f0SRichard Henderson     dc->zero = tcg_constant_tl(0);
15496597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1550118671f0SRichard Henderson         dc->R0 = dc->zero;
15516597c28dSRichard Henderson     } else {
1552d29f4368SRichard Henderson         dc->R0 = cpu_regs[0];
15536597c28dSRichard Henderson     }
1554a4fd3ec3SEmilio G. Cota }
15556597c28dSRichard Henderson 
1556a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1557a4fd3ec3SEmilio G. Cota {
1558a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1559a4fd3ec3SEmilio G. Cota 
15601ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1561a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1562a4fd3ec3SEmilio G. Cota }
1563bbe418f2SJia Liu 
1564a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1565a4fd3ec3SEmilio G. Cota {
1566a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1567074bd799SPhilippe Mathieu-Daudé     uint32_t insn = translator_ldl(cpu_env(cs), &dc->base, dc->base.pc_next);
1568a4fd3ec3SEmilio G. Cota 
1569c7b6f54bSRichard Henderson     if (!decode(dc, insn)) {
1570c7b6f54bSRichard Henderson         gen_illegal_exception(dc);
1571c7b6f54bSRichard Henderson     }
15721ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
157324c32852SRichard Henderson 
15748000ba56SRichard Henderson     /* When exiting the delay slot normally, exit via jmp_pc.
15758000ba56SRichard Henderson      * For DISAS_NORETURN, we have raised an exception and already exited.
15768000ba56SRichard Henderson      * For DISAS_EXIT, we found l.rfe in a delay slot.  There's nothing
15778000ba56SRichard Henderson      * in the manual saying this is illegal, but it surely it should.
15788000ba56SRichard Henderson      * At least or1ksim overrides pcnext and ignores the branch.
15798000ba56SRichard Henderson      */
15808000ba56SRichard Henderson     if (dc->delayed_branch
15818000ba56SRichard Henderson         && --dc->delayed_branch == 0
15828000ba56SRichard Henderson         && dc->base.is_jmp == DISAS_NEXT) {
15838000ba56SRichard Henderson         dc->base.is_jmp = DISAS_JUMP;
1584bbe418f2SJia Liu     }
1585a4fd3ec3SEmilio G. Cota }
1586bbe418f2SJia Liu 
1587a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1588a4fd3ec3SEmilio G. Cota {
1589a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
15908000ba56SRichard Henderson     target_ulong jmp_dest;
159124c32852SRichard Henderson 
1592e0a369cfSRichard Henderson     /* If we have already exited the TB, nothing following has effect.  */
1593e0a369cfSRichard Henderson     if (dc->base.is_jmp == DISAS_NORETURN) {
1594e0a369cfSRichard Henderson         return;
1595e0a369cfSRichard Henderson     }
1596e0a369cfSRichard Henderson 
15978000ba56SRichard Henderson     /* Adjust the delayed branch state for the next TB.  */
1598a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1599a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1600a01deb36SRichard Henderson     }
1601a01deb36SRichard Henderson 
16028000ba56SRichard Henderson     /* For DISAS_TOO_MANY, jump to the next insn.  */
16038000ba56SRichard Henderson     jmp_dest = dc->base.pc_next;
16048000ba56SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, jmp_dest - 4);
16058000ba56SRichard Henderson 
16061ffa4bceSEmilio G. Cota     switch (dc->base.is_jmp) {
16078000ba56SRichard Henderson     case DISAS_JUMP:
16088000ba56SRichard Henderson         jmp_dest = dc->jmp_pc_imm;
16098000ba56SRichard Henderson         if (jmp_dest == -1) {
16108000ba56SRichard Henderson             /* The jump destination is indirect/computed; use jmp_pc.  */
16118000ba56SRichard Henderson             tcg_gen_mov_tl(cpu_pc, jmp_pc);
16128000ba56SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
16138000ba56SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
1614bbe418f2SJia Liu             break;
16158000ba56SRichard Henderson         }
16168000ba56SRichard Henderson         /* The jump destination is direct; use jmp_pc_imm.
16178000ba56SRichard Henderson            However, we will have stored into jmp_pc as well;
16188000ba56SRichard Henderson            we know now that it wasn't needed.  */
16198000ba56SRichard Henderson         tcg_gen_discard_tl(jmp_pc);
16208000ba56SRichard Henderson         /* fallthru */
16218000ba56SRichard Henderson 
16228000ba56SRichard Henderson     case DISAS_TOO_MANY:
1623adf1f3deSRichard Henderson         if (translator_use_goto_tb(&dc->base, jmp_dest)) {
16248000ba56SRichard Henderson             tcg_gen_goto_tb(0);
16258000ba56SRichard Henderson             tcg_gen_movi_tl(cpu_pc, jmp_dest);
16268000ba56SRichard Henderson             tcg_gen_exit_tb(dc->base.tb, 0);
1627adf1f3deSRichard Henderson             break;
1628adf1f3deSRichard Henderson         }
1629adf1f3deSRichard Henderson         tcg_gen_movi_tl(cpu_pc, jmp_dest);
1630adf1f3deSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
16318000ba56SRichard Henderson         break;
16328000ba56SRichard Henderson 
163364e46c95SRichard Henderson     case DISAS_EXIT:
163407ea28b4SRichard Henderson         tcg_gen_exit_tb(NULL, 0);
1635bbe418f2SJia Liu         break;
1636a4fd3ec3SEmilio G. Cota     default:
1637a4fd3ec3SEmilio G. Cota         g_assert_not_reached();
1638a4fd3ec3SEmilio G. Cota     }
1639bbe418f2SJia Liu }
1640bbe418f2SJia Liu 
1641a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1642a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1643a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1644a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1645a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1646a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1647a4fd3ec3SEmilio G. Cota };
1648a4fd3ec3SEmilio G. Cota 
1649597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
165032f0c394SAnton Johansson                            vaddr pc, void *host_pc)
1651a4fd3ec3SEmilio G. Cota {
1652a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1653a4fd3ec3SEmilio G. Cota 
1654306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc,
1655306c8721SRichard Henderson                     &openrisc_tr_ops, &ctx.base);
1656e67db06eSJia Liu }
1657e67db06eSJia Liu 
165890c84c56SMarkus Armbruster void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
1659e67db06eSJia Liu {
1660074bd799SPhilippe Mathieu-Daudé     CPUOpenRISCState *env = cpu_env(cs);
1661e67db06eSJia Liu     int i;
1662878096eeSAndreas Färber 
166390c84c56SMarkus Armbruster     qemu_fprintf(f, "PC=%08x\n", env->pc);
1664e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
166590c84c56SMarkus Armbruster         qemu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1666e67db06eSJia Liu                      (i % 4) == 3 ? '\n' : ' ');
1667e67db06eSJia Liu     }
1668e67db06eSJia Liu }
1669