xref: /qemu/target/openrisc/translate.c (revision a4fd3ec3c7299f6a0f99e89aeb8a52c6538ca27b)
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
10e67db06eSJia Liu  * version 2 of the License, or (at your option) any later version.
11e67db06eSJia Liu  *
12e67db06eSJia Liu  * This library is distributed in the hope that it will be useful,
13e67db06eSJia Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14e67db06eSJia Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15e67db06eSJia Liu  * Lesser General Public License for more details.
16e67db06eSJia Liu  *
17e67db06eSJia Liu  * You should have received a copy of the GNU Lesser General Public
18e67db06eSJia Liu  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19e67db06eSJia Liu  */
20e67db06eSJia Liu 
21ed2decc6SPeter Maydell #include "qemu/osdep.h"
22e67db06eSJia Liu #include "cpu.h"
23022c62cbSPaolo Bonzini #include "exec/exec-all.h"
2476cad711SPaolo Bonzini #include "disas/disas.h"
25e67db06eSJia Liu #include "tcg-op.h"
26e67db06eSJia Liu #include "qemu-common.h"
271de7afc9SPaolo Bonzini #include "qemu/log.h"
281de7afc9SPaolo Bonzini #include "qemu/bitops.h"
29f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
3077fc6f5eSLluís Vilanova #include "exec/translator.h"
31bbe418f2SJia Liu 
322ef6175aSRichard Henderson #include "exec/helper-proto.h"
332ef6175aSRichard Henderson #include "exec/helper-gen.h"
34e67db06eSJia Liu 
35a7e30d84SLluís Vilanova #include "trace-tcg.h"
36508127e2SPaolo Bonzini #include "exec/log.h"
37a7e30d84SLluís Vilanova 
38111ece51SRichard Henderson #define LOG_DIS(str, ...) \
391ffa4bceSEmilio G. Cota     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->base.pc_next,    \
401ffa4bceSEmilio G. Cota                   ## __VA_ARGS__)
41e67db06eSJia Liu 
4277fc6f5eSLluís Vilanova /* is_jmp field values */
4377fc6f5eSLluís Vilanova #define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
4477fc6f5eSLluís Vilanova #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
4577fc6f5eSLluís Vilanova #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
4677fc6f5eSLluís Vilanova 
47bbe418f2SJia Liu typedef struct DisasContext {
481ffa4bceSEmilio G. Cota     DisasContextBase base;
49bbe418f2SJia Liu     uint32_t mem_idx;
50a01deb36SRichard Henderson     uint32_t tb_flags;
51bbe418f2SJia Liu     uint32_t delayed_branch;
52bbe418f2SJia Liu } DisasContext;
53bbe418f2SJia Liu 
54bbe418f2SJia Liu static TCGv cpu_sr;
55bbe418f2SJia Liu static TCGv cpu_R[32];
566597c28dSRichard Henderson static TCGv cpu_R0;
57bbe418f2SJia Liu static TCGv cpu_pc;
58bbe418f2SJia Liu static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
59bbe418f2SJia Liu static TCGv cpu_ppc;
6084775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
6197458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
6297458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
63930c3d00SRichard Henderson static TCGv cpu_lock_addr;
64930c3d00SRichard Henderson static TCGv cpu_lock_value;
65bbe418f2SJia Liu static TCGv_i32 fpcsr;
666f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
67a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
68022c62cbSPaolo Bonzini #include "exec/gen-icount.h"
69bbe418f2SJia Liu 
70e67db06eSJia Liu void openrisc_translate_init(void)
71e67db06eSJia Liu {
72bbe418f2SJia Liu     static const char * const regnames[] = {
73bbe418f2SJia Liu         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
74bbe418f2SJia Liu         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
75bbe418f2SJia Liu         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
76bbe418f2SJia Liu         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
77bbe418f2SJia Liu     };
78bbe418f2SJia Liu     int i;
79bbe418f2SJia Liu 
80e1ccc054SRichard Henderson     cpu_sr = tcg_global_mem_new(cpu_env,
81bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, sr), "sr");
82a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
83a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
84a01deb36SRichard Henderson                                        "dflag");
85e1ccc054SRichard Henderson     cpu_pc = tcg_global_mem_new(cpu_env,
86bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, pc), "pc");
87e1ccc054SRichard Henderson     cpu_ppc = tcg_global_mem_new(cpu_env,
88bbe418f2SJia Liu                                  offsetof(CPUOpenRISCState, ppc), "ppc");
89e1ccc054SRichard Henderson     jmp_pc = tcg_global_mem_new(cpu_env,
90bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
9184775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
9284775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
9397458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
9497458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
9597458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
9697458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
97930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
98930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
99930c3d00SRichard Henderson                                        "lock_addr");
100930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
101930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
102930c3d00SRichard Henderson                                         "lock_value");
103e1ccc054SRichard Henderson     fpcsr = tcg_global_mem_new_i32(cpu_env,
104bbe418f2SJia Liu                                    offsetof(CPUOpenRISCState, fpcsr),
105bbe418f2SJia Liu                                    "fpcsr");
1066f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1076f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1086f7332baSRichard Henderson                                      "mac");
109bbe418f2SJia Liu     for (i = 0; i < 32; i++) {
110e1ccc054SRichard Henderson         cpu_R[i] = tcg_global_mem_new(cpu_env,
111d89e71e8SStafford Horne                                       offsetof(CPUOpenRISCState,
112d89e71e8SStafford Horne                                                shadow_gpr[0][i]),
113bbe418f2SJia Liu                                       regnames[i]);
114bbe418f2SJia Liu     }
1156597c28dSRichard Henderson     cpu_R0 = cpu_R[0];
116bbe418f2SJia Liu }
117bbe418f2SJia Liu 
118bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp)
119bbe418f2SJia Liu {
120bbe418f2SJia Liu     TCGv_i32 tmp = tcg_const_i32(excp);
121bbe418f2SJia Liu     gen_helper_exception(cpu_env, tmp);
122bbe418f2SJia Liu     tcg_temp_free_i32(tmp);
123bbe418f2SJia Liu }
124bbe418f2SJia Liu 
125bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc)
126bbe418f2SJia Liu {
1271ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
128bbe418f2SJia Liu     gen_exception(dc, EXCP_ILLEGAL);
1291ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
130bbe418f2SJia Liu }
131bbe418f2SJia Liu 
132bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
133bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
134bbe418f2SJia Liu static void check_ob64s(DisasContext *dc)
135bbe418f2SJia Liu {
136bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OB64S)) {
137bbe418f2SJia Liu         gen_illegal_exception(dc);
138bbe418f2SJia Liu     }
139bbe418f2SJia Liu }
140bbe418f2SJia Liu 
141bbe418f2SJia Liu static void check_of64s(DisasContext *dc)
142bbe418f2SJia Liu {
143bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OF64S)) {
144bbe418f2SJia Liu         gen_illegal_exception(dc);
145bbe418f2SJia Liu     }
146bbe418f2SJia Liu }
147bbe418f2SJia Liu 
148bbe418f2SJia Liu static void check_ov64s(DisasContext *dc)
149bbe418f2SJia Liu {
150bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OV64S)) {
151bbe418f2SJia Liu         gen_illegal_exception(dc);
152bbe418f2SJia Liu     }
153bbe418f2SJia Liu }
154bbe418f2SJia Liu #endif*/
155bbe418f2SJia Liu 
1566597c28dSRichard Henderson /* We're about to write to REG.  On the off-chance that the user is
1576597c28dSRichard Henderson    writing to R0, re-instate the architectural register.  */
1586597c28dSRichard Henderson #define check_r0_write(reg)             \
1596597c28dSRichard Henderson     do {                                \
1606597c28dSRichard Henderson         if (unlikely(reg == 0)) {       \
1616597c28dSRichard Henderson             cpu_R[0] = cpu_R0;          \
1626597c28dSRichard Henderson         }                               \
1636597c28dSRichard Henderson     } while (0)
1646597c28dSRichard Henderson 
16590aa39a1SSergey Fedorov static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
16690aa39a1SSergey Fedorov {
1671ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
16890aa39a1SSergey Fedorov         return false;
16990aa39a1SSergey Fedorov     }
17090aa39a1SSergey Fedorov 
17190aa39a1SSergey Fedorov #ifndef CONFIG_USER_ONLY
1721ffa4bceSEmilio G. Cota     return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
17390aa39a1SSergey Fedorov #else
17490aa39a1SSergey Fedorov     return true;
17590aa39a1SSergey Fedorov #endif
17690aa39a1SSergey Fedorov }
17790aa39a1SSergey Fedorov 
178bbe418f2SJia Liu static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
179bbe418f2SJia Liu {
18090aa39a1SSergey Fedorov     if (use_goto_tb(dc, dest)) {
181bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dest);
182bbe418f2SJia Liu         tcg_gen_goto_tb(n);
1831ffa4bceSEmilio G. Cota         tcg_gen_exit_tb((uintptr_t)dc->base.tb + n);
184bbe418f2SJia Liu     } else {
185bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dest);
1861ffa4bceSEmilio G. Cota         if (dc->base.singlestep_enabled) {
187bbe418f2SJia Liu             gen_exception(dc, EXCP_DEBUG);
188bbe418f2SJia Liu         }
189bbe418f2SJia Liu         tcg_gen_exit_tb(0);
190bbe418f2SJia Liu     }
191bbe418f2SJia Liu }
192bbe418f2SJia Liu 
1936da544a6SRichard Henderson static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
194bbe418f2SJia Liu {
1951ffa4bceSEmilio G. Cota     target_ulong tmp_pc = dc->base.pc_next + n26 * 4;
196bbe418f2SJia Liu 
197da1d7759SSebastian Macke     switch (op0) {
198da1d7759SSebastian Macke     case 0x00:     /* l.j */
199bbe418f2SJia Liu         tcg_gen_movi_tl(jmp_pc, tmp_pc);
200da1d7759SSebastian Macke         break;
201da1d7759SSebastian Macke     case 0x01:     /* l.jal */
2021ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8);
203a8000cb4SRichard Henderson         /* Optimize jal being used to load the PC for PIC.  */
2041ffa4bceSEmilio G. Cota         if (tmp_pc == dc->base.pc_next + 8) {
205a8000cb4SRichard Henderson             return;
206a8000cb4SRichard Henderson         }
207bbe418f2SJia Liu         tcg_gen_movi_tl(jmp_pc, tmp_pc);
208da1d7759SSebastian Macke         break;
209da1d7759SSebastian Macke     case 0x03:     /* l.bnf */
210da1d7759SSebastian Macke     case 0x04:     /* l.bf  */
211da1d7759SSebastian Macke         {
2121ffa4bceSEmilio G. Cota             TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
213784696d1SRichard Henderson             TCGv t_true = tcg_const_tl(tmp_pc);
214784696d1SRichard Henderson             TCGv t_zero = tcg_const_tl(0);
215784696d1SRichard Henderson 
216784696d1SRichard Henderson             tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
217784696d1SRichard Henderson                                jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
218784696d1SRichard Henderson 
219784696d1SRichard Henderson             tcg_temp_free(t_next);
220784696d1SRichard Henderson             tcg_temp_free(t_true);
221784696d1SRichard Henderson             tcg_temp_free(t_zero);
222da1d7759SSebastian Macke         }
223da1d7759SSebastian Macke         break;
224da1d7759SSebastian Macke     case 0x11:     /* l.jr */
225bbe418f2SJia Liu         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
226da1d7759SSebastian Macke         break;
227da1d7759SSebastian Macke     case 0x12:     /* l.jalr */
2281ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_R[9], (dc->base.pc_next + 8));
229bbe418f2SJia Liu         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
230da1d7759SSebastian Macke         break;
231da1d7759SSebastian Macke     default:
232bbe418f2SJia Liu         gen_illegal_exception(dc);
233da1d7759SSebastian Macke         break;
234bbe418f2SJia Liu     }
235bbe418f2SJia Liu 
236bbe418f2SJia Liu     dc->delayed_branch = 2;
237bbe418f2SJia Liu }
238bbe418f2SJia Liu 
23997458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
2409ecaa27eSRichard Henderson {
2410c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
24297458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
2439ecaa27eSRichard Henderson     }
2440c53d734SRichard Henderson }
2459ecaa27eSRichard Henderson 
24697458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
2479ecaa27eSRichard Henderson {
2480c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
24997458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
2509ecaa27eSRichard Henderson     }
2510c53d734SRichard Henderson }
2529ecaa27eSRichard Henderson 
25397458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
2549ecaa27eSRichard Henderson {
2550c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
25697458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
2579ecaa27eSRichard Henderson     }
2580c53d734SRichard Henderson }
2599ecaa27eSRichard Henderson 
2609ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2619ecaa27eSRichard Henderson {
2629ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2639ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2649ecaa27eSRichard Henderson 
26597458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
26697458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2679ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
26897458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2699ecaa27eSRichard Henderson     tcg_temp_free(t0);
2709ecaa27eSRichard Henderson 
2719ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2729ecaa27eSRichard Henderson     tcg_temp_free(res);
2739ecaa27eSRichard Henderson 
27497458071SRichard Henderson     gen_ove_cyov(dc);
2759ecaa27eSRichard Henderson }
2769ecaa27eSRichard Henderson 
2779ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2789ecaa27eSRichard Henderson {
2799ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2809ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2819ecaa27eSRichard Henderson 
28297458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
28397458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
28497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2859ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
28697458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2879ecaa27eSRichard Henderson     tcg_temp_free(t0);
2889ecaa27eSRichard Henderson 
2899ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2909ecaa27eSRichard Henderson     tcg_temp_free(res);
2919ecaa27eSRichard Henderson 
29297458071SRichard Henderson     gen_ove_cyov(dc);
2939ecaa27eSRichard Henderson }
2949ecaa27eSRichard Henderson 
2959ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2969ecaa27eSRichard Henderson {
2979ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2989ecaa27eSRichard Henderson 
2999ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
30097458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
30197458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
30297458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
30397458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
3049ecaa27eSRichard Henderson 
3059ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
3069ecaa27eSRichard Henderson     tcg_temp_free(res);
3079ecaa27eSRichard Henderson 
30897458071SRichard Henderson     gen_ove_cyov(dc);
3099ecaa27eSRichard Henderson }
3109ecaa27eSRichard Henderson 
3119ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3129ecaa27eSRichard Henderson {
3139ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3149ecaa27eSRichard Henderson 
31597458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
3169ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
31797458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
3189ecaa27eSRichard Henderson     tcg_temp_free(t0);
3199ecaa27eSRichard Henderson 
32097458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
32197458071SRichard Henderson     gen_ove_ov(dc);
3229ecaa27eSRichard Henderson }
3239ecaa27eSRichard Henderson 
3249ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3259ecaa27eSRichard Henderson {
32697458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
32797458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
3289ecaa27eSRichard Henderson 
32997458071SRichard Henderson     gen_ove_cy(dc);
3309ecaa27eSRichard Henderson }
3319ecaa27eSRichard Henderson 
3329ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3339ecaa27eSRichard Henderson {
3349ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3359ecaa27eSRichard Henderson 
33697458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
3379ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3389ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
33997458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
3409ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
3419ecaa27eSRichard Henderson     tcg_temp_free(t0);
3429ecaa27eSRichard Henderson 
34397458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
34497458071SRichard Henderson     gen_ove_ov(dc);
3459ecaa27eSRichard Henderson }
3469ecaa27eSRichard Henderson 
3479ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3489ecaa27eSRichard Henderson {
3499ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3509ecaa27eSRichard Henderson 
35197458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
3529ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3539ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
35497458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
3559ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
3569ecaa27eSRichard Henderson     tcg_temp_free(t0);
3579ecaa27eSRichard Henderson 
35897458071SRichard Henderson     gen_ove_cy(dc);
3599ecaa27eSRichard Henderson }
360da1d7759SSebastian Macke 
361cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
362cc5de49eSRichard Henderson {
363cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
364cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
365cc5de49eSRichard Henderson 
366cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
367cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
368cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
369cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
370cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
371cc5de49eSRichard Henderson     } else {
372cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
373cc5de49eSRichard Henderson 
374cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
375cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
376cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
377cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
378cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
379cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
380cc5de49eSRichard Henderson 
381cc5de49eSRichard Henderson         gen_ove_ov(dc);
382cc5de49eSRichard Henderson     }
383cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
384cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
385cc5de49eSRichard Henderson }
386cc5de49eSRichard Henderson 
387cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
388cc5de49eSRichard Henderson {
389cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
390cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
391cc5de49eSRichard Henderson 
392cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
393cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
394cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
395cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
396cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
397cc5de49eSRichard Henderson     } else {
398cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
399cc5de49eSRichard Henderson 
400cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
401cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
402cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
403cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
404cc5de49eSRichard Henderson 
405cc5de49eSRichard Henderson         gen_ove_cy(dc);
406cc5de49eSRichard Henderson     }
407cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
408cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
409cc5de49eSRichard Henderson }
410cc5de49eSRichard Henderson 
4116f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
4126f7332baSRichard Henderson {
4136f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4146f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4156f7332baSRichard Henderson 
4166f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4176f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4186f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4196f7332baSRichard Henderson 
4206f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
4216f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4226f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
4236f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4246f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
4256f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4266f7332baSRichard Henderson 
4276f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4286f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4296f7332baSRichard Henderson #else
4306f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4316f7332baSRichard Henderson #endif
4326f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4336f7332baSRichard Henderson 
4346f7332baSRichard Henderson     gen_ove_ov(dc);
4356f7332baSRichard Henderson }
4366f7332baSRichard Henderson 
437cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
438cc5de49eSRichard Henderson {
439cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
440cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
441cc5de49eSRichard Henderson 
442cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
443cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
444cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
445cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
446cc5de49eSRichard Henderson 
447cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
448cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
449cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
450cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
451cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
452cc5de49eSRichard Henderson 
453cc5de49eSRichard Henderson     gen_ove_cy(dc);
454cc5de49eSRichard Henderson }
455cc5de49eSRichard Henderson 
4566f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
4576f7332baSRichard Henderson {
4586f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4596f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4606f7332baSRichard Henderson 
4616f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4626f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4636f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4646f7332baSRichard Henderson 
4656f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4666f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4676f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4686f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4696f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4706f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4716f7332baSRichard Henderson 
4726f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4736f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4746f7332baSRichard Henderson #else
4756f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4766f7332baSRichard Henderson #endif
4776f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4786f7332baSRichard Henderson 
4796f7332baSRichard Henderson     gen_ove_ov(dc);
4806f7332baSRichard Henderson }
4816f7332baSRichard Henderson 
482cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
483cc5de49eSRichard Henderson {
484cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
485cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
486cc5de49eSRichard Henderson 
487cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
488cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
489cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
490cc5de49eSRichard Henderson 
491cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
492cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
493cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
494cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
495cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
496cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
497cc5de49eSRichard Henderson 
498cc5de49eSRichard Henderson     gen_ove_cy(dc);
499cc5de49eSRichard Henderson }
500cc5de49eSRichard Henderson 
501930c3d00SRichard Henderson static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
502930c3d00SRichard Henderson {
503930c3d00SRichard Henderson     TCGv ea = tcg_temp_new();
504930c3d00SRichard Henderson 
505930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
506930c3d00SRichard Henderson     tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
507930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
508930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, rd);
509930c3d00SRichard Henderson     tcg_temp_free(ea);
510930c3d00SRichard Henderson }
511930c3d00SRichard Henderson 
5126597c28dSRichard Henderson static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs)
513930c3d00SRichard Henderson {
514930c3d00SRichard Henderson     TCGv ea, val;
515930c3d00SRichard Henderson     TCGLabel *lab_fail, *lab_done;
516930c3d00SRichard Henderson 
517930c3d00SRichard Henderson     ea = tcg_temp_new();
518930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
519930c3d00SRichard Henderson 
5206597c28dSRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
5216597c28dSRichard Henderson        to cpu_R[0].  Since l.swa is quite often immediately followed by a
5226597c28dSRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
5236597c28dSRichard Henderson        This also takes care of RB input across the branch.  */
5246597c28dSRichard Henderson     cpu_R[0] = cpu_R0;
5256597c28dSRichard Henderson 
526930c3d00SRichard Henderson     lab_fail = gen_new_label();
527930c3d00SRichard Henderson     lab_done = gen_new_label();
528930c3d00SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
529930c3d00SRichard Henderson     tcg_temp_free(ea);
530930c3d00SRichard Henderson 
531930c3d00SRichard Henderson     val = tcg_temp_new();
532930c3d00SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
5336597c28dSRichard Henderson                               cpu_R[b], dc->mem_idx, MO_TEUL);
53484775c43SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
535930c3d00SRichard Henderson     tcg_temp_free(val);
536930c3d00SRichard Henderson 
537930c3d00SRichard Henderson     tcg_gen_br(lab_done);
538930c3d00SRichard Henderson 
539930c3d00SRichard Henderson     gen_set_label(lab_fail);
54084775c43SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
541930c3d00SRichard Henderson 
542930c3d00SRichard Henderson     gen_set_label(lab_done);
543930c3d00SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
544930c3d00SRichard Henderson }
545930c3d00SRichard Henderson 
546bbe418f2SJia Liu static void dec_calc(DisasContext *dc, uint32_t insn)
547bbe418f2SJia Liu {
548bbe418f2SJia Liu     uint32_t op0, op1, op2;
549bbe418f2SJia Liu     uint32_t ra, rb, rd;
550bbe418f2SJia Liu     op0 = extract32(insn, 0, 4);
551bbe418f2SJia Liu     op1 = extract32(insn, 8, 2);
552bbe418f2SJia Liu     op2 = extract32(insn, 6, 2);
553bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
554bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
555bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
556bbe418f2SJia Liu 
557bbe418f2SJia Liu     switch (op1) {
558cf2ae442SRichard Henderson     case 0:
559cf2ae442SRichard Henderson         switch (op0) {
560cf2ae442SRichard Henderson         case 0x0: /* l.add */
561bbe418f2SJia Liu             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
5629ecaa27eSRichard Henderson             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
563cf2ae442SRichard Henderson             return;
564bbe418f2SJia Liu 
565cf2ae442SRichard Henderson         case 0x1: /* l.addc */
566bbe418f2SJia Liu             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
5679ecaa27eSRichard Henderson             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
568cf2ae442SRichard Henderson             return;
569bbe418f2SJia Liu 
570cf2ae442SRichard Henderson         case 0x2: /* l.sub */
571bbe418f2SJia Liu             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
5729ecaa27eSRichard Henderson             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
573cf2ae442SRichard Henderson             return;
574bbe418f2SJia Liu 
575cf2ae442SRichard Henderson         case 0x3: /* l.and */
576bbe418f2SJia Liu             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
577bbe418f2SJia Liu             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
578cf2ae442SRichard Henderson             return;
579bbe418f2SJia Liu 
580cf2ae442SRichard Henderson         case 0x4: /* l.or */
581bbe418f2SJia Liu             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
582bbe418f2SJia Liu             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
583cf2ae442SRichard Henderson             return;
584bbe418f2SJia Liu 
585cf2ae442SRichard Henderson         case 0x5: /* l.xor */
586bbe418f2SJia Liu             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
587bbe418f2SJia Liu             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
588cf2ae442SRichard Henderson             return;
589cf2ae442SRichard Henderson 
590cf2ae442SRichard Henderson         case 0x8:
591cf2ae442SRichard Henderson             switch (op2) {
592cf2ae442SRichard Henderson             case 0: /* l.sll */
593cf2ae442SRichard Henderson                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
594cf2ae442SRichard Henderson                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
595cf2ae442SRichard Henderson                 return;
596cf2ae442SRichard Henderson             case 1: /* l.srl */
597cf2ae442SRichard Henderson                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
598cf2ae442SRichard Henderson                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
599cf2ae442SRichard Henderson                 return;
600cf2ae442SRichard Henderson             case 2: /* l.sra */
601cf2ae442SRichard Henderson                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
602cf2ae442SRichard Henderson                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
603cf2ae442SRichard Henderson                 return;
604cf2ae442SRichard Henderson             case 3: /* l.ror */
605cf2ae442SRichard Henderson                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
606cf2ae442SRichard Henderson                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
607cf2ae442SRichard Henderson                 return;
608bbe418f2SJia Liu             }
609bbe418f2SJia Liu             break;
610bbe418f2SJia Liu 
611cf2ae442SRichard Henderson         case 0xc:
612cf2ae442SRichard Henderson             switch (op2) {
613cf2ae442SRichard Henderson             case 0: /* l.exths */
614cf2ae442SRichard Henderson                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
615cf2ae442SRichard Henderson                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
616cf2ae442SRichard Henderson                 return;
617cf2ae442SRichard Henderson             case 1: /* l.extbs */
618cf2ae442SRichard Henderson                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
619cf2ae442SRichard Henderson                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
620cf2ae442SRichard Henderson                 return;
621cf2ae442SRichard Henderson             case 2: /* l.exthz */
622cf2ae442SRichard Henderson                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
623cf2ae442SRichard Henderson                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
624cf2ae442SRichard Henderson                 return;
625cf2ae442SRichard Henderson             case 3: /* l.extbz */
626cf2ae442SRichard Henderson                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
627cf2ae442SRichard Henderson                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
628cf2ae442SRichard Henderson                 return;
629bbe418f2SJia Liu             }
630bbe418f2SJia Liu             break;
631bbe418f2SJia Liu 
632cf2ae442SRichard Henderson         case 0xd:
633cf2ae442SRichard Henderson             switch (op2) {
634cf2ae442SRichard Henderson             case 0: /* l.extws */
635cf2ae442SRichard Henderson                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
636cf2ae442SRichard Henderson                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
637cf2ae442SRichard Henderson                 return;
638cf2ae442SRichard Henderson             case 1: /* l.extwz */
639cf2ae442SRichard Henderson                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
640cf2ae442SRichard Henderson                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
641cf2ae442SRichard Henderson                 return;
642bbe418f2SJia Liu             }
643bbe418f2SJia Liu             break;
644bbe418f2SJia Liu 
645cf2ae442SRichard Henderson         case 0xe: /* l.cmov */
646bbe418f2SJia Liu             LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
647bbe418f2SJia Liu             {
648784696d1SRichard Henderson                 TCGv zero = tcg_const_tl(0);
649784696d1SRichard Henderson                 tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero,
650784696d1SRichard Henderson                                    cpu_R[ra], cpu_R[rb]);
651784696d1SRichard Henderson                 tcg_temp_free(zero);
652bbe418f2SJia Liu             }
653cf2ae442SRichard Henderson             return;
654bbe418f2SJia Liu 
655cf2ae442SRichard Henderson         case 0xf: /* l.ff1 */
656bbe418f2SJia Liu             LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
657555baef8SRichard Henderson             tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1);
658555baef8SRichard Henderson             tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1);
659cf2ae442SRichard Henderson             return;
660cf2ae442SRichard Henderson         }
661bbe418f2SJia Liu         break;
662cf2ae442SRichard Henderson 
663cf2ae442SRichard Henderson     case 1:
664cf2ae442SRichard Henderson         switch (op0) {
665cf2ae442SRichard Henderson         case 0xf: /* l.fl1 */
666bbe418f2SJia Liu             LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
667555baef8SRichard Henderson             tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS);
668555baef8SRichard Henderson             tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]);
669cf2ae442SRichard Henderson             return;
670bbe418f2SJia Liu         }
671bbe418f2SJia Liu         break;
672bbe418f2SJia Liu 
673cf2ae442SRichard Henderson     case 2:
674bbe418f2SJia Liu         break;
675bbe418f2SJia Liu 
676cf2ae442SRichard Henderson     case 3:
677cf2ae442SRichard Henderson         switch (op0) {
678cf2ae442SRichard Henderson         case 0x6: /* l.mul */
679cf2ae442SRichard Henderson             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
680cf2ae442SRichard Henderson             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
681cf2ae442SRichard Henderson             return;
682cf2ae442SRichard Henderson 
683cc5de49eSRichard Henderson         case 0x7: /* l.muld */
684cc5de49eSRichard Henderson             LOG_DIS("l.muld r%d, r%d\n", ra, rb);
685cc5de49eSRichard Henderson             gen_muld(dc, cpu_R[ra], cpu_R[rb]);
686cc5de49eSRichard Henderson             break;
687cc5de49eSRichard Henderson 
688cf2ae442SRichard Henderson         case 0x9: /* l.div */
689cf2ae442SRichard Henderson             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
690cf2ae442SRichard Henderson             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
691cf2ae442SRichard Henderson             return;
692cf2ae442SRichard Henderson 
693cf2ae442SRichard Henderson         case 0xa: /* l.divu */
694cf2ae442SRichard Henderson             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
695cf2ae442SRichard Henderson             gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
696cf2ae442SRichard Henderson             return;
697cf2ae442SRichard Henderson 
698cf2ae442SRichard Henderson         case 0xb: /* l.mulu */
699cf2ae442SRichard Henderson             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
700cf2ae442SRichard Henderson             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
701cf2ae442SRichard Henderson             return;
702cc5de49eSRichard Henderson 
703cc5de49eSRichard Henderson         case 0xc: /* l.muldu */
704cc5de49eSRichard Henderson             LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
705cc5de49eSRichard Henderson             gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
706cc5de49eSRichard Henderson             return;
707bbe418f2SJia Liu         }
708bbe418f2SJia Liu         break;
709bbe418f2SJia Liu     }
710bbe418f2SJia Liu     gen_illegal_exception(dc);
711bbe418f2SJia Liu }
712bbe418f2SJia Liu 
713bbe418f2SJia Liu static void dec_misc(DisasContext *dc, uint32_t insn)
714bbe418f2SJia Liu {
715bbe418f2SJia Liu     uint32_t op0, op1;
716bbe418f2SJia Liu     uint32_t ra, rb, rd;
7176da544a6SRichard Henderson     uint32_t L6, K5, K16, K5_11;
7186da544a6SRichard Henderson     int32_t I16, I5_11, N26;
7195631e69cSRichard Henderson     TCGMemOp mop;
7209ecaa27eSRichard Henderson     TCGv t0;
7215631e69cSRichard Henderson 
722bbe418f2SJia Liu     op0 = extract32(insn, 26, 6);
723bbe418f2SJia Liu     op1 = extract32(insn, 24, 2);
724bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
725bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
726bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
727bbe418f2SJia Liu     L6 = extract32(insn, 5, 6);
728bbe418f2SJia Liu     K5 = extract32(insn, 0, 5);
7296da544a6SRichard Henderson     K16 = extract32(insn, 0, 16);
7306da544a6SRichard Henderson     I16 = (int16_t)K16;
7316da544a6SRichard Henderson     N26 = sextract32(insn, 0, 26);
7326da544a6SRichard Henderson     K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
7336da544a6SRichard Henderson     I5_11 = (int16_t)K5_11;
734bbe418f2SJia Liu 
735bbe418f2SJia Liu     switch (op0) {
736bbe418f2SJia Liu     case 0x00:    /* l.j */
737bbe418f2SJia Liu         LOG_DIS("l.j %d\n", N26);
738bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
739bbe418f2SJia Liu         break;
740bbe418f2SJia Liu 
741bbe418f2SJia Liu     case 0x01:    /* l.jal */
742bbe418f2SJia Liu         LOG_DIS("l.jal %d\n", N26);
743bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
744bbe418f2SJia Liu         break;
745bbe418f2SJia Liu 
746bbe418f2SJia Liu     case 0x03:    /* l.bnf */
747bbe418f2SJia Liu         LOG_DIS("l.bnf %d\n", N26);
748bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
749bbe418f2SJia Liu         break;
750bbe418f2SJia Liu 
751bbe418f2SJia Liu     case 0x04:    /* l.bf */
752bbe418f2SJia Liu         LOG_DIS("l.bf %d\n", N26);
753bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
754bbe418f2SJia Liu         break;
755bbe418f2SJia Liu 
756bbe418f2SJia Liu     case 0x05:
757bbe418f2SJia Liu         switch (op1) {
758bbe418f2SJia Liu         case 0x01:    /* l.nop */
759bbe418f2SJia Liu             LOG_DIS("l.nop %d\n", I16);
760bbe418f2SJia Liu             break;
761bbe418f2SJia Liu 
762bbe418f2SJia Liu         default:
763bbe418f2SJia Liu             gen_illegal_exception(dc);
764bbe418f2SJia Liu             break;
765bbe418f2SJia Liu         }
766bbe418f2SJia Liu         break;
767bbe418f2SJia Liu 
768bbe418f2SJia Liu     case 0x11:    /* l.jr */
769bbe418f2SJia Liu         LOG_DIS("l.jr r%d\n", rb);
770bbe418f2SJia Liu          gen_jump(dc, 0, rb, op0);
771bbe418f2SJia Liu          break;
772bbe418f2SJia Liu 
773bbe418f2SJia Liu     case 0x12:    /* l.jalr */
774bbe418f2SJia Liu         LOG_DIS("l.jalr r%d\n", rb);
775bbe418f2SJia Liu         gen_jump(dc, 0, rb, op0);
776bbe418f2SJia Liu         break;
777bbe418f2SJia Liu 
778bbe418f2SJia Liu     case 0x13:    /* l.maci */
7796da544a6SRichard Henderson         LOG_DIS("l.maci r%d, %d\n", ra, I16);
7806f7332baSRichard Henderson         t0 = tcg_const_tl(I16);
7816f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], t0);
7826f7332baSRichard Henderson         tcg_temp_free(t0);
783bbe418f2SJia Liu         break;
784bbe418f2SJia Liu 
785bbe418f2SJia Liu     case 0x09:    /* l.rfe */
786bbe418f2SJia Liu         LOG_DIS("l.rfe\n");
787bbe418f2SJia Liu         {
788bbe418f2SJia Liu #if defined(CONFIG_USER_ONLY)
789bbe418f2SJia Liu             return;
790bbe418f2SJia Liu #else
791bbe418f2SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
792bbe418f2SJia Liu                 gen_illegal_exception(dc);
793bbe418f2SJia Liu                 return;
794bbe418f2SJia Liu             }
795bbe418f2SJia Liu             gen_helper_rfe(cpu_env);
7961ffa4bceSEmilio G. Cota             dc->base.is_jmp = DISAS_UPDATE;
797bbe418f2SJia Liu #endif
798bbe418f2SJia Liu         }
799bbe418f2SJia Liu         break;
800bbe418f2SJia Liu 
801930c3d00SRichard Henderson     case 0x1b: /* l.lwa */
802930c3d00SRichard Henderson         LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
8036597c28dSRichard Henderson         check_r0_write(rd);
804930c3d00SRichard Henderson         gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
805930c3d00SRichard Henderson         break;
806930c3d00SRichard Henderson 
807bbe418f2SJia Liu     case 0x1c:    /* l.cust1 */
808bbe418f2SJia Liu         LOG_DIS("l.cust1\n");
809bbe418f2SJia Liu         break;
810bbe418f2SJia Liu 
811bbe418f2SJia Liu     case 0x1d:    /* l.cust2 */
812bbe418f2SJia Liu         LOG_DIS("l.cust2\n");
813bbe418f2SJia Liu         break;
814bbe418f2SJia Liu 
815bbe418f2SJia Liu     case 0x1e:    /* l.cust3 */
816bbe418f2SJia Liu         LOG_DIS("l.cust3\n");
817bbe418f2SJia Liu         break;
818bbe418f2SJia Liu 
819bbe418f2SJia Liu     case 0x1f:    /* l.cust4 */
820bbe418f2SJia Liu         LOG_DIS("l.cust4\n");
821bbe418f2SJia Liu         break;
822bbe418f2SJia Liu 
823bbe418f2SJia Liu     case 0x3c:    /* l.cust5 */
824bbe418f2SJia Liu         LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);
825bbe418f2SJia Liu         break;
826bbe418f2SJia Liu 
827bbe418f2SJia Liu     case 0x3d:    /* l.cust6 */
828bbe418f2SJia Liu         LOG_DIS("l.cust6\n");
829bbe418f2SJia Liu         break;
830bbe418f2SJia Liu 
831bbe418f2SJia Liu     case 0x3e:    /* l.cust7 */
832bbe418f2SJia Liu         LOG_DIS("l.cust7\n");
833bbe418f2SJia Liu         break;
834bbe418f2SJia Liu 
835bbe418f2SJia Liu     case 0x3f:    /* l.cust8 */
836bbe418f2SJia Liu         LOG_DIS("l.cust8\n");
837bbe418f2SJia Liu         break;
838bbe418f2SJia Liu 
839bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
840bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
841bbe418f2SJia Liu     case 0x20:     l.ld
842bbe418f2SJia Liu         LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
843bbe418f2SJia Liu         check_ob64s(dc);
8445631e69cSRichard Henderson         mop = MO_TEQ;
8455631e69cSRichard Henderson         goto do_load;
846bbe418f2SJia Liu #endif*/
847bbe418f2SJia Liu 
848bbe418f2SJia Liu     case 0x21:    /* l.lwz */
849bbe418f2SJia Liu         LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
8505631e69cSRichard Henderson         mop = MO_TEUL;
8515631e69cSRichard Henderson         goto do_load;
852bbe418f2SJia Liu 
853bbe418f2SJia Liu     case 0x22:    /* l.lws */
854bbe418f2SJia Liu         LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
8555631e69cSRichard Henderson         mop = MO_TESL;
8565631e69cSRichard Henderson         goto do_load;
857bbe418f2SJia Liu 
858bbe418f2SJia Liu     case 0x23:    /* l.lbz */
859bbe418f2SJia Liu         LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
8605631e69cSRichard Henderson         mop = MO_UB;
8615631e69cSRichard Henderson         goto do_load;
862bbe418f2SJia Liu 
863bbe418f2SJia Liu     case 0x24:    /* l.lbs */
864bbe418f2SJia Liu         LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
8655631e69cSRichard Henderson         mop = MO_SB;
8665631e69cSRichard Henderson         goto do_load;
867bbe418f2SJia Liu 
868bbe418f2SJia Liu     case 0x25:    /* l.lhz */
869bbe418f2SJia Liu         LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
8705631e69cSRichard Henderson         mop = MO_TEUW;
8715631e69cSRichard Henderson         goto do_load;
872bbe418f2SJia Liu 
873bbe418f2SJia Liu     case 0x26:    /* l.lhs */
874bbe418f2SJia Liu         LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
8755631e69cSRichard Henderson         mop = MO_TESW;
8765631e69cSRichard Henderson         goto do_load;
8775631e69cSRichard Henderson 
8785631e69cSRichard Henderson     do_load:
8796597c28dSRichard Henderson         check_r0_write(rd);
8806597c28dSRichard Henderson         t0 = tcg_temp_new();
8816da544a6SRichard Henderson         tcg_gen_addi_tl(t0, cpu_R[ra], I16);
8825631e69cSRichard Henderson         tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
883bbe418f2SJia Liu         tcg_temp_free(t0);
884bbe418f2SJia Liu         break;
885bbe418f2SJia Liu 
886bbe418f2SJia Liu     case 0x27:    /* l.addi */
887bbe418f2SJia Liu         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
8886597c28dSRichard Henderson         check_r0_write(rd);
8899ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
8909ecaa27eSRichard Henderson         gen_add(dc, cpu_R[rd], cpu_R[ra], t0);
8919ecaa27eSRichard Henderson         tcg_temp_free(t0);
892bbe418f2SJia Liu         break;
893bbe418f2SJia Liu 
894bbe418f2SJia Liu     case 0x28:    /* l.addic */
895bbe418f2SJia Liu         LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
8966597c28dSRichard Henderson         check_r0_write(rd);
8979ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
8989ecaa27eSRichard Henderson         gen_addc(dc, cpu_R[rd], cpu_R[ra], t0);
8999ecaa27eSRichard Henderson         tcg_temp_free(t0);
900bbe418f2SJia Liu         break;
901bbe418f2SJia Liu 
902bbe418f2SJia Liu     case 0x29:    /* l.andi */
9036da544a6SRichard Henderson         LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16);
9046597c28dSRichard Henderson         check_r0_write(rd);
9056da544a6SRichard Henderson         tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16);
906bbe418f2SJia Liu         break;
907bbe418f2SJia Liu 
908bbe418f2SJia Liu     case 0x2a:    /* l.ori */
9096da544a6SRichard Henderson         LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16);
9106597c28dSRichard Henderson         check_r0_write(rd);
9116da544a6SRichard Henderson         tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16);
912bbe418f2SJia Liu         break;
913bbe418f2SJia Liu 
914bbe418f2SJia Liu     case 0x2b:    /* l.xori */
915bbe418f2SJia Liu         LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
9166597c28dSRichard Henderson         check_r0_write(rd);
9176da544a6SRichard Henderson         tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16);
918bbe418f2SJia Liu         break;
919bbe418f2SJia Liu 
920bbe418f2SJia Liu     case 0x2c:    /* l.muli */
921bbe418f2SJia Liu         LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
9226597c28dSRichard Henderson         check_r0_write(rd);
9239ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
9249ecaa27eSRichard Henderson         gen_mul(dc, cpu_R[rd], cpu_R[ra], t0);
9259ecaa27eSRichard Henderson         tcg_temp_free(t0);
926bbe418f2SJia Liu         break;
927bbe418f2SJia Liu 
928bbe418f2SJia Liu     case 0x2d:    /* l.mfspr */
9296da544a6SRichard Henderson         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
9306597c28dSRichard Henderson         check_r0_write(rd);
9314dd044c6SJia Liu         {
9324dd044c6SJia Liu #if defined(CONFIG_USER_ONLY)
9334dd044c6SJia Liu             return;
9344dd044c6SJia Liu #else
9356da544a6SRichard Henderson             TCGv_i32 ti = tcg_const_i32(K16);
9364dd044c6SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
9374dd044c6SJia Liu                 gen_illegal_exception(dc);
9384dd044c6SJia Liu                 return;
9394dd044c6SJia Liu             }
9404dd044c6SJia Liu             gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
9414dd044c6SJia Liu             tcg_temp_free_i32(ti);
9424dd044c6SJia Liu #endif
9434dd044c6SJia Liu         }
944bbe418f2SJia Liu         break;
945bbe418f2SJia Liu 
946bbe418f2SJia Liu     case 0x30:    /* l.mtspr */
9476da544a6SRichard Henderson         LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11);
9484dd044c6SJia Liu         {
9494dd044c6SJia Liu #if defined(CONFIG_USER_ONLY)
9504dd044c6SJia Liu             return;
9514dd044c6SJia Liu #else
9526da544a6SRichard Henderson             TCGv_i32 im = tcg_const_i32(K5_11);
9534dd044c6SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
9544dd044c6SJia Liu                 gen_illegal_exception(dc);
9554dd044c6SJia Liu                 return;
9564dd044c6SJia Liu             }
9574dd044c6SJia Liu             gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
9584dd044c6SJia Liu             tcg_temp_free_i32(im);
9594dd044c6SJia Liu #endif
9604dd044c6SJia Liu         }
961bbe418f2SJia Liu         break;
962bbe418f2SJia Liu 
963930c3d00SRichard Henderson     case 0x33: /* l.swa */
9646da544a6SRichard Henderson         LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
9656597c28dSRichard Henderson         gen_swa(dc, rb, cpu_R[ra], I5_11);
966930c3d00SRichard Henderson         break;
967930c3d00SRichard Henderson 
968bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
969bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
970bbe418f2SJia Liu     case 0x34:     l.sd
9716da544a6SRichard Henderson         LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
972bbe418f2SJia Liu         check_ob64s(dc);
9735631e69cSRichard Henderson         mop = MO_TEQ;
9745631e69cSRichard Henderson         goto do_store;
975bbe418f2SJia Liu #endif*/
976bbe418f2SJia Liu 
977bbe418f2SJia Liu     case 0x35:    /* l.sw */
9786da544a6SRichard Henderson         LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
9795631e69cSRichard Henderson         mop = MO_TEUL;
9805631e69cSRichard Henderson         goto do_store;
981bbe418f2SJia Liu 
982bbe418f2SJia Liu     case 0x36:    /* l.sb */
9836da544a6SRichard Henderson         LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
9845631e69cSRichard Henderson         mop = MO_UB;
9855631e69cSRichard Henderson         goto do_store;
986bbe418f2SJia Liu 
987bbe418f2SJia Liu     case 0x37:    /* l.sh */
9886da544a6SRichard Henderson         LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
9895631e69cSRichard Henderson         mop = MO_TEUW;
9905631e69cSRichard Henderson         goto do_store;
9915631e69cSRichard Henderson 
9925631e69cSRichard Henderson     do_store:
993bbe418f2SJia Liu         {
994bbe418f2SJia Liu             TCGv t0 = tcg_temp_new();
9956da544a6SRichard Henderson             tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
9965631e69cSRichard Henderson             tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
997bbe418f2SJia Liu             tcg_temp_free(t0);
998bbe418f2SJia Liu         }
999bbe418f2SJia Liu         break;
1000bbe418f2SJia Liu 
1001bbe418f2SJia Liu     default:
1002bbe418f2SJia Liu         gen_illegal_exception(dc);
1003bbe418f2SJia Liu         break;
1004bbe418f2SJia Liu     }
1005bbe418f2SJia Liu }
1006bbe418f2SJia Liu 
1007bbe418f2SJia Liu static void dec_mac(DisasContext *dc, uint32_t insn)
1008bbe418f2SJia Liu {
1009bbe418f2SJia Liu     uint32_t op0;
1010bbe418f2SJia Liu     uint32_t ra, rb;
1011bbe418f2SJia Liu     op0 = extract32(insn, 0, 4);
1012bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1013bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1014bbe418f2SJia Liu 
1015bbe418f2SJia Liu     switch (op0) {
1016bbe418f2SJia Liu     case 0x0001:    /* l.mac */
1017bbe418f2SJia Liu         LOG_DIS("l.mac r%d, r%d\n", ra, rb);
10186f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], cpu_R[rb]);
1019bbe418f2SJia Liu         break;
1020bbe418f2SJia Liu 
1021bbe418f2SJia Liu     case 0x0002:    /* l.msb */
1022bbe418f2SJia Liu         LOG_DIS("l.msb r%d, r%d\n", ra, rb);
10236f7332baSRichard Henderson         gen_msb(dc, cpu_R[ra], cpu_R[rb]);
1024bbe418f2SJia Liu         break;
1025bbe418f2SJia Liu 
1026cc5de49eSRichard Henderson     case 0x0003:    /* l.macu */
1027cc5de49eSRichard Henderson         LOG_DIS("l.macu r%d, r%d\n", ra, rb);
1028cc5de49eSRichard Henderson         gen_macu(dc, cpu_R[ra], cpu_R[rb]);
1029cc5de49eSRichard Henderson         break;
1030cc5de49eSRichard Henderson 
1031cc5de49eSRichard Henderson     case 0x0004:    /* l.msbu */
1032cc5de49eSRichard Henderson         LOG_DIS("l.msbu r%d, r%d\n", ra, rb);
1033cc5de49eSRichard Henderson         gen_msbu(dc, cpu_R[ra], cpu_R[rb]);
1034cc5de49eSRichard Henderson         break;
1035cc5de49eSRichard Henderson 
1036bbe418f2SJia Liu     default:
1037bbe418f2SJia Liu         gen_illegal_exception(dc);
1038bbe418f2SJia Liu         break;
1039bbe418f2SJia Liu    }
1040bbe418f2SJia Liu }
1041bbe418f2SJia Liu 
1042bbe418f2SJia Liu static void dec_logic(DisasContext *dc, uint32_t insn)
1043bbe418f2SJia Liu {
1044bbe418f2SJia Liu     uint32_t op0;
10456da544a6SRichard Henderson     uint32_t rd, ra, L6, S6;
1046bbe418f2SJia Liu     op0 = extract32(insn, 6, 2);
1047bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1048bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1049bbe418f2SJia Liu     L6 = extract32(insn, 0, 6);
10506da544a6SRichard Henderson     S6 = L6 & (TARGET_LONG_BITS - 1);
1051bbe418f2SJia Liu 
10526597c28dSRichard Henderson     check_r0_write(rd);
1053bbe418f2SJia Liu     switch (op0) {
1054bbe418f2SJia Liu     case 0x00:    /* l.slli */
1055bbe418f2SJia Liu         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
10566da544a6SRichard Henderson         tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6);
1057bbe418f2SJia Liu         break;
1058bbe418f2SJia Liu 
1059bbe418f2SJia Liu     case 0x01:    /* l.srli */
1060bbe418f2SJia Liu         LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
10616da544a6SRichard Henderson         tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6);
1062bbe418f2SJia Liu         break;
1063bbe418f2SJia Liu 
1064bbe418f2SJia Liu     case 0x02:    /* l.srai */
1065bbe418f2SJia Liu         LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
10666da544a6SRichard Henderson         tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6);
10676da544a6SRichard Henderson         break;
1068bbe418f2SJia Liu 
1069bbe418f2SJia Liu     case 0x03:    /* l.rori */
1070bbe418f2SJia Liu         LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
10716da544a6SRichard Henderson         tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6);
1072bbe418f2SJia Liu         break;
1073bbe418f2SJia Liu 
1074bbe418f2SJia Liu     default:
1075bbe418f2SJia Liu         gen_illegal_exception(dc);
1076bbe418f2SJia Liu         break;
1077bbe418f2SJia Liu     }
1078bbe418f2SJia Liu }
1079bbe418f2SJia Liu 
1080bbe418f2SJia Liu static void dec_M(DisasContext *dc, uint32_t insn)
1081bbe418f2SJia Liu {
1082bbe418f2SJia Liu     uint32_t op0;
1083bbe418f2SJia Liu     uint32_t rd;
1084bbe418f2SJia Liu     uint32_t K16;
1085bbe418f2SJia Liu     op0 = extract32(insn, 16, 1);
1086bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1087bbe418f2SJia Liu     K16 = extract32(insn, 0, 16);
1088bbe418f2SJia Liu 
10896597c28dSRichard Henderson     check_r0_write(rd);
1090bbe418f2SJia Liu     switch (op0) {
1091bbe418f2SJia Liu     case 0x0:    /* l.movhi */
1092bbe418f2SJia Liu         LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
1093bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
1094bbe418f2SJia Liu         break;
1095bbe418f2SJia Liu 
1096bbe418f2SJia Liu     case 0x1:    /* l.macrc */
1097bbe418f2SJia Liu         LOG_DIS("l.macrc  r%d\n", rd);
10986f7332baSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
10996f7332baSRichard Henderson         tcg_gen_movi_i64(cpu_mac, 0);
1100bbe418f2SJia Liu         break;
1101bbe418f2SJia Liu 
1102bbe418f2SJia Liu     default:
1103bbe418f2SJia Liu         gen_illegal_exception(dc);
1104bbe418f2SJia Liu         break;
1105bbe418f2SJia Liu     }
1106bbe418f2SJia Liu }
1107bbe418f2SJia Liu 
1108bbe418f2SJia Liu static void dec_comp(DisasContext *dc, uint32_t insn)
1109bbe418f2SJia Liu {
1110bbe418f2SJia Liu     uint32_t op0;
1111bbe418f2SJia Liu     uint32_t ra, rb;
1112bbe418f2SJia Liu 
1113bbe418f2SJia Liu     op0 = extract32(insn, 21, 5);
1114bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1115bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1116bbe418f2SJia Liu 
1117bbe418f2SJia Liu     /* unsigned integers  */
1118bbe418f2SJia Liu     tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
1119bbe418f2SJia Liu     tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
1120bbe418f2SJia Liu 
1121bbe418f2SJia Liu     switch (op0) {
1122bbe418f2SJia Liu     case 0x0:    /* l.sfeq */
1123bbe418f2SJia Liu         LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
112484775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1125bbe418f2SJia Liu         break;
1126bbe418f2SJia Liu 
1127bbe418f2SJia Liu     case 0x1:    /* l.sfne */
1128bbe418f2SJia Liu         LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
112984775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1130bbe418f2SJia Liu         break;
1131bbe418f2SJia Liu 
1132bbe418f2SJia Liu     case 0x2:    /* l.sfgtu */
1133bbe418f2SJia Liu         LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
113484775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1135bbe418f2SJia Liu         break;
1136bbe418f2SJia Liu 
1137bbe418f2SJia Liu     case 0x3:    /* l.sfgeu */
1138bbe418f2SJia Liu         LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
113984775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1140bbe418f2SJia Liu         break;
1141bbe418f2SJia Liu 
1142bbe418f2SJia Liu     case 0x4:    /* l.sfltu */
1143bbe418f2SJia Liu         LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
114484775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1145bbe418f2SJia Liu         break;
1146bbe418f2SJia Liu 
1147bbe418f2SJia Liu     case 0x5:    /* l.sfleu */
1148bbe418f2SJia Liu         LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
114984775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1150bbe418f2SJia Liu         break;
1151bbe418f2SJia Liu 
1152bbe418f2SJia Liu     case 0xa:    /* l.sfgts */
1153bbe418f2SJia Liu         LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
115484775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1155bbe418f2SJia Liu         break;
1156bbe418f2SJia Liu 
1157bbe418f2SJia Liu     case 0xb:    /* l.sfges */
1158bbe418f2SJia Liu         LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
115984775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1160bbe418f2SJia Liu         break;
1161bbe418f2SJia Liu 
1162bbe418f2SJia Liu     case 0xc:    /* l.sflts */
1163bbe418f2SJia Liu         LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
116484775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1165bbe418f2SJia Liu         break;
1166bbe418f2SJia Liu 
1167bbe418f2SJia Liu     case 0xd:    /* l.sfles */
1168bbe418f2SJia Liu         LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
116984775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1170bbe418f2SJia Liu         break;
1171bbe418f2SJia Liu 
1172bbe418f2SJia Liu     default:
1173bbe418f2SJia Liu         gen_illegal_exception(dc);
1174bbe418f2SJia Liu         break;
1175bbe418f2SJia Liu     }
1176bbe418f2SJia Liu }
1177bbe418f2SJia Liu 
1178bbe418f2SJia Liu static void dec_compi(DisasContext *dc, uint32_t insn)
1179bbe418f2SJia Liu {
11806da544a6SRichard Henderson     uint32_t op0, ra;
11816da544a6SRichard Henderson     int32_t I16;
1182bbe418f2SJia Liu 
1183bbe418f2SJia Liu     op0 = extract32(insn, 21, 5);
1184bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
11856da544a6SRichard Henderson     I16 = sextract32(insn, 0, 16);
1186bbe418f2SJia Liu 
1187bbe418f2SJia Liu     switch (op0) {
1188bbe418f2SJia Liu     case 0x0:    /* l.sfeqi */
1189bbe418f2SJia Liu         LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
119084775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16);
1191bbe418f2SJia Liu         break;
1192bbe418f2SJia Liu 
1193bbe418f2SJia Liu     case 0x1:    /* l.sfnei */
1194bbe418f2SJia Liu         LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
119584775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16);
1196bbe418f2SJia Liu         break;
1197bbe418f2SJia Liu 
1198bbe418f2SJia Liu     case 0x2:    /* l.sfgtui */
1199bbe418f2SJia Liu         LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
120084775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16);
1201bbe418f2SJia Liu         break;
1202bbe418f2SJia Liu 
1203bbe418f2SJia Liu     case 0x3:    /* l.sfgeui */
1204bbe418f2SJia Liu         LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
120584775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16);
1206bbe418f2SJia Liu         break;
1207bbe418f2SJia Liu 
1208bbe418f2SJia Liu     case 0x4:    /* l.sfltui */
1209bbe418f2SJia Liu         LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
121084775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16);
1211bbe418f2SJia Liu         break;
1212bbe418f2SJia Liu 
1213bbe418f2SJia Liu     case 0x5:    /* l.sfleui */
1214bbe418f2SJia Liu         LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
121584775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16);
1216bbe418f2SJia Liu         break;
1217bbe418f2SJia Liu 
1218bbe418f2SJia Liu     case 0xa:    /* l.sfgtsi */
1219bbe418f2SJia Liu         LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
122084775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16);
1221bbe418f2SJia Liu         break;
1222bbe418f2SJia Liu 
1223bbe418f2SJia Liu     case 0xb:    /* l.sfgesi */
1224bbe418f2SJia Liu         LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
122584775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16);
1226bbe418f2SJia Liu         break;
1227bbe418f2SJia Liu 
1228bbe418f2SJia Liu     case 0xc:    /* l.sfltsi */
1229bbe418f2SJia Liu         LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
123084775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16);
1231bbe418f2SJia Liu         break;
1232bbe418f2SJia Liu 
1233bbe418f2SJia Liu     case 0xd:    /* l.sflesi */
1234bbe418f2SJia Liu         LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
123584775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16);
1236bbe418f2SJia Liu         break;
1237bbe418f2SJia Liu 
1238bbe418f2SJia Liu     default:
1239bbe418f2SJia Liu         gen_illegal_exception(dc);
1240bbe418f2SJia Liu         break;
1241bbe418f2SJia Liu     }
1242bbe418f2SJia Liu }
1243bbe418f2SJia Liu 
1244bbe418f2SJia Liu static void dec_sys(DisasContext *dc, uint32_t insn)
1245bbe418f2SJia Liu {
1246bbe418f2SJia Liu     uint32_t op0;
1247bbe418f2SJia Liu     uint32_t K16;
1248111ece51SRichard Henderson 
12493d59b680SDavid Morrison     op0 = extract32(insn, 16, 10);
1250bbe418f2SJia Liu     K16 = extract32(insn, 0, 16);
1251bbe418f2SJia Liu 
1252bbe418f2SJia Liu     switch (op0) {
1253bbe418f2SJia Liu     case 0x000:    /* l.sys */
1254bbe418f2SJia Liu         LOG_DIS("l.sys %d\n", K16);
12551ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1256bbe418f2SJia Liu         gen_exception(dc, EXCP_SYSCALL);
12571ffa4bceSEmilio G. Cota         dc->base.is_jmp = DISAS_NORETURN;
1258bbe418f2SJia Liu         break;
1259bbe418f2SJia Liu 
1260bbe418f2SJia Liu     case 0x100:    /* l.trap */
1261bbe418f2SJia Liu         LOG_DIS("l.trap %d\n", K16);
12621ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1263bbe418f2SJia Liu         gen_exception(dc, EXCP_TRAP);
12641ffa4bceSEmilio G. Cota         dc->base.is_jmp = DISAS_NORETURN;
1265bbe418f2SJia Liu         break;
1266bbe418f2SJia Liu 
1267bbe418f2SJia Liu     case 0x300:    /* l.csync */
1268bbe418f2SJia Liu         LOG_DIS("l.csync\n");
1269bbe418f2SJia Liu         break;
1270bbe418f2SJia Liu 
1271bbe418f2SJia Liu     case 0x200:    /* l.msync */
1272bbe418f2SJia Liu         LOG_DIS("l.msync\n");
127324fc5c0fSRichard Henderson         tcg_gen_mb(TCG_MO_ALL);
1274bbe418f2SJia Liu         break;
1275bbe418f2SJia Liu 
1276bbe418f2SJia Liu     case 0x270:    /* l.psync */
1277bbe418f2SJia Liu         LOG_DIS("l.psync\n");
1278bbe418f2SJia Liu         break;
1279bbe418f2SJia Liu 
1280bbe418f2SJia Liu     default:
1281bbe418f2SJia Liu         gen_illegal_exception(dc);
1282bbe418f2SJia Liu         break;
1283bbe418f2SJia Liu     }
1284bbe418f2SJia Liu }
1285bbe418f2SJia Liu 
1286bbe418f2SJia Liu static void dec_float(DisasContext *dc, uint32_t insn)
1287bbe418f2SJia Liu {
1288bbe418f2SJia Liu     uint32_t op0;
1289bbe418f2SJia Liu     uint32_t ra, rb, rd;
1290bbe418f2SJia Liu     op0 = extract32(insn, 0, 8);
1291bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1292bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1293bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1294bbe418f2SJia Liu 
1295bbe418f2SJia Liu     switch (op0) {
1296bbe418f2SJia Liu     case 0x00:    /* lf.add.s */
1297bbe418f2SJia Liu         LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
12986597c28dSRichard Henderson         check_r0_write(rd);
1299bbe418f2SJia Liu         gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1300bbe418f2SJia Liu         break;
1301bbe418f2SJia Liu 
1302bbe418f2SJia Liu     case 0x01:    /* lf.sub.s */
1303bbe418f2SJia Liu         LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
13046597c28dSRichard Henderson         check_r0_write(rd);
1305bbe418f2SJia Liu         gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1306bbe418f2SJia Liu         break;
1307bbe418f2SJia Liu 
1308bbe418f2SJia Liu     case 0x02:    /* lf.mul.s */
1309bbe418f2SJia Liu         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
13106597c28dSRichard Henderson         check_r0_write(rd);
1311bbe418f2SJia Liu         gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1312bbe418f2SJia Liu         break;
1313bbe418f2SJia Liu 
1314bbe418f2SJia Liu     case 0x03:    /* lf.div.s */
1315bbe418f2SJia Liu         LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
13166597c28dSRichard Henderson         check_r0_write(rd);
1317bbe418f2SJia Liu         gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1318bbe418f2SJia Liu         break;
1319bbe418f2SJia Liu 
1320bbe418f2SJia Liu     case 0x04:    /* lf.itof.s */
1321bbe418f2SJia Liu         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
13226597c28dSRichard Henderson         check_r0_write(rd);
1323bbe418f2SJia Liu         gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
1324bbe418f2SJia Liu         break;
1325bbe418f2SJia Liu 
1326bbe418f2SJia Liu     case 0x05:    /* lf.ftoi.s */
1327bbe418f2SJia Liu         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
13286597c28dSRichard Henderson         check_r0_write(rd);
1329bbe418f2SJia Liu         gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
1330bbe418f2SJia Liu         break;
1331bbe418f2SJia Liu 
1332bbe418f2SJia Liu     case 0x06:    /* lf.rem.s */
1333bbe418f2SJia Liu         LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
13346597c28dSRichard Henderson         check_r0_write(rd);
1335bbe418f2SJia Liu         gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1336bbe418f2SJia Liu         break;
1337bbe418f2SJia Liu 
1338bbe418f2SJia Liu     case 0x07:    /* lf.madd.s */
1339bbe418f2SJia Liu         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
13406597c28dSRichard Henderson         check_r0_write(rd);
1341762e22edSRichard Henderson         gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
1342762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
1343bbe418f2SJia Liu         break;
1344bbe418f2SJia Liu 
1345bbe418f2SJia Liu     case 0x08:    /* lf.sfeq.s */
1346bbe418f2SJia Liu         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
134784775c43SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1348bbe418f2SJia Liu         break;
1349bbe418f2SJia Liu 
1350bbe418f2SJia Liu     case 0x09:    /* lf.sfne.s */
1351bbe418f2SJia Liu         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
135284775c43SRichard Henderson         gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1353bbe418f2SJia Liu         break;
1354bbe418f2SJia Liu 
1355bbe418f2SJia Liu     case 0x0a:    /* lf.sfgt.s */
1356bbe418f2SJia Liu         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
135784775c43SRichard Henderson         gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1358bbe418f2SJia Liu         break;
1359bbe418f2SJia Liu 
1360bbe418f2SJia Liu     case 0x0b:    /* lf.sfge.s */
1361bbe418f2SJia Liu         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
136284775c43SRichard Henderson         gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1363bbe418f2SJia Liu         break;
1364bbe418f2SJia Liu 
1365bbe418f2SJia Liu     case 0x0c:    /* lf.sflt.s */
1366bbe418f2SJia Liu         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
136784775c43SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1368bbe418f2SJia Liu         break;
1369bbe418f2SJia Liu 
1370bbe418f2SJia Liu     case 0x0d:    /* lf.sfle.s */
1371bbe418f2SJia Liu         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
137284775c43SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1373bbe418f2SJia Liu         break;
1374bbe418f2SJia Liu 
1375bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
1376bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
1377bbe418f2SJia Liu     case 0x10:     lf.add.d
1378bbe418f2SJia Liu         LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
1379bbe418f2SJia Liu         check_of64s(dc);
13806597c28dSRichard Henderson         check_r0_write(rd);
1381bbe418f2SJia Liu         gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1382bbe418f2SJia Liu         break;
1383bbe418f2SJia Liu 
1384bbe418f2SJia Liu     case 0x11:     lf.sub.d
1385bbe418f2SJia Liu         LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
1386bbe418f2SJia Liu         check_of64s(dc);
13876597c28dSRichard Henderson         check_r0_write(rd);
1388bbe418f2SJia Liu         gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1389bbe418f2SJia Liu         break;
1390bbe418f2SJia Liu 
1391bbe418f2SJia Liu     case 0x12:     lf.mul.d
1392bbe418f2SJia Liu         LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
1393bbe418f2SJia Liu         check_of64s(dc);
13946597c28dSRichard Henderson         check_r0_write(rd);
1395bbe418f2SJia Liu         gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1396bbe418f2SJia Liu         break;
1397bbe418f2SJia Liu 
1398bbe418f2SJia Liu     case 0x13:     lf.div.d
1399bbe418f2SJia Liu         LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
1400bbe418f2SJia Liu         check_of64s(dc);
14016597c28dSRichard Henderson         check_r0_write(rd);
1402bbe418f2SJia Liu         gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1403bbe418f2SJia Liu         break;
1404bbe418f2SJia Liu 
1405bbe418f2SJia Liu     case 0x14:     lf.itof.d
1406bbe418f2SJia Liu         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
1407bbe418f2SJia Liu         check_of64s(dc);
14086597c28dSRichard Henderson         check_r0_write(rd);
1409bbe418f2SJia Liu         gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
1410bbe418f2SJia Liu         break;
1411bbe418f2SJia Liu 
1412bbe418f2SJia Liu     case 0x15:     lf.ftoi.d
1413bbe418f2SJia Liu         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
1414bbe418f2SJia Liu         check_of64s(dc);
14156597c28dSRichard Henderson         check_r0_write(rd);
1416bbe418f2SJia Liu         gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
1417bbe418f2SJia Liu         break;
1418bbe418f2SJia Liu 
1419bbe418f2SJia Liu     case 0x16:     lf.rem.d
1420bbe418f2SJia Liu         LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
1421bbe418f2SJia Liu         check_of64s(dc);
14226597c28dSRichard Henderson         check_r0_write(rd);
1423bbe418f2SJia Liu         gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1424bbe418f2SJia Liu         break;
1425bbe418f2SJia Liu 
1426bbe418f2SJia Liu     case 0x17:     lf.madd.d
1427bbe418f2SJia Liu         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
1428bbe418f2SJia Liu         check_of64s(dc);
14296597c28dSRichard Henderson         check_r0_write(rd);
1430762e22edSRichard Henderson         gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
1431762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
1432bbe418f2SJia Liu         break;
1433bbe418f2SJia Liu 
1434bbe418f2SJia Liu     case 0x18:     lf.sfeq.d
1435bbe418f2SJia Liu         LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
1436bbe418f2SJia Liu         check_of64s(dc);
143784775c43SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1438bbe418f2SJia Liu         break;
1439bbe418f2SJia Liu 
1440bbe418f2SJia Liu     case 0x1a:     lf.sfgt.d
1441bbe418f2SJia Liu         LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
1442bbe418f2SJia Liu         check_of64s(dc);
144384775c43SRichard Henderson         gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1444bbe418f2SJia Liu         break;
1445bbe418f2SJia Liu 
1446bbe418f2SJia Liu     case 0x1b:     lf.sfge.d
1447bbe418f2SJia Liu         LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
1448bbe418f2SJia Liu         check_of64s(dc);
144984775c43SRichard Henderson         gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1450bbe418f2SJia Liu         break;
1451bbe418f2SJia Liu 
1452bbe418f2SJia Liu     case 0x19:     lf.sfne.d
1453bbe418f2SJia Liu         LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
1454bbe418f2SJia Liu         check_of64s(dc);
145584775c43SRichard Henderson         gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1456bbe418f2SJia Liu         break;
1457bbe418f2SJia Liu 
1458bbe418f2SJia Liu     case 0x1c:     lf.sflt.d
1459bbe418f2SJia Liu         LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
1460bbe418f2SJia Liu         check_of64s(dc);
146184775c43SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1462bbe418f2SJia Liu         break;
1463bbe418f2SJia Liu 
1464bbe418f2SJia Liu     case 0x1d:     lf.sfle.d
1465bbe418f2SJia Liu         LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
1466bbe418f2SJia Liu         check_of64s(dc);
146784775c43SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1468bbe418f2SJia Liu         break;
1469bbe418f2SJia Liu #endif*/
1470bbe418f2SJia Liu 
1471bbe418f2SJia Liu     default:
1472bbe418f2SJia Liu         gen_illegal_exception(dc);
1473bbe418f2SJia Liu         break;
1474bbe418f2SJia Liu     }
1475bbe418f2SJia Liu }
1476bbe418f2SJia Liu 
1477bbe418f2SJia Liu static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
1478bbe418f2SJia Liu {
1479bbe418f2SJia Liu     uint32_t op0;
1480bbe418f2SJia Liu     uint32_t insn;
14811ffa4bceSEmilio G. Cota     insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1482bbe418f2SJia Liu     op0 = extract32(insn, 26, 6);
1483bbe418f2SJia Liu 
1484bbe418f2SJia Liu     switch (op0) {
1485bbe418f2SJia Liu     case 0x06:
1486bbe418f2SJia Liu         dec_M(dc, insn);
1487bbe418f2SJia Liu         break;
1488bbe418f2SJia Liu 
1489bbe418f2SJia Liu     case 0x08:
1490bbe418f2SJia Liu         dec_sys(dc, insn);
1491bbe418f2SJia Liu         break;
1492bbe418f2SJia Liu 
1493bbe418f2SJia Liu     case 0x2e:
1494bbe418f2SJia Liu         dec_logic(dc, insn);
1495bbe418f2SJia Liu         break;
1496bbe418f2SJia Liu 
1497bbe418f2SJia Liu     case 0x2f:
1498bbe418f2SJia Liu         dec_compi(dc, insn);
1499bbe418f2SJia Liu         break;
1500bbe418f2SJia Liu 
1501bbe418f2SJia Liu     case 0x31:
1502bbe418f2SJia Liu         dec_mac(dc, insn);
1503bbe418f2SJia Liu         break;
1504bbe418f2SJia Liu 
1505bbe418f2SJia Liu     case 0x32:
1506bbe418f2SJia Liu         dec_float(dc, insn);
1507bbe418f2SJia Liu         break;
1508bbe418f2SJia Liu 
1509bbe418f2SJia Liu     case 0x38:
1510bbe418f2SJia Liu         dec_calc(dc, insn);
1511bbe418f2SJia Liu         break;
1512bbe418f2SJia Liu 
1513bbe418f2SJia Liu     case 0x39:
1514bbe418f2SJia Liu         dec_comp(dc, insn);
1515bbe418f2SJia Liu         break;
1516bbe418f2SJia Liu 
1517bbe418f2SJia Liu     default:
1518bbe418f2SJia Liu         dec_misc(dc, insn);
1519bbe418f2SJia Liu         break;
1520bbe418f2SJia Liu     }
1521bbe418f2SJia Liu }
1522bbe418f2SJia Liu 
1523*a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1524e67db06eSJia Liu {
1525*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
15269c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1527*a4fd3ec3SEmilio G. Cota     int bound;
1528bbe418f2SJia Liu 
1529*a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
15301ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1531a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1532*a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1533*a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1534190ce7fbSRichard Henderson }
1535bbe418f2SJia Liu 
1536*a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1537*a4fd3ec3SEmilio G. Cota {
1538*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1539bbe418f2SJia Liu 
15406597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15416597c28dSRichard Henderson        when it's true, which is the common case.  */
15426597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
15436597c28dSRichard Henderson         cpu_R[0] = tcg_const_tl(0);
15446597c28dSRichard Henderson     } else {
15456597c28dSRichard Henderson         cpu_R[0] = cpu_R0;
15466597c28dSRichard Henderson     }
1547*a4fd3ec3SEmilio G. Cota }
15486597c28dSRichard Henderson 
1549*a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1550*a4fd3ec3SEmilio G. Cota {
1551*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1552*a4fd3ec3SEmilio G. Cota 
15531ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1554*a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1555*a4fd3ec3SEmilio G. Cota }
1556bbe418f2SJia Liu 
1557*a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1558*a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1559*a4fd3ec3SEmilio G. Cota {
1560*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1561*a4fd3ec3SEmilio G. Cota 
15621ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1563b933066aSRichard Henderson     gen_exception(dc, EXCP_DEBUG);
15641ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1565522a0d4eSRichard Henderson     /* The address covered by the breakpoint must be included in
1566522a0d4eSRichard Henderson        [tb->pc, tb->pc + tb->size) in order to for it to be
1567522a0d4eSRichard Henderson        properly cleared -- thus we increment the PC here so that
1568522a0d4eSRichard Henderson        the logic setting tb->size below does the right thing.  */
15691ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1570*a4fd3ec3SEmilio G. Cota     return true;
1571b933066aSRichard Henderson }
1572b933066aSRichard Henderson 
1573*a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1574*a4fd3ec3SEmilio G. Cota {
1575*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1576*a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1577*a4fd3ec3SEmilio G. Cota 
1578bbe418f2SJia Liu     disas_openrisc_insn(dc, cpu);
15791ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
158024c32852SRichard Henderson 
1581bbe418f2SJia Liu     /* delay slot */
1582bbe418f2SJia Liu     if (dc->delayed_branch) {
1583bbe418f2SJia Liu         dc->delayed_branch--;
1584bbe418f2SJia Liu         if (!dc->delayed_branch) {
1585bbe418f2SJia Liu             tcg_gen_mov_tl(cpu_pc, jmp_pc);
158624c32852SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
15871ffa4bceSEmilio G. Cota             dc->base.is_jmp = DISAS_UPDATE;
1588*a4fd3ec3SEmilio G. Cota             return;
1589bbe418f2SJia Liu         }
1590bbe418f2SJia Liu     }
1591*a4fd3ec3SEmilio G. Cota }
1592bbe418f2SJia Liu 
1593*a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1594*a4fd3ec3SEmilio G. Cota {
1595*a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
159624c32852SRichard Henderson 
1597a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1598a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1599a01deb36SRichard Henderson     }
1600a01deb36SRichard Henderson 
16011ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
16021ffa4bceSEmilio G. Cota     if (dc->base.is_jmp == DISAS_NEXT) {
16031ffa4bceSEmilio G. Cota         dc->base.is_jmp = DISAS_UPDATE;
16041ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1605bbe418f2SJia Liu     }
16061ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
1607bbe418f2SJia Liu         gen_exception(dc, EXCP_DEBUG);
1608bbe418f2SJia Liu     } else {
16091ffa4bceSEmilio G. Cota         switch (dc->base.is_jmp) {
1610*a4fd3ec3SEmilio G. Cota         case DISAS_TOO_MANY:
16111ffa4bceSEmilio G. Cota             gen_goto_tb(dc, 0, dc->base.pc_next);
1612bbe418f2SJia Liu             break;
16131ffa4bceSEmilio G. Cota         case DISAS_NORETURN:
1614bbe418f2SJia Liu         case DISAS_JUMP:
16151ffa4bceSEmilio G. Cota         case DISAS_TB_JUMP:
1616bbe418f2SJia Liu             break;
1617bbe418f2SJia Liu         case DISAS_UPDATE:
1618bbe418f2SJia Liu             /* indicate that the hash table must be used
1619bbe418f2SJia Liu                to find the next TB */
1620bbe418f2SJia Liu             tcg_gen_exit_tb(0);
1621bbe418f2SJia Liu             break;
1622*a4fd3ec3SEmilio G. Cota         default:
1623*a4fd3ec3SEmilio G. Cota             g_assert_not_reached();
1624*a4fd3ec3SEmilio G. Cota         }
1625bbe418f2SJia Liu     }
1626bbe418f2SJia Liu }
1627bbe418f2SJia Liu 
1628*a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1629*a4fd3ec3SEmilio G. Cota {
1630*a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
16310a7df5daSRichard Henderson 
1632*a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1633*a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1634bbe418f2SJia Liu }
1635*a4fd3ec3SEmilio G. Cota 
1636*a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1637*a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1638*a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1639*a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1640*a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1641*a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1642*a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1643*a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1644*a4fd3ec3SEmilio G. Cota };
1645*a4fd3ec3SEmilio G. Cota 
1646*a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
1647*a4fd3ec3SEmilio G. Cota {
1648*a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1649*a4fd3ec3SEmilio G. Cota 
1650*a4fd3ec3SEmilio G. Cota     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb);
1651e67db06eSJia Liu }
1652e67db06eSJia Liu 
1653878096eeSAndreas Färber void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
1654e67db06eSJia Liu                              fprintf_function cpu_fprintf,
1655e67db06eSJia Liu                              int flags)
1656e67db06eSJia Liu {
1657878096eeSAndreas Färber     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1658878096eeSAndreas Färber     CPUOpenRISCState *env = &cpu->env;
1659e67db06eSJia Liu     int i;
1660878096eeSAndreas Färber 
1661e67db06eSJia Liu     cpu_fprintf(f, "PC=%08x\n", env->pc);
1662e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
1663d89e71e8SStafford Horne         cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1664e67db06eSJia Liu                     (i % 4) == 3 ? '\n' : ' ');
1665e67db06eSJia Liu     }
1666e67db06eSJia Liu }
1667e67db06eSJia Liu 
1668e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1669bad729e2SRichard Henderson                           target_ulong *data)
1670e67db06eSJia Liu {
1671bad729e2SRichard Henderson     env->pc = data[0];
1672a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1673a01deb36SRichard Henderson     if (data[1] & 2) {
167424c32852SRichard Henderson         env->ppc = env->pc - 4;
167524c32852SRichard Henderson     }
1676e67db06eSJia Liu }
1677