xref: /qemu/target/openrisc/translate.c (revision 6597c28d618a3d16d468770b7c30a0237a8c8ea9)
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"
30bbe418f2SJia Liu 
312ef6175aSRichard Henderson #include "exec/helper-proto.h"
322ef6175aSRichard Henderson #include "exec/helper-gen.h"
33e67db06eSJia Liu 
34a7e30d84SLluís Vilanova #include "trace-tcg.h"
35508127e2SPaolo Bonzini #include "exec/log.h"
36a7e30d84SLluís Vilanova 
37111ece51SRichard Henderson #define LOG_DIS(str, ...) \
38111ece51SRichard Henderson     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->pc, ## __VA_ARGS__)
39e67db06eSJia Liu 
40bbe418f2SJia Liu typedef struct DisasContext {
41bbe418f2SJia Liu     TranslationBlock *tb;
4224c32852SRichard Henderson     target_ulong pc;
43bbe418f2SJia Liu     uint32_t is_jmp;
44bbe418f2SJia Liu     uint32_t mem_idx;
45a01deb36SRichard Henderson     uint32_t tb_flags;
46bbe418f2SJia Liu     uint32_t delayed_branch;
47a01deb36SRichard Henderson     bool singlestep_enabled;
48bbe418f2SJia Liu } DisasContext;
49bbe418f2SJia Liu 
501bcea73eSLluís Vilanova static TCGv_env cpu_env;
51bbe418f2SJia Liu static TCGv cpu_sr;
52bbe418f2SJia Liu static TCGv cpu_R[32];
53*6597c28dSRichard Henderson static TCGv cpu_R0;
54bbe418f2SJia Liu static TCGv cpu_pc;
55bbe418f2SJia Liu static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
56bbe418f2SJia Liu static TCGv cpu_ppc;
5784775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
5897458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
5997458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
60930c3d00SRichard Henderson static TCGv cpu_lock_addr;
61930c3d00SRichard Henderson static TCGv cpu_lock_value;
62bbe418f2SJia Liu static TCGv_i32 fpcsr;
636f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
64a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
65022c62cbSPaolo Bonzini #include "exec/gen-icount.h"
66bbe418f2SJia Liu 
67e67db06eSJia Liu void openrisc_translate_init(void)
68e67db06eSJia Liu {
69bbe418f2SJia Liu     static const char * const regnames[] = {
70bbe418f2SJia Liu         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
71bbe418f2SJia Liu         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
72bbe418f2SJia Liu         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
73bbe418f2SJia Liu         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
74bbe418f2SJia Liu     };
75bbe418f2SJia Liu     int i;
76bbe418f2SJia Liu 
77bbe418f2SJia Liu     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
787c255043SLluís Vilanova     tcg_ctx.tcg_env = cpu_env;
79e1ccc054SRichard Henderson     cpu_sr = tcg_global_mem_new(cpu_env,
80bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, sr), "sr");
81a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
82a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
83a01deb36SRichard Henderson                                        "dflag");
84e1ccc054SRichard Henderson     cpu_pc = tcg_global_mem_new(cpu_env,
85bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, pc), "pc");
86e1ccc054SRichard Henderson     cpu_ppc = tcg_global_mem_new(cpu_env,
87bbe418f2SJia Liu                                  offsetof(CPUOpenRISCState, ppc), "ppc");
88e1ccc054SRichard Henderson     jmp_pc = tcg_global_mem_new(cpu_env,
89bbe418f2SJia Liu                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
9084775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
9184775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
9297458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
9397458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
9497458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
9597458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
96930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
97930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
98930c3d00SRichard Henderson                                        "lock_addr");
99930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
100930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
101930c3d00SRichard Henderson                                         "lock_value");
102e1ccc054SRichard Henderson     fpcsr = tcg_global_mem_new_i32(cpu_env,
103bbe418f2SJia Liu                                    offsetof(CPUOpenRISCState, fpcsr),
104bbe418f2SJia Liu                                    "fpcsr");
1056f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1066f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1076f7332baSRichard Henderson                                      "mac");
108bbe418f2SJia Liu     for (i = 0; i < 32; i++) {
109e1ccc054SRichard Henderson         cpu_R[i] = tcg_global_mem_new(cpu_env,
110bbe418f2SJia Liu                                       offsetof(CPUOpenRISCState, gpr[i]),
111bbe418f2SJia Liu                                       regnames[i]);
112bbe418f2SJia Liu     }
113*6597c28dSRichard Henderson     cpu_R0 = cpu_R[0];
114bbe418f2SJia Liu }
115bbe418f2SJia Liu 
116bbe418f2SJia Liu static void gen_exception(DisasContext *dc, unsigned int excp)
117bbe418f2SJia Liu {
118bbe418f2SJia Liu     TCGv_i32 tmp = tcg_const_i32(excp);
119bbe418f2SJia Liu     gen_helper_exception(cpu_env, tmp);
120bbe418f2SJia Liu     tcg_temp_free_i32(tmp);
121bbe418f2SJia Liu }
122bbe418f2SJia Liu 
123bbe418f2SJia Liu static void gen_illegal_exception(DisasContext *dc)
124bbe418f2SJia Liu {
125bbe418f2SJia Liu     tcg_gen_movi_tl(cpu_pc, dc->pc);
126bbe418f2SJia Liu     gen_exception(dc, EXCP_ILLEGAL);
127bbe418f2SJia Liu     dc->is_jmp = DISAS_UPDATE;
128bbe418f2SJia Liu }
129bbe418f2SJia Liu 
130bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
131bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
132bbe418f2SJia Liu static void check_ob64s(DisasContext *dc)
133bbe418f2SJia Liu {
134bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OB64S)) {
135bbe418f2SJia Liu         gen_illegal_exception(dc);
136bbe418f2SJia Liu     }
137bbe418f2SJia Liu }
138bbe418f2SJia Liu 
139bbe418f2SJia Liu static void check_of64s(DisasContext *dc)
140bbe418f2SJia Liu {
141bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OF64S)) {
142bbe418f2SJia Liu         gen_illegal_exception(dc);
143bbe418f2SJia Liu     }
144bbe418f2SJia Liu }
145bbe418f2SJia Liu 
146bbe418f2SJia Liu static void check_ov64s(DisasContext *dc)
147bbe418f2SJia Liu {
148bbe418f2SJia Liu     if (!(dc->flags & CPUCFGR_OV64S)) {
149bbe418f2SJia Liu         gen_illegal_exception(dc);
150bbe418f2SJia Liu     }
151bbe418f2SJia Liu }
152bbe418f2SJia Liu #endif*/
153bbe418f2SJia Liu 
154*6597c28dSRichard Henderson /* We're about to write to REG.  On the off-chance that the user is
155*6597c28dSRichard Henderson    writing to R0, re-instate the architectural register.  */
156*6597c28dSRichard Henderson #define check_r0_write(reg)             \
157*6597c28dSRichard Henderson     do {                                \
158*6597c28dSRichard Henderson         if (unlikely(reg == 0)) {       \
159*6597c28dSRichard Henderson             cpu_R[0] = cpu_R0;          \
160*6597c28dSRichard Henderson         }                               \
161*6597c28dSRichard Henderson     } while (0)
162*6597c28dSRichard Henderson 
16390aa39a1SSergey Fedorov static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
16490aa39a1SSergey Fedorov {
16590aa39a1SSergey Fedorov     if (unlikely(dc->singlestep_enabled)) {
16690aa39a1SSergey Fedorov         return false;
16790aa39a1SSergey Fedorov     }
16890aa39a1SSergey Fedorov 
16990aa39a1SSergey Fedorov #ifndef CONFIG_USER_ONLY
17090aa39a1SSergey Fedorov     return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
17190aa39a1SSergey Fedorov #else
17290aa39a1SSergey Fedorov     return true;
17390aa39a1SSergey Fedorov #endif
17490aa39a1SSergey Fedorov }
17590aa39a1SSergey Fedorov 
176bbe418f2SJia Liu static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
177bbe418f2SJia Liu {
17890aa39a1SSergey Fedorov     if (use_goto_tb(dc, dest)) {
179bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dest);
180bbe418f2SJia Liu         tcg_gen_goto_tb(n);
18190aa39a1SSergey Fedorov         tcg_gen_exit_tb((uintptr_t)dc->tb + n);
182bbe418f2SJia Liu     } else {
183bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dest);
184bbe418f2SJia Liu         if (dc->singlestep_enabled) {
185bbe418f2SJia Liu             gen_exception(dc, EXCP_DEBUG);
186bbe418f2SJia Liu         }
187bbe418f2SJia Liu         tcg_gen_exit_tb(0);
188bbe418f2SJia Liu     }
189bbe418f2SJia Liu }
190bbe418f2SJia Liu 
1916da544a6SRichard Henderson static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
192bbe418f2SJia Liu {
1936da544a6SRichard Henderson     target_ulong tmp_pc = dc->pc + n26 * 4;
194bbe418f2SJia Liu 
195da1d7759SSebastian Macke     switch (op0) {
196da1d7759SSebastian Macke     case 0x00:     /* l.j */
197bbe418f2SJia Liu         tcg_gen_movi_tl(jmp_pc, tmp_pc);
198da1d7759SSebastian Macke         break;
199da1d7759SSebastian Macke     case 0x01:     /* l.jal */
200a8000cb4SRichard Henderson         tcg_gen_movi_tl(cpu_R[9], dc->pc + 8);
201a8000cb4SRichard Henderson         /* Optimize jal being used to load the PC for PIC.  */
202a8000cb4SRichard Henderson         if (tmp_pc == dc->pc + 8) {
203a8000cb4SRichard Henderson             return;
204a8000cb4SRichard Henderson         }
205bbe418f2SJia Liu         tcg_gen_movi_tl(jmp_pc, tmp_pc);
206da1d7759SSebastian Macke         break;
207da1d7759SSebastian Macke     case 0x03:     /* l.bnf */
208da1d7759SSebastian Macke     case 0x04:     /* l.bf  */
209da1d7759SSebastian Macke         {
210784696d1SRichard Henderson             TCGv t_next = tcg_const_tl(dc->pc + 8);
211784696d1SRichard Henderson             TCGv t_true = tcg_const_tl(tmp_pc);
212784696d1SRichard Henderson             TCGv t_zero = tcg_const_tl(0);
213784696d1SRichard Henderson 
214784696d1SRichard Henderson             tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
215784696d1SRichard Henderson                                jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
216784696d1SRichard Henderson 
217784696d1SRichard Henderson             tcg_temp_free(t_next);
218784696d1SRichard Henderson             tcg_temp_free(t_true);
219784696d1SRichard Henderson             tcg_temp_free(t_zero);
220da1d7759SSebastian Macke         }
221da1d7759SSebastian Macke         break;
222da1d7759SSebastian Macke     case 0x11:     /* l.jr */
223bbe418f2SJia Liu         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
224da1d7759SSebastian Macke         break;
225da1d7759SSebastian Macke     case 0x12:     /* l.jalr */
226bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
227bbe418f2SJia Liu         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
228da1d7759SSebastian Macke         break;
229da1d7759SSebastian Macke     default:
230bbe418f2SJia Liu         gen_illegal_exception(dc);
231da1d7759SSebastian Macke         break;
232bbe418f2SJia Liu     }
233bbe418f2SJia Liu 
234bbe418f2SJia Liu     dc->delayed_branch = 2;
235bbe418f2SJia Liu }
236bbe418f2SJia Liu 
23797458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
2389ecaa27eSRichard Henderson {
2390c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
24097458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
2419ecaa27eSRichard Henderson     }
2420c53d734SRichard Henderson }
2439ecaa27eSRichard Henderson 
24497458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
2459ecaa27eSRichard Henderson {
2460c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
24797458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
2489ecaa27eSRichard Henderson     }
2490c53d734SRichard Henderson }
2509ecaa27eSRichard Henderson 
25197458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
2529ecaa27eSRichard Henderson {
2530c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
25497458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
2559ecaa27eSRichard Henderson     }
2560c53d734SRichard Henderson }
2579ecaa27eSRichard Henderson 
2589ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2599ecaa27eSRichard Henderson {
2609ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2619ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2629ecaa27eSRichard Henderson 
26397458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
26497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2659ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
26697458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2679ecaa27eSRichard Henderson     tcg_temp_free(t0);
2689ecaa27eSRichard Henderson 
2699ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2709ecaa27eSRichard Henderson     tcg_temp_free(res);
2719ecaa27eSRichard Henderson 
27297458071SRichard Henderson     gen_ove_cyov(dc);
2739ecaa27eSRichard Henderson }
2749ecaa27eSRichard Henderson 
2759ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2769ecaa27eSRichard Henderson {
2779ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2789ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2799ecaa27eSRichard Henderson 
28097458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
28197458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
28297458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2839ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
28497458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2859ecaa27eSRichard Henderson     tcg_temp_free(t0);
2869ecaa27eSRichard Henderson 
2879ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2889ecaa27eSRichard Henderson     tcg_temp_free(res);
2899ecaa27eSRichard Henderson 
29097458071SRichard Henderson     gen_ove_cyov(dc);
2919ecaa27eSRichard Henderson }
2929ecaa27eSRichard Henderson 
2939ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2949ecaa27eSRichard Henderson {
2959ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2969ecaa27eSRichard Henderson 
2979ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
29897458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
29997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
30097458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
30197458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
3029ecaa27eSRichard Henderson 
3039ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
3049ecaa27eSRichard Henderson     tcg_temp_free(res);
3059ecaa27eSRichard Henderson 
30697458071SRichard Henderson     gen_ove_cyov(dc);
3079ecaa27eSRichard Henderson }
3089ecaa27eSRichard Henderson 
3099ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3109ecaa27eSRichard Henderson {
3119ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3129ecaa27eSRichard Henderson 
31397458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
3149ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
31597458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
3169ecaa27eSRichard Henderson     tcg_temp_free(t0);
3179ecaa27eSRichard Henderson 
31897458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
31997458071SRichard Henderson     gen_ove_ov(dc);
3209ecaa27eSRichard Henderson }
3219ecaa27eSRichard Henderson 
3229ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3239ecaa27eSRichard Henderson {
32497458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
32597458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
3269ecaa27eSRichard Henderson 
32797458071SRichard Henderson     gen_ove_cy(dc);
3289ecaa27eSRichard Henderson }
3299ecaa27eSRichard Henderson 
3309ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3319ecaa27eSRichard Henderson {
3329ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3339ecaa27eSRichard Henderson 
33497458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
3359ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3369ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
33797458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
3389ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
3399ecaa27eSRichard Henderson     tcg_temp_free(t0);
3409ecaa27eSRichard Henderson 
34197458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
34297458071SRichard Henderson     gen_ove_ov(dc);
3439ecaa27eSRichard Henderson }
3449ecaa27eSRichard Henderson 
3459ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3469ecaa27eSRichard Henderson {
3479ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3489ecaa27eSRichard Henderson 
34997458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
3509ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3519ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
35297458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
3539ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
3549ecaa27eSRichard Henderson     tcg_temp_free(t0);
3559ecaa27eSRichard Henderson 
35697458071SRichard Henderson     gen_ove_cy(dc);
3579ecaa27eSRichard Henderson }
358da1d7759SSebastian Macke 
359cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
360cc5de49eSRichard Henderson {
361cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
362cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
363cc5de49eSRichard Henderson 
364cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
365cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
366cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
367cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
368cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
369cc5de49eSRichard Henderson     } else {
370cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
371cc5de49eSRichard Henderson 
372cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
373cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
374cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
375cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
376cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
377cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
378cc5de49eSRichard Henderson 
379cc5de49eSRichard Henderson         gen_ove_ov(dc);
380cc5de49eSRichard Henderson     }
381cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
382cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
383cc5de49eSRichard Henderson }
384cc5de49eSRichard Henderson 
385cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
386cc5de49eSRichard Henderson {
387cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
388cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
389cc5de49eSRichard Henderson 
390cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
391cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
392cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
393cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
394cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
395cc5de49eSRichard Henderson     } else {
396cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
397cc5de49eSRichard Henderson 
398cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
399cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
400cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
401cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
402cc5de49eSRichard Henderson 
403cc5de49eSRichard Henderson         gen_ove_cy(dc);
404cc5de49eSRichard Henderson     }
405cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
406cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
407cc5de49eSRichard Henderson }
408cc5de49eSRichard Henderson 
4096f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
4106f7332baSRichard Henderson {
4116f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4126f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4136f7332baSRichard Henderson 
4146f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4156f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4166f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4176f7332baSRichard Henderson 
4186f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
4196f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4206f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
4216f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4226f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
4236f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4246f7332baSRichard Henderson 
4256f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4266f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4276f7332baSRichard Henderson #else
4286f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4296f7332baSRichard Henderson #endif
4306f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4316f7332baSRichard Henderson 
4326f7332baSRichard Henderson     gen_ove_ov(dc);
4336f7332baSRichard Henderson }
4346f7332baSRichard Henderson 
435cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
436cc5de49eSRichard Henderson {
437cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
438cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
439cc5de49eSRichard Henderson 
440cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
441cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
442cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
443cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
444cc5de49eSRichard Henderson 
445cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
446cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
447cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
448cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
449cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
450cc5de49eSRichard Henderson 
451cc5de49eSRichard Henderson     gen_ove_cy(dc);
452cc5de49eSRichard Henderson }
453cc5de49eSRichard Henderson 
4546f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
4556f7332baSRichard Henderson {
4566f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4576f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4586f7332baSRichard Henderson 
4596f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4606f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4616f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4626f7332baSRichard Henderson 
4636f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4646f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4656f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4666f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4676f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4686f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4696f7332baSRichard Henderson 
4706f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4716f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4726f7332baSRichard Henderson #else
4736f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4746f7332baSRichard Henderson #endif
4756f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4766f7332baSRichard Henderson 
4776f7332baSRichard Henderson     gen_ove_ov(dc);
4786f7332baSRichard Henderson }
4796f7332baSRichard Henderson 
480cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
481cc5de49eSRichard Henderson {
482cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
483cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
484cc5de49eSRichard Henderson 
485cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
486cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
487cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
488cc5de49eSRichard Henderson 
489cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
490cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
491cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
492cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
493cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
494cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
495cc5de49eSRichard Henderson 
496cc5de49eSRichard Henderson     gen_ove_cy(dc);
497cc5de49eSRichard Henderson }
498cc5de49eSRichard Henderson 
499930c3d00SRichard Henderson static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
500930c3d00SRichard Henderson {
501930c3d00SRichard Henderson     TCGv ea = tcg_temp_new();
502930c3d00SRichard Henderson 
503930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
504930c3d00SRichard Henderson     tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
505930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
506930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, rd);
507930c3d00SRichard Henderson     tcg_temp_free(ea);
508930c3d00SRichard Henderson }
509930c3d00SRichard Henderson 
510*6597c28dSRichard Henderson static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs)
511930c3d00SRichard Henderson {
512930c3d00SRichard Henderson     TCGv ea, val;
513930c3d00SRichard Henderson     TCGLabel *lab_fail, *lab_done;
514930c3d00SRichard Henderson 
515930c3d00SRichard Henderson     ea = tcg_temp_new();
516930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
517930c3d00SRichard Henderson 
518*6597c28dSRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
519*6597c28dSRichard Henderson        to cpu_R[0].  Since l.swa is quite often immediately followed by a
520*6597c28dSRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
521*6597c28dSRichard Henderson        This also takes care of RB input across the branch.  */
522*6597c28dSRichard Henderson     cpu_R[0] = cpu_R0;
523*6597c28dSRichard Henderson 
524930c3d00SRichard Henderson     lab_fail = gen_new_label();
525930c3d00SRichard Henderson     lab_done = gen_new_label();
526930c3d00SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
527930c3d00SRichard Henderson     tcg_temp_free(ea);
528930c3d00SRichard Henderson 
529930c3d00SRichard Henderson     val = tcg_temp_new();
530930c3d00SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
531*6597c28dSRichard Henderson                               cpu_R[b], dc->mem_idx, MO_TEUL);
53284775c43SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
533930c3d00SRichard Henderson     tcg_temp_free(val);
534930c3d00SRichard Henderson 
535930c3d00SRichard Henderson     tcg_gen_br(lab_done);
536930c3d00SRichard Henderson 
537930c3d00SRichard Henderson     gen_set_label(lab_fail);
53884775c43SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
539930c3d00SRichard Henderson 
540930c3d00SRichard Henderson     gen_set_label(lab_done);
541930c3d00SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
542930c3d00SRichard Henderson }
543930c3d00SRichard Henderson 
544bbe418f2SJia Liu static void dec_calc(DisasContext *dc, uint32_t insn)
545bbe418f2SJia Liu {
546bbe418f2SJia Liu     uint32_t op0, op1, op2;
547bbe418f2SJia Liu     uint32_t ra, rb, rd;
548bbe418f2SJia Liu     op0 = extract32(insn, 0, 4);
549bbe418f2SJia Liu     op1 = extract32(insn, 8, 2);
550bbe418f2SJia Liu     op2 = extract32(insn, 6, 2);
551bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
552bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
553bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
554bbe418f2SJia Liu 
555bbe418f2SJia Liu     switch (op1) {
556cf2ae442SRichard Henderson     case 0:
557cf2ae442SRichard Henderson         switch (op0) {
558cf2ae442SRichard Henderson         case 0x0: /* l.add */
559bbe418f2SJia Liu             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
5609ecaa27eSRichard Henderson             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
561cf2ae442SRichard Henderson             return;
562bbe418f2SJia Liu 
563cf2ae442SRichard Henderson         case 0x1: /* l.addc */
564bbe418f2SJia Liu             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
5659ecaa27eSRichard Henderson             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
566cf2ae442SRichard Henderson             return;
567bbe418f2SJia Liu 
568cf2ae442SRichard Henderson         case 0x2: /* l.sub */
569bbe418f2SJia Liu             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
5709ecaa27eSRichard Henderson             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
571cf2ae442SRichard Henderson             return;
572bbe418f2SJia Liu 
573cf2ae442SRichard Henderson         case 0x3: /* l.and */
574bbe418f2SJia Liu             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
575bbe418f2SJia Liu             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
576cf2ae442SRichard Henderson             return;
577bbe418f2SJia Liu 
578cf2ae442SRichard Henderson         case 0x4: /* l.or */
579bbe418f2SJia Liu             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
580bbe418f2SJia Liu             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
581cf2ae442SRichard Henderson             return;
582bbe418f2SJia Liu 
583cf2ae442SRichard Henderson         case 0x5: /* l.xor */
584bbe418f2SJia Liu             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
585bbe418f2SJia Liu             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
586cf2ae442SRichard Henderson             return;
587cf2ae442SRichard Henderson 
588cf2ae442SRichard Henderson         case 0x8:
589cf2ae442SRichard Henderson             switch (op2) {
590cf2ae442SRichard Henderson             case 0: /* l.sll */
591cf2ae442SRichard Henderson                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
592cf2ae442SRichard Henderson                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
593cf2ae442SRichard Henderson                 return;
594cf2ae442SRichard Henderson             case 1: /* l.srl */
595cf2ae442SRichard Henderson                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
596cf2ae442SRichard Henderson                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
597cf2ae442SRichard Henderson                 return;
598cf2ae442SRichard Henderson             case 2: /* l.sra */
599cf2ae442SRichard Henderson                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
600cf2ae442SRichard Henderson                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
601cf2ae442SRichard Henderson                 return;
602cf2ae442SRichard Henderson             case 3: /* l.ror */
603cf2ae442SRichard Henderson                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
604cf2ae442SRichard Henderson                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
605cf2ae442SRichard Henderson                 return;
606bbe418f2SJia Liu             }
607bbe418f2SJia Liu             break;
608bbe418f2SJia Liu 
609cf2ae442SRichard Henderson         case 0xc:
610cf2ae442SRichard Henderson             switch (op2) {
611cf2ae442SRichard Henderson             case 0: /* l.exths */
612cf2ae442SRichard Henderson                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
613cf2ae442SRichard Henderson                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
614cf2ae442SRichard Henderson                 return;
615cf2ae442SRichard Henderson             case 1: /* l.extbs */
616cf2ae442SRichard Henderson                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
617cf2ae442SRichard Henderson                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
618cf2ae442SRichard Henderson                 return;
619cf2ae442SRichard Henderson             case 2: /* l.exthz */
620cf2ae442SRichard Henderson                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
621cf2ae442SRichard Henderson                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
622cf2ae442SRichard Henderson                 return;
623cf2ae442SRichard Henderson             case 3: /* l.extbz */
624cf2ae442SRichard Henderson                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
625cf2ae442SRichard Henderson                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
626cf2ae442SRichard Henderson                 return;
627bbe418f2SJia Liu             }
628bbe418f2SJia Liu             break;
629bbe418f2SJia Liu 
630cf2ae442SRichard Henderson         case 0xd:
631cf2ae442SRichard Henderson             switch (op2) {
632cf2ae442SRichard Henderson             case 0: /* l.extws */
633cf2ae442SRichard Henderson                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
634cf2ae442SRichard Henderson                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
635cf2ae442SRichard Henderson                 return;
636cf2ae442SRichard Henderson             case 1: /* l.extwz */
637cf2ae442SRichard Henderson                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
638cf2ae442SRichard Henderson                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
639cf2ae442SRichard Henderson                 return;
640bbe418f2SJia Liu             }
641bbe418f2SJia Liu             break;
642bbe418f2SJia Liu 
643cf2ae442SRichard Henderson         case 0xe: /* l.cmov */
644bbe418f2SJia Liu             LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
645bbe418f2SJia Liu             {
646784696d1SRichard Henderson                 TCGv zero = tcg_const_tl(0);
647784696d1SRichard Henderson                 tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero,
648784696d1SRichard Henderson                                    cpu_R[ra], cpu_R[rb]);
649784696d1SRichard Henderson                 tcg_temp_free(zero);
650bbe418f2SJia Liu             }
651cf2ae442SRichard Henderson             return;
652bbe418f2SJia Liu 
653cf2ae442SRichard Henderson         case 0xf: /* l.ff1 */
654bbe418f2SJia Liu             LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
655555baef8SRichard Henderson             tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1);
656555baef8SRichard Henderson             tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1);
657cf2ae442SRichard Henderson             return;
658cf2ae442SRichard Henderson         }
659bbe418f2SJia Liu         break;
660cf2ae442SRichard Henderson 
661cf2ae442SRichard Henderson     case 1:
662cf2ae442SRichard Henderson         switch (op0) {
663cf2ae442SRichard Henderson         case 0xf: /* l.fl1 */
664bbe418f2SJia Liu             LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
665555baef8SRichard Henderson             tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS);
666555baef8SRichard Henderson             tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]);
667cf2ae442SRichard Henderson             return;
668bbe418f2SJia Liu         }
669bbe418f2SJia Liu         break;
670bbe418f2SJia Liu 
671cf2ae442SRichard Henderson     case 2:
672bbe418f2SJia Liu         break;
673bbe418f2SJia Liu 
674cf2ae442SRichard Henderson     case 3:
675cf2ae442SRichard Henderson         switch (op0) {
676cf2ae442SRichard Henderson         case 0x6: /* l.mul */
677cf2ae442SRichard Henderson             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
678cf2ae442SRichard Henderson             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
679cf2ae442SRichard Henderson             return;
680cf2ae442SRichard Henderson 
681cc5de49eSRichard Henderson         case 0x7: /* l.muld */
682cc5de49eSRichard Henderson             LOG_DIS("l.muld r%d, r%d\n", ra, rb);
683cc5de49eSRichard Henderson             gen_muld(dc, cpu_R[ra], cpu_R[rb]);
684cc5de49eSRichard Henderson             break;
685cc5de49eSRichard Henderson 
686cf2ae442SRichard Henderson         case 0x9: /* l.div */
687cf2ae442SRichard Henderson             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
688cf2ae442SRichard Henderson             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
689cf2ae442SRichard Henderson             return;
690cf2ae442SRichard Henderson 
691cf2ae442SRichard Henderson         case 0xa: /* l.divu */
692cf2ae442SRichard Henderson             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
693cf2ae442SRichard Henderson             gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
694cf2ae442SRichard Henderson             return;
695cf2ae442SRichard Henderson 
696cf2ae442SRichard Henderson         case 0xb: /* l.mulu */
697cf2ae442SRichard Henderson             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
698cf2ae442SRichard Henderson             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
699cf2ae442SRichard Henderson             return;
700cc5de49eSRichard Henderson 
701cc5de49eSRichard Henderson         case 0xc: /* l.muldu */
702cc5de49eSRichard Henderson             LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
703cc5de49eSRichard Henderson             gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
704cc5de49eSRichard Henderson             return;
705bbe418f2SJia Liu         }
706bbe418f2SJia Liu         break;
707bbe418f2SJia Liu     }
708bbe418f2SJia Liu     gen_illegal_exception(dc);
709bbe418f2SJia Liu }
710bbe418f2SJia Liu 
711bbe418f2SJia Liu static void dec_misc(DisasContext *dc, uint32_t insn)
712bbe418f2SJia Liu {
713bbe418f2SJia Liu     uint32_t op0, op1;
714bbe418f2SJia Liu     uint32_t ra, rb, rd;
7156da544a6SRichard Henderson     uint32_t L6, K5, K16, K5_11;
7166da544a6SRichard Henderson     int32_t I16, I5_11, N26;
7175631e69cSRichard Henderson     TCGMemOp mop;
7189ecaa27eSRichard Henderson     TCGv t0;
7195631e69cSRichard Henderson 
720bbe418f2SJia Liu     op0 = extract32(insn, 26, 6);
721bbe418f2SJia Liu     op1 = extract32(insn, 24, 2);
722bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
723bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
724bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
725bbe418f2SJia Liu     L6 = extract32(insn, 5, 6);
726bbe418f2SJia Liu     K5 = extract32(insn, 0, 5);
7276da544a6SRichard Henderson     K16 = extract32(insn, 0, 16);
7286da544a6SRichard Henderson     I16 = (int16_t)K16;
7296da544a6SRichard Henderson     N26 = sextract32(insn, 0, 26);
7306da544a6SRichard Henderson     K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
7316da544a6SRichard Henderson     I5_11 = (int16_t)K5_11;
732bbe418f2SJia Liu 
733bbe418f2SJia Liu     switch (op0) {
734bbe418f2SJia Liu     case 0x00:    /* l.j */
735bbe418f2SJia Liu         LOG_DIS("l.j %d\n", N26);
736bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
737bbe418f2SJia Liu         break;
738bbe418f2SJia Liu 
739bbe418f2SJia Liu     case 0x01:    /* l.jal */
740bbe418f2SJia Liu         LOG_DIS("l.jal %d\n", N26);
741bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
742bbe418f2SJia Liu         break;
743bbe418f2SJia Liu 
744bbe418f2SJia Liu     case 0x03:    /* l.bnf */
745bbe418f2SJia Liu         LOG_DIS("l.bnf %d\n", N26);
746bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
747bbe418f2SJia Liu         break;
748bbe418f2SJia Liu 
749bbe418f2SJia Liu     case 0x04:    /* l.bf */
750bbe418f2SJia Liu         LOG_DIS("l.bf %d\n", N26);
751bbe418f2SJia Liu         gen_jump(dc, N26, 0, op0);
752bbe418f2SJia Liu         break;
753bbe418f2SJia Liu 
754bbe418f2SJia Liu     case 0x05:
755bbe418f2SJia Liu         switch (op1) {
756bbe418f2SJia Liu         case 0x01:    /* l.nop */
757bbe418f2SJia Liu             LOG_DIS("l.nop %d\n", I16);
758bbe418f2SJia Liu             break;
759bbe418f2SJia Liu 
760bbe418f2SJia Liu         default:
761bbe418f2SJia Liu             gen_illegal_exception(dc);
762bbe418f2SJia Liu             break;
763bbe418f2SJia Liu         }
764bbe418f2SJia Liu         break;
765bbe418f2SJia Liu 
766bbe418f2SJia Liu     case 0x11:    /* l.jr */
767bbe418f2SJia Liu         LOG_DIS("l.jr r%d\n", rb);
768bbe418f2SJia Liu          gen_jump(dc, 0, rb, op0);
769bbe418f2SJia Liu          break;
770bbe418f2SJia Liu 
771bbe418f2SJia Liu     case 0x12:    /* l.jalr */
772bbe418f2SJia Liu         LOG_DIS("l.jalr r%d\n", rb);
773bbe418f2SJia Liu         gen_jump(dc, 0, rb, op0);
774bbe418f2SJia Liu         break;
775bbe418f2SJia Liu 
776bbe418f2SJia Liu     case 0x13:    /* l.maci */
7776da544a6SRichard Henderson         LOG_DIS("l.maci r%d, %d\n", ra, I16);
7786f7332baSRichard Henderson         t0 = tcg_const_tl(I16);
7796f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], t0);
7806f7332baSRichard Henderson         tcg_temp_free(t0);
781bbe418f2SJia Liu         break;
782bbe418f2SJia Liu 
783bbe418f2SJia Liu     case 0x09:    /* l.rfe */
784bbe418f2SJia Liu         LOG_DIS("l.rfe\n");
785bbe418f2SJia Liu         {
786bbe418f2SJia Liu #if defined(CONFIG_USER_ONLY)
787bbe418f2SJia Liu             return;
788bbe418f2SJia Liu #else
789bbe418f2SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
790bbe418f2SJia Liu                 gen_illegal_exception(dc);
791bbe418f2SJia Liu                 return;
792bbe418f2SJia Liu             }
793bbe418f2SJia Liu             gen_helper_rfe(cpu_env);
794bbe418f2SJia Liu             dc->is_jmp = DISAS_UPDATE;
795bbe418f2SJia Liu #endif
796bbe418f2SJia Liu         }
797bbe418f2SJia Liu         break;
798bbe418f2SJia Liu 
799930c3d00SRichard Henderson     case 0x1b: /* l.lwa */
800930c3d00SRichard Henderson         LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
801*6597c28dSRichard Henderson         check_r0_write(rd);
802930c3d00SRichard Henderson         gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
803930c3d00SRichard Henderson         break;
804930c3d00SRichard Henderson 
805bbe418f2SJia Liu     case 0x1c:    /* l.cust1 */
806bbe418f2SJia Liu         LOG_DIS("l.cust1\n");
807bbe418f2SJia Liu         break;
808bbe418f2SJia Liu 
809bbe418f2SJia Liu     case 0x1d:    /* l.cust2 */
810bbe418f2SJia Liu         LOG_DIS("l.cust2\n");
811bbe418f2SJia Liu         break;
812bbe418f2SJia Liu 
813bbe418f2SJia Liu     case 0x1e:    /* l.cust3 */
814bbe418f2SJia Liu         LOG_DIS("l.cust3\n");
815bbe418f2SJia Liu         break;
816bbe418f2SJia Liu 
817bbe418f2SJia Liu     case 0x1f:    /* l.cust4 */
818bbe418f2SJia Liu         LOG_DIS("l.cust4\n");
819bbe418f2SJia Liu         break;
820bbe418f2SJia Liu 
821bbe418f2SJia Liu     case 0x3c:    /* l.cust5 */
822bbe418f2SJia Liu         LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);
823bbe418f2SJia Liu         break;
824bbe418f2SJia Liu 
825bbe418f2SJia Liu     case 0x3d:    /* l.cust6 */
826bbe418f2SJia Liu         LOG_DIS("l.cust6\n");
827bbe418f2SJia Liu         break;
828bbe418f2SJia Liu 
829bbe418f2SJia Liu     case 0x3e:    /* l.cust7 */
830bbe418f2SJia Liu         LOG_DIS("l.cust7\n");
831bbe418f2SJia Liu         break;
832bbe418f2SJia Liu 
833bbe418f2SJia Liu     case 0x3f:    /* l.cust8 */
834bbe418f2SJia Liu         LOG_DIS("l.cust8\n");
835bbe418f2SJia Liu         break;
836bbe418f2SJia Liu 
837bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
838bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
839bbe418f2SJia Liu     case 0x20:     l.ld
840bbe418f2SJia Liu         LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
841bbe418f2SJia Liu         check_ob64s(dc);
8425631e69cSRichard Henderson         mop = MO_TEQ;
8435631e69cSRichard Henderson         goto do_load;
844bbe418f2SJia Liu #endif*/
845bbe418f2SJia Liu 
846bbe418f2SJia Liu     case 0x21:    /* l.lwz */
847bbe418f2SJia Liu         LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
8485631e69cSRichard Henderson         mop = MO_TEUL;
8495631e69cSRichard Henderson         goto do_load;
850bbe418f2SJia Liu 
851bbe418f2SJia Liu     case 0x22:    /* l.lws */
852bbe418f2SJia Liu         LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
8535631e69cSRichard Henderson         mop = MO_TESL;
8545631e69cSRichard Henderson         goto do_load;
855bbe418f2SJia Liu 
856bbe418f2SJia Liu     case 0x23:    /* l.lbz */
857bbe418f2SJia Liu         LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
8585631e69cSRichard Henderson         mop = MO_UB;
8595631e69cSRichard Henderson         goto do_load;
860bbe418f2SJia Liu 
861bbe418f2SJia Liu     case 0x24:    /* l.lbs */
862bbe418f2SJia Liu         LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
8635631e69cSRichard Henderson         mop = MO_SB;
8645631e69cSRichard Henderson         goto do_load;
865bbe418f2SJia Liu 
866bbe418f2SJia Liu     case 0x25:    /* l.lhz */
867bbe418f2SJia Liu         LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
8685631e69cSRichard Henderson         mop = MO_TEUW;
8695631e69cSRichard Henderson         goto do_load;
870bbe418f2SJia Liu 
871bbe418f2SJia Liu     case 0x26:    /* l.lhs */
872bbe418f2SJia Liu         LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
8735631e69cSRichard Henderson         mop = MO_TESW;
8745631e69cSRichard Henderson         goto do_load;
8755631e69cSRichard Henderson 
8765631e69cSRichard Henderson     do_load:
877*6597c28dSRichard Henderson         check_r0_write(rd);
878*6597c28dSRichard Henderson         t0 = tcg_temp_new();
8796da544a6SRichard Henderson         tcg_gen_addi_tl(t0, cpu_R[ra], I16);
8805631e69cSRichard Henderson         tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
881bbe418f2SJia Liu         tcg_temp_free(t0);
882bbe418f2SJia Liu         break;
883bbe418f2SJia Liu 
884bbe418f2SJia Liu     case 0x27:    /* l.addi */
885bbe418f2SJia Liu         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
886*6597c28dSRichard Henderson         check_r0_write(rd);
8879ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
8889ecaa27eSRichard Henderson         gen_add(dc, cpu_R[rd], cpu_R[ra], t0);
8899ecaa27eSRichard Henderson         tcg_temp_free(t0);
890bbe418f2SJia Liu         break;
891bbe418f2SJia Liu 
892bbe418f2SJia Liu     case 0x28:    /* l.addic */
893bbe418f2SJia Liu         LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
894*6597c28dSRichard Henderson         check_r0_write(rd);
8959ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
8969ecaa27eSRichard Henderson         gen_addc(dc, cpu_R[rd], cpu_R[ra], t0);
8979ecaa27eSRichard Henderson         tcg_temp_free(t0);
898bbe418f2SJia Liu         break;
899bbe418f2SJia Liu 
900bbe418f2SJia Liu     case 0x29:    /* l.andi */
9016da544a6SRichard Henderson         LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16);
902*6597c28dSRichard Henderson         check_r0_write(rd);
9036da544a6SRichard Henderson         tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16);
904bbe418f2SJia Liu         break;
905bbe418f2SJia Liu 
906bbe418f2SJia Liu     case 0x2a:    /* l.ori */
9076da544a6SRichard Henderson         LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16);
908*6597c28dSRichard Henderson         check_r0_write(rd);
9096da544a6SRichard Henderson         tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16);
910bbe418f2SJia Liu         break;
911bbe418f2SJia Liu 
912bbe418f2SJia Liu     case 0x2b:    /* l.xori */
913bbe418f2SJia Liu         LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
914*6597c28dSRichard Henderson         check_r0_write(rd);
9156da544a6SRichard Henderson         tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16);
916bbe418f2SJia Liu         break;
917bbe418f2SJia Liu 
918bbe418f2SJia Liu     case 0x2c:    /* l.muli */
919bbe418f2SJia Liu         LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
920*6597c28dSRichard Henderson         check_r0_write(rd);
9219ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
9229ecaa27eSRichard Henderson         gen_mul(dc, cpu_R[rd], cpu_R[ra], t0);
9239ecaa27eSRichard Henderson         tcg_temp_free(t0);
924bbe418f2SJia Liu         break;
925bbe418f2SJia Liu 
926bbe418f2SJia Liu     case 0x2d:    /* l.mfspr */
9276da544a6SRichard Henderson         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
928*6597c28dSRichard Henderson         check_r0_write(rd);
9294dd044c6SJia Liu         {
9304dd044c6SJia Liu #if defined(CONFIG_USER_ONLY)
9314dd044c6SJia Liu             return;
9324dd044c6SJia Liu #else
9336da544a6SRichard Henderson             TCGv_i32 ti = tcg_const_i32(K16);
9344dd044c6SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
9354dd044c6SJia Liu                 gen_illegal_exception(dc);
9364dd044c6SJia Liu                 return;
9374dd044c6SJia Liu             }
9384dd044c6SJia Liu             gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
9394dd044c6SJia Liu             tcg_temp_free_i32(ti);
9404dd044c6SJia Liu #endif
9414dd044c6SJia Liu         }
942bbe418f2SJia Liu         break;
943bbe418f2SJia Liu 
944bbe418f2SJia Liu     case 0x30:    /* l.mtspr */
9456da544a6SRichard Henderson         LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11);
9464dd044c6SJia Liu         {
9474dd044c6SJia Liu #if defined(CONFIG_USER_ONLY)
9484dd044c6SJia Liu             return;
9494dd044c6SJia Liu #else
9506da544a6SRichard Henderson             TCGv_i32 im = tcg_const_i32(K5_11);
9514dd044c6SJia Liu             if (dc->mem_idx == MMU_USER_IDX) {
9524dd044c6SJia Liu                 gen_illegal_exception(dc);
9534dd044c6SJia Liu                 return;
9544dd044c6SJia Liu             }
9554dd044c6SJia Liu             gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
9564dd044c6SJia Liu             tcg_temp_free_i32(im);
9574dd044c6SJia Liu #endif
9584dd044c6SJia Liu         }
959bbe418f2SJia Liu         break;
960bbe418f2SJia Liu 
961930c3d00SRichard Henderson     case 0x33: /* l.swa */
9626da544a6SRichard Henderson         LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
963*6597c28dSRichard Henderson         gen_swa(dc, rb, cpu_R[ra], I5_11);
964930c3d00SRichard Henderson         break;
965930c3d00SRichard Henderson 
966bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
967bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
968bbe418f2SJia Liu     case 0x34:     l.sd
9696da544a6SRichard Henderson         LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
970bbe418f2SJia Liu         check_ob64s(dc);
9715631e69cSRichard Henderson         mop = MO_TEQ;
9725631e69cSRichard Henderson         goto do_store;
973bbe418f2SJia Liu #endif*/
974bbe418f2SJia Liu 
975bbe418f2SJia Liu     case 0x35:    /* l.sw */
9766da544a6SRichard Henderson         LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
9775631e69cSRichard Henderson         mop = MO_TEUL;
9785631e69cSRichard Henderson         goto do_store;
979bbe418f2SJia Liu 
980bbe418f2SJia Liu     case 0x36:    /* l.sb */
9816da544a6SRichard Henderson         LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
9825631e69cSRichard Henderson         mop = MO_UB;
9835631e69cSRichard Henderson         goto do_store;
984bbe418f2SJia Liu 
985bbe418f2SJia Liu     case 0x37:    /* l.sh */
9866da544a6SRichard Henderson         LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
9875631e69cSRichard Henderson         mop = MO_TEUW;
9885631e69cSRichard Henderson         goto do_store;
9895631e69cSRichard Henderson 
9905631e69cSRichard Henderson     do_store:
991bbe418f2SJia Liu         {
992bbe418f2SJia Liu             TCGv t0 = tcg_temp_new();
9936da544a6SRichard Henderson             tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
9945631e69cSRichard Henderson             tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
995bbe418f2SJia Liu             tcg_temp_free(t0);
996bbe418f2SJia Liu         }
997bbe418f2SJia Liu         break;
998bbe418f2SJia Liu 
999bbe418f2SJia Liu     default:
1000bbe418f2SJia Liu         gen_illegal_exception(dc);
1001bbe418f2SJia Liu         break;
1002bbe418f2SJia Liu     }
1003bbe418f2SJia Liu }
1004bbe418f2SJia Liu 
1005bbe418f2SJia Liu static void dec_mac(DisasContext *dc, uint32_t insn)
1006bbe418f2SJia Liu {
1007bbe418f2SJia Liu     uint32_t op0;
1008bbe418f2SJia Liu     uint32_t ra, rb;
1009bbe418f2SJia Liu     op0 = extract32(insn, 0, 4);
1010bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1011bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1012bbe418f2SJia Liu 
1013bbe418f2SJia Liu     switch (op0) {
1014bbe418f2SJia Liu     case 0x0001:    /* l.mac */
1015bbe418f2SJia Liu         LOG_DIS("l.mac r%d, r%d\n", ra, rb);
10166f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], cpu_R[rb]);
1017bbe418f2SJia Liu         break;
1018bbe418f2SJia Liu 
1019bbe418f2SJia Liu     case 0x0002:    /* l.msb */
1020bbe418f2SJia Liu         LOG_DIS("l.msb r%d, r%d\n", ra, rb);
10216f7332baSRichard Henderson         gen_msb(dc, cpu_R[ra], cpu_R[rb]);
1022bbe418f2SJia Liu         break;
1023bbe418f2SJia Liu 
1024cc5de49eSRichard Henderson     case 0x0003:    /* l.macu */
1025cc5de49eSRichard Henderson         LOG_DIS("l.macu r%d, r%d\n", ra, rb);
1026cc5de49eSRichard Henderson         gen_macu(dc, cpu_R[ra], cpu_R[rb]);
1027cc5de49eSRichard Henderson         break;
1028cc5de49eSRichard Henderson 
1029cc5de49eSRichard Henderson     case 0x0004:    /* l.msbu */
1030cc5de49eSRichard Henderson         LOG_DIS("l.msbu r%d, r%d\n", ra, rb);
1031cc5de49eSRichard Henderson         gen_msbu(dc, cpu_R[ra], cpu_R[rb]);
1032cc5de49eSRichard Henderson         break;
1033cc5de49eSRichard Henderson 
1034bbe418f2SJia Liu     default:
1035bbe418f2SJia Liu         gen_illegal_exception(dc);
1036bbe418f2SJia Liu         break;
1037bbe418f2SJia Liu    }
1038bbe418f2SJia Liu }
1039bbe418f2SJia Liu 
1040bbe418f2SJia Liu static void dec_logic(DisasContext *dc, uint32_t insn)
1041bbe418f2SJia Liu {
1042bbe418f2SJia Liu     uint32_t op0;
10436da544a6SRichard Henderson     uint32_t rd, ra, L6, S6;
1044bbe418f2SJia Liu     op0 = extract32(insn, 6, 2);
1045bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1046bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1047bbe418f2SJia Liu     L6 = extract32(insn, 0, 6);
10486da544a6SRichard Henderson     S6 = L6 & (TARGET_LONG_BITS - 1);
1049bbe418f2SJia Liu 
1050*6597c28dSRichard Henderson     check_r0_write(rd);
1051bbe418f2SJia Liu     switch (op0) {
1052bbe418f2SJia Liu     case 0x00:    /* l.slli */
1053bbe418f2SJia Liu         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
10546da544a6SRichard Henderson         tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6);
1055bbe418f2SJia Liu         break;
1056bbe418f2SJia Liu 
1057bbe418f2SJia Liu     case 0x01:    /* l.srli */
1058bbe418f2SJia Liu         LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
10596da544a6SRichard Henderson         tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6);
1060bbe418f2SJia Liu         break;
1061bbe418f2SJia Liu 
1062bbe418f2SJia Liu     case 0x02:    /* l.srai */
1063bbe418f2SJia Liu         LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
10646da544a6SRichard Henderson         tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6);
10656da544a6SRichard Henderson         break;
1066bbe418f2SJia Liu 
1067bbe418f2SJia Liu     case 0x03:    /* l.rori */
1068bbe418f2SJia Liu         LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
10696da544a6SRichard Henderson         tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6);
1070bbe418f2SJia Liu         break;
1071bbe418f2SJia Liu 
1072bbe418f2SJia Liu     default:
1073bbe418f2SJia Liu         gen_illegal_exception(dc);
1074bbe418f2SJia Liu         break;
1075bbe418f2SJia Liu     }
1076bbe418f2SJia Liu }
1077bbe418f2SJia Liu 
1078bbe418f2SJia Liu static void dec_M(DisasContext *dc, uint32_t insn)
1079bbe418f2SJia Liu {
1080bbe418f2SJia Liu     uint32_t op0;
1081bbe418f2SJia Liu     uint32_t rd;
1082bbe418f2SJia Liu     uint32_t K16;
1083bbe418f2SJia Liu     op0 = extract32(insn, 16, 1);
1084bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1085bbe418f2SJia Liu     K16 = extract32(insn, 0, 16);
1086bbe418f2SJia Liu 
1087*6597c28dSRichard Henderson     check_r0_write(rd);
1088bbe418f2SJia Liu     switch (op0) {
1089bbe418f2SJia Liu     case 0x0:    /* l.movhi */
1090bbe418f2SJia Liu         LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
1091bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
1092bbe418f2SJia Liu         break;
1093bbe418f2SJia Liu 
1094bbe418f2SJia Liu     case 0x1:    /* l.macrc */
1095bbe418f2SJia Liu         LOG_DIS("l.macrc  r%d\n", rd);
10966f7332baSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
10976f7332baSRichard Henderson         tcg_gen_movi_i64(cpu_mac, 0);
1098bbe418f2SJia Liu         break;
1099bbe418f2SJia Liu 
1100bbe418f2SJia Liu     default:
1101bbe418f2SJia Liu         gen_illegal_exception(dc);
1102bbe418f2SJia Liu         break;
1103bbe418f2SJia Liu     }
1104bbe418f2SJia Liu }
1105bbe418f2SJia Liu 
1106bbe418f2SJia Liu static void dec_comp(DisasContext *dc, uint32_t insn)
1107bbe418f2SJia Liu {
1108bbe418f2SJia Liu     uint32_t op0;
1109bbe418f2SJia Liu     uint32_t ra, rb;
1110bbe418f2SJia Liu 
1111bbe418f2SJia Liu     op0 = extract32(insn, 21, 5);
1112bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1113bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1114bbe418f2SJia Liu 
1115bbe418f2SJia Liu     /* unsigned integers  */
1116bbe418f2SJia Liu     tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
1117bbe418f2SJia Liu     tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
1118bbe418f2SJia Liu 
1119bbe418f2SJia Liu     switch (op0) {
1120bbe418f2SJia Liu     case 0x0:    /* l.sfeq */
1121bbe418f2SJia Liu         LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
112284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1123bbe418f2SJia Liu         break;
1124bbe418f2SJia Liu 
1125bbe418f2SJia Liu     case 0x1:    /* l.sfne */
1126bbe418f2SJia Liu         LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
112784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1128bbe418f2SJia Liu         break;
1129bbe418f2SJia Liu 
1130bbe418f2SJia Liu     case 0x2:    /* l.sfgtu */
1131bbe418f2SJia Liu         LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
113284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1133bbe418f2SJia Liu         break;
1134bbe418f2SJia Liu 
1135bbe418f2SJia Liu     case 0x3:    /* l.sfgeu */
1136bbe418f2SJia Liu         LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
113784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1138bbe418f2SJia Liu         break;
1139bbe418f2SJia Liu 
1140bbe418f2SJia Liu     case 0x4:    /* l.sfltu */
1141bbe418f2SJia Liu         LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
114284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1143bbe418f2SJia Liu         break;
1144bbe418f2SJia Liu 
1145bbe418f2SJia Liu     case 0x5:    /* l.sfleu */
1146bbe418f2SJia Liu         LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
114784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1148bbe418f2SJia Liu         break;
1149bbe418f2SJia Liu 
1150bbe418f2SJia Liu     case 0xa:    /* l.sfgts */
1151bbe418f2SJia Liu         LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
115284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1153bbe418f2SJia Liu         break;
1154bbe418f2SJia Liu 
1155bbe418f2SJia Liu     case 0xb:    /* l.sfges */
1156bbe418f2SJia Liu         LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
115784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1158bbe418f2SJia Liu         break;
1159bbe418f2SJia Liu 
1160bbe418f2SJia Liu     case 0xc:    /* l.sflts */
1161bbe418f2SJia Liu         LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
116284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1163bbe418f2SJia Liu         break;
1164bbe418f2SJia Liu 
1165bbe418f2SJia Liu     case 0xd:    /* l.sfles */
1166bbe418f2SJia Liu         LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
116784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1168bbe418f2SJia Liu         break;
1169bbe418f2SJia Liu 
1170bbe418f2SJia Liu     default:
1171bbe418f2SJia Liu         gen_illegal_exception(dc);
1172bbe418f2SJia Liu         break;
1173bbe418f2SJia Liu     }
1174bbe418f2SJia Liu }
1175bbe418f2SJia Liu 
1176bbe418f2SJia Liu static void dec_compi(DisasContext *dc, uint32_t insn)
1177bbe418f2SJia Liu {
11786da544a6SRichard Henderson     uint32_t op0, ra;
11796da544a6SRichard Henderson     int32_t I16;
1180bbe418f2SJia Liu 
1181bbe418f2SJia Liu     op0 = extract32(insn, 21, 5);
1182bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
11836da544a6SRichard Henderson     I16 = sextract32(insn, 0, 16);
1184bbe418f2SJia Liu 
1185bbe418f2SJia Liu     switch (op0) {
1186bbe418f2SJia Liu     case 0x0:    /* l.sfeqi */
1187bbe418f2SJia Liu         LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
118884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16);
1189bbe418f2SJia Liu         break;
1190bbe418f2SJia Liu 
1191bbe418f2SJia Liu     case 0x1:    /* l.sfnei */
1192bbe418f2SJia Liu         LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
119384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16);
1194bbe418f2SJia Liu         break;
1195bbe418f2SJia Liu 
1196bbe418f2SJia Liu     case 0x2:    /* l.sfgtui */
1197bbe418f2SJia Liu         LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
119884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16);
1199bbe418f2SJia Liu         break;
1200bbe418f2SJia Liu 
1201bbe418f2SJia Liu     case 0x3:    /* l.sfgeui */
1202bbe418f2SJia Liu         LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
120384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16);
1204bbe418f2SJia Liu         break;
1205bbe418f2SJia Liu 
1206bbe418f2SJia Liu     case 0x4:    /* l.sfltui */
1207bbe418f2SJia Liu         LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
120884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16);
1209bbe418f2SJia Liu         break;
1210bbe418f2SJia Liu 
1211bbe418f2SJia Liu     case 0x5:    /* l.sfleui */
1212bbe418f2SJia Liu         LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
121384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16);
1214bbe418f2SJia Liu         break;
1215bbe418f2SJia Liu 
1216bbe418f2SJia Liu     case 0xa:    /* l.sfgtsi */
1217bbe418f2SJia Liu         LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
121884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16);
1219bbe418f2SJia Liu         break;
1220bbe418f2SJia Liu 
1221bbe418f2SJia Liu     case 0xb:    /* l.sfgesi */
1222bbe418f2SJia Liu         LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
122384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16);
1224bbe418f2SJia Liu         break;
1225bbe418f2SJia Liu 
1226bbe418f2SJia Liu     case 0xc:    /* l.sfltsi */
1227bbe418f2SJia Liu         LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
122884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16);
1229bbe418f2SJia Liu         break;
1230bbe418f2SJia Liu 
1231bbe418f2SJia Liu     case 0xd:    /* l.sflesi */
1232bbe418f2SJia Liu         LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
123384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16);
1234bbe418f2SJia Liu         break;
1235bbe418f2SJia Liu 
1236bbe418f2SJia Liu     default:
1237bbe418f2SJia Liu         gen_illegal_exception(dc);
1238bbe418f2SJia Liu         break;
1239bbe418f2SJia Liu     }
1240bbe418f2SJia Liu }
1241bbe418f2SJia Liu 
1242bbe418f2SJia Liu static void dec_sys(DisasContext *dc, uint32_t insn)
1243bbe418f2SJia Liu {
1244bbe418f2SJia Liu     uint32_t op0;
1245bbe418f2SJia Liu     uint32_t K16;
1246111ece51SRichard Henderson 
12473d59b680SDavid Morrison     op0 = extract32(insn, 16, 10);
1248bbe418f2SJia Liu     K16 = extract32(insn, 0, 16);
1249bbe418f2SJia Liu 
1250bbe418f2SJia Liu     switch (op0) {
1251bbe418f2SJia Liu     case 0x000:    /* l.sys */
1252bbe418f2SJia Liu         LOG_DIS("l.sys %d\n", K16);
1253bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dc->pc);
1254bbe418f2SJia Liu         gen_exception(dc, EXCP_SYSCALL);
1255bbe418f2SJia Liu         dc->is_jmp = DISAS_UPDATE;
1256bbe418f2SJia Liu         break;
1257bbe418f2SJia Liu 
1258bbe418f2SJia Liu     case 0x100:    /* l.trap */
1259bbe418f2SJia Liu         LOG_DIS("l.trap %d\n", K16);
1260bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dc->pc);
1261bbe418f2SJia Liu         gen_exception(dc, EXCP_TRAP);
1262bbe418f2SJia Liu         break;
1263bbe418f2SJia Liu 
1264bbe418f2SJia Liu     case 0x300:    /* l.csync */
1265bbe418f2SJia Liu         LOG_DIS("l.csync\n");
1266bbe418f2SJia Liu         break;
1267bbe418f2SJia Liu 
1268bbe418f2SJia Liu     case 0x200:    /* l.msync */
1269bbe418f2SJia Liu         LOG_DIS("l.msync\n");
127024fc5c0fSRichard Henderson         tcg_gen_mb(TCG_MO_ALL);
1271bbe418f2SJia Liu         break;
1272bbe418f2SJia Liu 
1273bbe418f2SJia Liu     case 0x270:    /* l.psync */
1274bbe418f2SJia Liu         LOG_DIS("l.psync\n");
1275bbe418f2SJia Liu         break;
1276bbe418f2SJia Liu 
1277bbe418f2SJia Liu     default:
1278bbe418f2SJia Liu         gen_illegal_exception(dc);
1279bbe418f2SJia Liu         break;
1280bbe418f2SJia Liu     }
1281bbe418f2SJia Liu }
1282bbe418f2SJia Liu 
1283bbe418f2SJia Liu static void dec_float(DisasContext *dc, uint32_t insn)
1284bbe418f2SJia Liu {
1285bbe418f2SJia Liu     uint32_t op0;
1286bbe418f2SJia Liu     uint32_t ra, rb, rd;
1287bbe418f2SJia Liu     op0 = extract32(insn, 0, 8);
1288bbe418f2SJia Liu     ra = extract32(insn, 16, 5);
1289bbe418f2SJia Liu     rb = extract32(insn, 11, 5);
1290bbe418f2SJia Liu     rd = extract32(insn, 21, 5);
1291bbe418f2SJia Liu 
1292bbe418f2SJia Liu     switch (op0) {
1293bbe418f2SJia Liu     case 0x00:    /* lf.add.s */
1294bbe418f2SJia Liu         LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
1295*6597c28dSRichard Henderson         check_r0_write(rd);
1296bbe418f2SJia Liu         gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1297bbe418f2SJia Liu         break;
1298bbe418f2SJia Liu 
1299bbe418f2SJia Liu     case 0x01:    /* lf.sub.s */
1300bbe418f2SJia Liu         LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
1301*6597c28dSRichard Henderson         check_r0_write(rd);
1302bbe418f2SJia Liu         gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1303bbe418f2SJia Liu         break;
1304bbe418f2SJia Liu 
1305bbe418f2SJia Liu     case 0x02:    /* lf.mul.s */
1306bbe418f2SJia Liu         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
1307*6597c28dSRichard Henderson         check_r0_write(rd);
1308bbe418f2SJia Liu         gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1309bbe418f2SJia Liu         break;
1310bbe418f2SJia Liu 
1311bbe418f2SJia Liu     case 0x03:    /* lf.div.s */
1312bbe418f2SJia Liu         LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
1313*6597c28dSRichard Henderson         check_r0_write(rd);
1314bbe418f2SJia Liu         gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1315bbe418f2SJia Liu         break;
1316bbe418f2SJia Liu 
1317bbe418f2SJia Liu     case 0x04:    /* lf.itof.s */
1318bbe418f2SJia Liu         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
1319*6597c28dSRichard Henderson         check_r0_write(rd);
1320bbe418f2SJia Liu         gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
1321bbe418f2SJia Liu         break;
1322bbe418f2SJia Liu 
1323bbe418f2SJia Liu     case 0x05:    /* lf.ftoi.s */
1324bbe418f2SJia Liu         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
1325*6597c28dSRichard Henderson         check_r0_write(rd);
1326bbe418f2SJia Liu         gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
1327bbe418f2SJia Liu         break;
1328bbe418f2SJia Liu 
1329bbe418f2SJia Liu     case 0x06:    /* lf.rem.s */
1330bbe418f2SJia Liu         LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
1331*6597c28dSRichard Henderson         check_r0_write(rd);
1332bbe418f2SJia Liu         gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1333bbe418f2SJia Liu         break;
1334bbe418f2SJia Liu 
1335bbe418f2SJia Liu     case 0x07:    /* lf.madd.s */
1336bbe418f2SJia Liu         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
1337*6597c28dSRichard Henderson         check_r0_write(rd);
1338762e22edSRichard Henderson         gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
1339762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
1340bbe418f2SJia Liu         break;
1341bbe418f2SJia Liu 
1342bbe418f2SJia Liu     case 0x08:    /* lf.sfeq.s */
1343bbe418f2SJia Liu         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
134484775c43SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1345bbe418f2SJia Liu         break;
1346bbe418f2SJia Liu 
1347bbe418f2SJia Liu     case 0x09:    /* lf.sfne.s */
1348bbe418f2SJia Liu         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
134984775c43SRichard Henderson         gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1350bbe418f2SJia Liu         break;
1351bbe418f2SJia Liu 
1352bbe418f2SJia Liu     case 0x0a:    /* lf.sfgt.s */
1353bbe418f2SJia Liu         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
135484775c43SRichard Henderson         gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1355bbe418f2SJia Liu         break;
1356bbe418f2SJia Liu 
1357bbe418f2SJia Liu     case 0x0b:    /* lf.sfge.s */
1358bbe418f2SJia Liu         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
135984775c43SRichard Henderson         gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1360bbe418f2SJia Liu         break;
1361bbe418f2SJia Liu 
1362bbe418f2SJia Liu     case 0x0c:    /* lf.sflt.s */
1363bbe418f2SJia Liu         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
136484775c43SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1365bbe418f2SJia Liu         break;
1366bbe418f2SJia Liu 
1367bbe418f2SJia Liu     case 0x0d:    /* lf.sfle.s */
1368bbe418f2SJia Liu         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
136984775c43SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1370bbe418f2SJia Liu         break;
1371bbe418f2SJia Liu 
1372bbe418f2SJia Liu /* not used yet, open it when we need or64.  */
1373bbe418f2SJia Liu /*#ifdef TARGET_OPENRISC64
1374bbe418f2SJia Liu     case 0x10:     lf.add.d
1375bbe418f2SJia Liu         LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
1376bbe418f2SJia Liu         check_of64s(dc);
1377*6597c28dSRichard Henderson         check_r0_write(rd);
1378bbe418f2SJia Liu         gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1379bbe418f2SJia Liu         break;
1380bbe418f2SJia Liu 
1381bbe418f2SJia Liu     case 0x11:     lf.sub.d
1382bbe418f2SJia Liu         LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
1383bbe418f2SJia Liu         check_of64s(dc);
1384*6597c28dSRichard Henderson         check_r0_write(rd);
1385bbe418f2SJia Liu         gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1386bbe418f2SJia Liu         break;
1387bbe418f2SJia Liu 
1388bbe418f2SJia Liu     case 0x12:     lf.mul.d
1389bbe418f2SJia Liu         LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
1390bbe418f2SJia Liu         check_of64s(dc);
1391*6597c28dSRichard Henderson         check_r0_write(rd);
1392bbe418f2SJia Liu         gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1393bbe418f2SJia Liu         break;
1394bbe418f2SJia Liu 
1395bbe418f2SJia Liu     case 0x13:     lf.div.d
1396bbe418f2SJia Liu         LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
1397bbe418f2SJia Liu         check_of64s(dc);
1398*6597c28dSRichard Henderson         check_r0_write(rd);
1399bbe418f2SJia Liu         gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1400bbe418f2SJia Liu         break;
1401bbe418f2SJia Liu 
1402bbe418f2SJia Liu     case 0x14:     lf.itof.d
1403bbe418f2SJia Liu         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
1404bbe418f2SJia Liu         check_of64s(dc);
1405*6597c28dSRichard Henderson         check_r0_write(rd);
1406bbe418f2SJia Liu         gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
1407bbe418f2SJia Liu         break;
1408bbe418f2SJia Liu 
1409bbe418f2SJia Liu     case 0x15:     lf.ftoi.d
1410bbe418f2SJia Liu         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
1411bbe418f2SJia Liu         check_of64s(dc);
1412*6597c28dSRichard Henderson         check_r0_write(rd);
1413bbe418f2SJia Liu         gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
1414bbe418f2SJia Liu         break;
1415bbe418f2SJia Liu 
1416bbe418f2SJia Liu     case 0x16:     lf.rem.d
1417bbe418f2SJia Liu         LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
1418bbe418f2SJia Liu         check_of64s(dc);
1419*6597c28dSRichard Henderson         check_r0_write(rd);
1420bbe418f2SJia Liu         gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
1421bbe418f2SJia Liu         break;
1422bbe418f2SJia Liu 
1423bbe418f2SJia Liu     case 0x17:     lf.madd.d
1424bbe418f2SJia Liu         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
1425bbe418f2SJia Liu         check_of64s(dc);
1426*6597c28dSRichard Henderson         check_r0_write(rd);
1427762e22edSRichard Henderson         gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
1428762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
1429bbe418f2SJia Liu         break;
1430bbe418f2SJia Liu 
1431bbe418f2SJia Liu     case 0x18:     lf.sfeq.d
1432bbe418f2SJia Liu         LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
1433bbe418f2SJia Liu         check_of64s(dc);
143484775c43SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1435bbe418f2SJia Liu         break;
1436bbe418f2SJia Liu 
1437bbe418f2SJia Liu     case 0x1a:     lf.sfgt.d
1438bbe418f2SJia Liu         LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
1439bbe418f2SJia Liu         check_of64s(dc);
144084775c43SRichard Henderson         gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1441bbe418f2SJia Liu         break;
1442bbe418f2SJia Liu 
1443bbe418f2SJia Liu     case 0x1b:     lf.sfge.d
1444bbe418f2SJia Liu         LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
1445bbe418f2SJia Liu         check_of64s(dc);
144684775c43SRichard Henderson         gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1447bbe418f2SJia Liu         break;
1448bbe418f2SJia Liu 
1449bbe418f2SJia Liu     case 0x19:     lf.sfne.d
1450bbe418f2SJia Liu         LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
1451bbe418f2SJia Liu         check_of64s(dc);
145284775c43SRichard Henderson         gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1453bbe418f2SJia Liu         break;
1454bbe418f2SJia Liu 
1455bbe418f2SJia Liu     case 0x1c:     lf.sflt.d
1456bbe418f2SJia Liu         LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
1457bbe418f2SJia Liu         check_of64s(dc);
145884775c43SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1459bbe418f2SJia Liu         break;
1460bbe418f2SJia Liu 
1461bbe418f2SJia Liu     case 0x1d:     lf.sfle.d
1462bbe418f2SJia Liu         LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
1463bbe418f2SJia Liu         check_of64s(dc);
146484775c43SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
1465bbe418f2SJia Liu         break;
1466bbe418f2SJia Liu #endif*/
1467bbe418f2SJia Liu 
1468bbe418f2SJia Liu     default:
1469bbe418f2SJia Liu         gen_illegal_exception(dc);
1470bbe418f2SJia Liu         break;
1471bbe418f2SJia Liu     }
1472bbe418f2SJia Liu }
1473bbe418f2SJia Liu 
1474bbe418f2SJia Liu static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
1475bbe418f2SJia Liu {
1476bbe418f2SJia Liu     uint32_t op0;
1477bbe418f2SJia Liu     uint32_t insn;
1478bbe418f2SJia Liu     insn = cpu_ldl_code(&cpu->env, dc->pc);
1479bbe418f2SJia Liu     op0 = extract32(insn, 26, 6);
1480bbe418f2SJia Liu 
1481bbe418f2SJia Liu     switch (op0) {
1482bbe418f2SJia Liu     case 0x06:
1483bbe418f2SJia Liu         dec_M(dc, insn);
1484bbe418f2SJia Liu         break;
1485bbe418f2SJia Liu 
1486bbe418f2SJia Liu     case 0x08:
1487bbe418f2SJia Liu         dec_sys(dc, insn);
1488bbe418f2SJia Liu         break;
1489bbe418f2SJia Liu 
1490bbe418f2SJia Liu     case 0x2e:
1491bbe418f2SJia Liu         dec_logic(dc, insn);
1492bbe418f2SJia Liu         break;
1493bbe418f2SJia Liu 
1494bbe418f2SJia Liu     case 0x2f:
1495bbe418f2SJia Liu         dec_compi(dc, insn);
1496bbe418f2SJia Liu         break;
1497bbe418f2SJia Liu 
1498bbe418f2SJia Liu     case 0x31:
1499bbe418f2SJia Liu         dec_mac(dc, insn);
1500bbe418f2SJia Liu         break;
1501bbe418f2SJia Liu 
1502bbe418f2SJia Liu     case 0x32:
1503bbe418f2SJia Liu         dec_float(dc, insn);
1504bbe418f2SJia Liu         break;
1505bbe418f2SJia Liu 
1506bbe418f2SJia Liu     case 0x38:
1507bbe418f2SJia Liu         dec_calc(dc, insn);
1508bbe418f2SJia Liu         break;
1509bbe418f2SJia Liu 
1510bbe418f2SJia Liu     case 0x39:
1511bbe418f2SJia Liu         dec_comp(dc, insn);
1512bbe418f2SJia Liu         break;
1513bbe418f2SJia Liu 
1514bbe418f2SJia Liu     default:
1515bbe418f2SJia Liu         dec_misc(dc, insn);
1516bbe418f2SJia Liu         break;
1517bbe418f2SJia Liu     }
1518bbe418f2SJia Liu }
1519bbe418f2SJia Liu 
15204e5e1215SRichard Henderson void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
1521e67db06eSJia Liu {
15224e5e1215SRichard Henderson     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
1523ed2803daSAndreas Färber     CPUState *cs = CPU(cpu);
1524bbe418f2SJia Liu     struct DisasContext ctx, *dc = &ctx;
1525bbe418f2SJia Liu     uint32_t pc_start;
1526bbe418f2SJia Liu     uint32_t next_page_start;
1527bbe418f2SJia Liu     int num_insns;
1528bbe418f2SJia Liu     int max_insns;
1529bbe418f2SJia Liu 
1530bbe418f2SJia Liu     pc_start = tb->pc;
1531bbe418f2SJia Liu     dc->tb = tb;
1532bbe418f2SJia Liu 
1533bbe418f2SJia Liu     dc->is_jmp = DISAS_NEXT;
1534bbe418f2SJia Liu     dc->pc = pc_start;
153597ed5ccdSBenjamin Herrenschmidt     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
1536a01deb36SRichard Henderson     dc->tb_flags = tb->flags;
1537a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1538ed2803daSAndreas Färber     dc->singlestep_enabled = cs->singlestep_enabled;
1539bbe418f2SJia Liu 
1540bbe418f2SJia Liu     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1541bbe418f2SJia Liu     num_insns = 0;
1542bbe418f2SJia Liu     max_insns = tb->cflags & CF_COUNT_MASK;
1543bbe418f2SJia Liu 
1544bbe418f2SJia Liu     if (max_insns == 0) {
1545bbe418f2SJia Liu         max_insns = CF_COUNT_MASK;
1546bbe418f2SJia Liu     }
1547190ce7fbSRichard Henderson     if (max_insns > TCG_MAX_INSNS) {
1548190ce7fbSRichard Henderson         max_insns = TCG_MAX_INSNS;
1549190ce7fbSRichard Henderson     }
1550bbe418f2SJia Liu 
1551111ece51SRichard Henderson     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1552111ece51SRichard Henderson         && qemu_log_in_addr_range(pc_start)) {
1553111ece51SRichard Henderson         qemu_log_lock();
1554111ece51SRichard Henderson         qemu_log("----------------\n");
1555111ece51SRichard Henderson         qemu_log("IN: %s\n", lookup_symbol(pc_start));
1556111ece51SRichard Henderson     }
1557111ece51SRichard Henderson 
1558cd42d5b2SPaolo Bonzini     gen_tb_start(tb);
1559bbe418f2SJia Liu 
1560*6597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
1561*6597c28dSRichard Henderson        when it's true, which is the common case.  */
1562*6597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
1563*6597c28dSRichard Henderson         cpu_R[0] = tcg_const_tl(0);
1564*6597c28dSRichard Henderson     } else {
1565*6597c28dSRichard Henderson         cpu_R[0] = cpu_R0;
1566*6597c28dSRichard Henderson     }
1567*6597c28dSRichard Henderson 
1568bbe418f2SJia Liu     do {
1569a01deb36SRichard Henderson         tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0)
1570a01deb36SRichard Henderson 			   | (num_insns ? 2 : 0));
1571959082fcSRichard Henderson         num_insns++;
1572bbe418f2SJia Liu 
1573b933066aSRichard Henderson         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1574b933066aSRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->pc);
1575b933066aSRichard Henderson             gen_exception(dc, EXCP_DEBUG);
1576b933066aSRichard Henderson             dc->is_jmp = DISAS_UPDATE;
1577522a0d4eSRichard Henderson             /* The address covered by the breakpoint must be included in
1578522a0d4eSRichard Henderson                [tb->pc, tb->pc + tb->size) in order to for it to be
1579522a0d4eSRichard Henderson                properly cleared -- thus we increment the PC here so that
1580522a0d4eSRichard Henderson                the logic setting tb->size below does the right thing.  */
1581522a0d4eSRichard Henderson             dc->pc += 4;
1582b933066aSRichard Henderson             break;
1583b933066aSRichard Henderson         }
1584b933066aSRichard Henderson 
1585959082fcSRichard Henderson         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
1586bbe418f2SJia Liu             gen_io_start();
1587bbe418f2SJia Liu         }
1588bbe418f2SJia Liu         disas_openrisc_insn(dc, cpu);
158924c32852SRichard Henderson         dc->pc = dc->pc + 4;
159024c32852SRichard Henderson 
1591bbe418f2SJia Liu         /* delay slot */
1592bbe418f2SJia Liu         if (dc->delayed_branch) {
1593bbe418f2SJia Liu             dc->delayed_branch--;
1594bbe418f2SJia Liu             if (!dc->delayed_branch) {
1595bbe418f2SJia Liu                 tcg_gen_mov_tl(cpu_pc, jmp_pc);
159624c32852SRichard Henderson                 tcg_gen_discard_tl(jmp_pc);
159724c32852SRichard Henderson                 dc->is_jmp = DISAS_UPDATE;
1598bbe418f2SJia Liu                 break;
1599bbe418f2SJia Liu             }
1600bbe418f2SJia Liu         }
1601bbe418f2SJia Liu     } while (!dc->is_jmp
1602fe700adbSRichard Henderson              && !tcg_op_buf_full()
1603ed2803daSAndreas Färber              && !cs->singlestep_enabled
1604bbe418f2SJia Liu              && !singlestep
1605bbe418f2SJia Liu              && (dc->pc < next_page_start)
1606bbe418f2SJia Liu              && num_insns < max_insns);
1607bbe418f2SJia Liu 
1608bbe418f2SJia Liu     if (tb->cflags & CF_LAST_IO) {
1609bbe418f2SJia Liu         gen_io_end();
1610bbe418f2SJia Liu     }
161124c32852SRichard Henderson 
1612a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1613a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1614a01deb36SRichard Henderson     }
1615a01deb36SRichard Henderson 
161624c32852SRichard Henderson     tcg_gen_movi_tl(cpu_ppc, dc->pc - 4);
1617bbe418f2SJia Liu     if (dc->is_jmp == DISAS_NEXT) {
1618bbe418f2SJia Liu         dc->is_jmp = DISAS_UPDATE;
1619bbe418f2SJia Liu         tcg_gen_movi_tl(cpu_pc, dc->pc);
1620bbe418f2SJia Liu     }
1621ed2803daSAndreas Färber     if (unlikely(cs->singlestep_enabled)) {
1622bbe418f2SJia Liu         gen_exception(dc, EXCP_DEBUG);
1623bbe418f2SJia Liu     } else {
1624bbe418f2SJia Liu         switch (dc->is_jmp) {
1625bbe418f2SJia Liu         case DISAS_NEXT:
1626bbe418f2SJia Liu             gen_goto_tb(dc, 0, dc->pc);
1627bbe418f2SJia Liu             break;
1628bbe418f2SJia Liu         default:
1629bbe418f2SJia Liu         case DISAS_JUMP:
1630bbe418f2SJia Liu             break;
1631bbe418f2SJia Liu         case DISAS_UPDATE:
1632bbe418f2SJia Liu             /* indicate that the hash table must be used
1633bbe418f2SJia Liu                to find the next TB */
1634bbe418f2SJia Liu             tcg_gen_exit_tb(0);
1635bbe418f2SJia Liu             break;
1636bbe418f2SJia Liu         case DISAS_TB_JUMP:
1637bbe418f2SJia Liu             /* nothing more to generate */
1638bbe418f2SJia Liu             break;
1639bbe418f2SJia Liu         }
1640bbe418f2SJia Liu     }
1641bbe418f2SJia Liu 
1642806f352dSPeter Maydell     gen_tb_end(tb, num_insns);
16430a7df5daSRichard Henderson 
1644bbe418f2SJia Liu     tb->size = dc->pc - pc_start;
1645bbe418f2SJia Liu     tb->icount = num_insns;
1646bbe418f2SJia Liu 
16474910e6e4SRichard Henderson     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
16484910e6e4SRichard Henderson         && qemu_log_in_addr_range(pc_start)) {
1649111ece51SRichard Henderson         log_target_disas(cs, pc_start, tb->size, 0);
1650111ece51SRichard Henderson         qemu_log("\n");
16511ee73216SRichard Henderson         qemu_log_unlock();
1652bbe418f2SJia Liu     }
1653e67db06eSJia Liu }
1654e67db06eSJia Liu 
1655878096eeSAndreas Färber void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
1656e67db06eSJia Liu                              fprintf_function cpu_fprintf,
1657e67db06eSJia Liu                              int flags)
1658e67db06eSJia Liu {
1659878096eeSAndreas Färber     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1660878096eeSAndreas Färber     CPUOpenRISCState *env = &cpu->env;
1661e67db06eSJia Liu     int i;
1662878096eeSAndreas Färber 
1663e67db06eSJia Liu     cpu_fprintf(f, "PC=%08x\n", env->pc);
1664e67db06eSJia Liu     for (i = 0; i < 32; ++i) {
1665878096eeSAndreas Färber         cpu_fprintf(f, "R%02d=%08x%c", i, env->gpr[i],
1666e67db06eSJia Liu                     (i % 4) == 3 ? '\n' : ' ');
1667e67db06eSJia Liu     }
1668e67db06eSJia Liu }
1669e67db06eSJia Liu 
1670e67db06eSJia Liu void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1671bad729e2SRichard Henderson                           target_ulong *data)
1672e67db06eSJia Liu {
1673bad729e2SRichard Henderson     env->pc = data[0];
1674a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1675a01deb36SRichard Henderson     if (data[1] & 2) {
167624c32852SRichard Henderson         env->ppc = env->pc - 4;
167724c32852SRichard Henderson     }
1678e67db06eSJia Liu }
1679