xref: /qemu/target/openrisc/translate.c (revision 7de9729f)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  * OpenRISC translation
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5fcf5ef2aSThomas Huth  *                         Feng Gao <gf91597@gmail.com>
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
10fcf5ef2aSThomas Huth  * version 2 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15fcf5ef2aSThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth 
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "cpu.h"
23fcf5ef2aSThomas Huth #include "exec/exec-all.h"
24fcf5ef2aSThomas Huth #include "disas/disas.h"
25fcf5ef2aSThomas Huth #include "tcg-op.h"
26fcf5ef2aSThomas Huth #include "qemu-common.h"
27fcf5ef2aSThomas Huth #include "qemu/log.h"
28fcf5ef2aSThomas Huth #include "qemu/bitops.h"
29fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h"
3077fc6f5eSLluís Vilanova #include "exec/translator.h"
31fcf5ef2aSThomas Huth 
32fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
33fcf5ef2aSThomas Huth #include "exec/helper-gen.h"
34*7de9729fSRichard Henderson #include "exec/gen-icount.h"
35fcf5ef2aSThomas Huth 
36fcf5ef2aSThomas Huth #include "trace-tcg.h"
37fcf5ef2aSThomas Huth #include "exec/log.h"
38fcf5ef2aSThomas Huth 
39111ece51SRichard Henderson #define LOG_DIS(str, ...) \
401ffa4bceSEmilio G. Cota     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->base.pc_next,    \
411ffa4bceSEmilio G. Cota                   ## __VA_ARGS__)
42fcf5ef2aSThomas Huth 
4377fc6f5eSLluís Vilanova /* is_jmp field values */
4477fc6f5eSLluís Vilanova #define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
4577fc6f5eSLluís Vilanova #define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
4677fc6f5eSLluís Vilanova #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
4777fc6f5eSLluís Vilanova 
48fcf5ef2aSThomas Huth typedef struct DisasContext {
491ffa4bceSEmilio G. Cota     DisasContextBase base;
50fcf5ef2aSThomas Huth     uint32_t mem_idx;
51a01deb36SRichard Henderson     uint32_t tb_flags;
52fcf5ef2aSThomas Huth     uint32_t delayed_branch;
53fcf5ef2aSThomas Huth } DisasContext;
54fcf5ef2aSThomas Huth 
55*7de9729fSRichard Henderson /* Include the auto-generated decoder.  */
56*7de9729fSRichard Henderson #include "decode.inc.c"
57*7de9729fSRichard Henderson 
58fcf5ef2aSThomas Huth static TCGv cpu_sr;
59fcf5ef2aSThomas Huth static TCGv cpu_R[32];
606597c28dSRichard Henderson static TCGv cpu_R0;
61fcf5ef2aSThomas Huth static TCGv cpu_pc;
62fcf5ef2aSThomas Huth static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
63fcf5ef2aSThomas Huth static TCGv cpu_ppc;
6484775c43SRichard Henderson static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
6597458071SRichard Henderson static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
6697458071SRichard Henderson static TCGv cpu_sr_ov;          /* signed overflow */
67930c3d00SRichard Henderson static TCGv cpu_lock_addr;
68930c3d00SRichard Henderson static TCGv cpu_lock_value;
69fcf5ef2aSThomas Huth static TCGv_i32 fpcsr;
706f7332baSRichard Henderson static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
71a01deb36SRichard Henderson static TCGv_i32 cpu_dflag;
72fcf5ef2aSThomas Huth 
73fcf5ef2aSThomas Huth void openrisc_translate_init(void)
74fcf5ef2aSThomas Huth {
75fcf5ef2aSThomas Huth     static const char * const regnames[] = {
76fcf5ef2aSThomas Huth         "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77fcf5ef2aSThomas Huth         "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
78fcf5ef2aSThomas Huth         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
79fcf5ef2aSThomas Huth         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
80fcf5ef2aSThomas Huth     };
81fcf5ef2aSThomas Huth     int i;
82fcf5ef2aSThomas Huth 
83fcf5ef2aSThomas Huth     cpu_sr = tcg_global_mem_new(cpu_env,
84fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, sr), "sr");
85a01deb36SRichard Henderson     cpu_dflag = tcg_global_mem_new_i32(cpu_env,
86a01deb36SRichard Henderson                                        offsetof(CPUOpenRISCState, dflag),
87a01deb36SRichard Henderson                                        "dflag");
88fcf5ef2aSThomas Huth     cpu_pc = tcg_global_mem_new(cpu_env,
89fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, pc), "pc");
90fcf5ef2aSThomas Huth     cpu_ppc = tcg_global_mem_new(cpu_env,
91fcf5ef2aSThomas Huth                                  offsetof(CPUOpenRISCState, ppc), "ppc");
92fcf5ef2aSThomas Huth     jmp_pc = tcg_global_mem_new(cpu_env,
93fcf5ef2aSThomas Huth                                 offsetof(CPUOpenRISCState, jmp_pc), "jmp_pc");
9484775c43SRichard Henderson     cpu_sr_f = tcg_global_mem_new(cpu_env,
9584775c43SRichard Henderson                                   offsetof(CPUOpenRISCState, sr_f), "sr_f");
9697458071SRichard Henderson     cpu_sr_cy = tcg_global_mem_new(cpu_env,
9797458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_cy), "sr_cy");
9897458071SRichard Henderson     cpu_sr_ov = tcg_global_mem_new(cpu_env,
9997458071SRichard Henderson                                    offsetof(CPUOpenRISCState, sr_ov), "sr_ov");
100930c3d00SRichard Henderson     cpu_lock_addr = tcg_global_mem_new(cpu_env,
101930c3d00SRichard Henderson                                        offsetof(CPUOpenRISCState, lock_addr),
102930c3d00SRichard Henderson                                        "lock_addr");
103930c3d00SRichard Henderson     cpu_lock_value = tcg_global_mem_new(cpu_env,
104930c3d00SRichard Henderson                                         offsetof(CPUOpenRISCState, lock_value),
105930c3d00SRichard Henderson                                         "lock_value");
106fcf5ef2aSThomas Huth     fpcsr = tcg_global_mem_new_i32(cpu_env,
107fcf5ef2aSThomas Huth                                    offsetof(CPUOpenRISCState, fpcsr),
108fcf5ef2aSThomas Huth                                    "fpcsr");
1096f7332baSRichard Henderson     cpu_mac = tcg_global_mem_new_i64(cpu_env,
1106f7332baSRichard Henderson                                      offsetof(CPUOpenRISCState, mac),
1116f7332baSRichard Henderson                                      "mac");
112fcf5ef2aSThomas Huth     for (i = 0; i < 32; i++) {
113fcf5ef2aSThomas Huth         cpu_R[i] = tcg_global_mem_new(cpu_env,
114d89e71e8SStafford Horne                                       offsetof(CPUOpenRISCState,
115d89e71e8SStafford Horne                                                shadow_gpr[0][i]),
116fcf5ef2aSThomas Huth                                       regnames[i]);
117fcf5ef2aSThomas Huth     }
1186597c28dSRichard Henderson     cpu_R0 = cpu_R[0];
119fcf5ef2aSThomas Huth }
120fcf5ef2aSThomas Huth 
121fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, unsigned int excp)
122fcf5ef2aSThomas Huth {
123fcf5ef2aSThomas Huth     TCGv_i32 tmp = tcg_const_i32(excp);
124fcf5ef2aSThomas Huth     gen_helper_exception(cpu_env, tmp);
125fcf5ef2aSThomas Huth     tcg_temp_free_i32(tmp);
126fcf5ef2aSThomas Huth }
127fcf5ef2aSThomas Huth 
128fcf5ef2aSThomas Huth static void gen_illegal_exception(DisasContext *dc)
129fcf5ef2aSThomas Huth {
1301ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
131fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_ILLEGAL);
1321ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
133fcf5ef2aSThomas Huth }
134fcf5ef2aSThomas Huth 
135fcf5ef2aSThomas Huth /* not used yet, open it when we need or64.  */
136fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64
137fcf5ef2aSThomas Huth static void check_ob64s(DisasContext *dc)
138fcf5ef2aSThomas Huth {
139fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OB64S)) {
140fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
141fcf5ef2aSThomas Huth     }
142fcf5ef2aSThomas Huth }
143fcf5ef2aSThomas Huth 
144fcf5ef2aSThomas Huth static void check_of64s(DisasContext *dc)
145fcf5ef2aSThomas Huth {
146fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OF64S)) {
147fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
148fcf5ef2aSThomas Huth     }
149fcf5ef2aSThomas Huth }
150fcf5ef2aSThomas Huth 
151fcf5ef2aSThomas Huth static void check_ov64s(DisasContext *dc)
152fcf5ef2aSThomas Huth {
153fcf5ef2aSThomas Huth     if (!(dc->flags & CPUCFGR_OV64S)) {
154fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
155fcf5ef2aSThomas Huth     }
156fcf5ef2aSThomas Huth }
157fcf5ef2aSThomas Huth #endif*/
158fcf5ef2aSThomas Huth 
1596597c28dSRichard Henderson /* We're about to write to REG.  On the off-chance that the user is
1606597c28dSRichard Henderson    writing to R0, re-instate the architectural register.  */
1616597c28dSRichard Henderson #define check_r0_write(reg)             \
1626597c28dSRichard Henderson     do {                                \
1636597c28dSRichard Henderson         if (unlikely(reg == 0)) {       \
1646597c28dSRichard Henderson             cpu_R[0] = cpu_R0;          \
1656597c28dSRichard Henderson         }                               \
1666597c28dSRichard Henderson     } while (0)
1676597c28dSRichard Henderson 
168fcf5ef2aSThomas Huth static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
169fcf5ef2aSThomas Huth {
1701ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
171fcf5ef2aSThomas Huth         return false;
172fcf5ef2aSThomas Huth     }
173fcf5ef2aSThomas Huth 
174fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
1751ffa4bceSEmilio G. Cota     return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
176fcf5ef2aSThomas Huth #else
177fcf5ef2aSThomas Huth     return true;
178fcf5ef2aSThomas Huth #endif
179fcf5ef2aSThomas Huth }
180fcf5ef2aSThomas Huth 
181fcf5ef2aSThomas Huth static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
182fcf5ef2aSThomas Huth {
183fcf5ef2aSThomas Huth     if (use_goto_tb(dc, dest)) {
184fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, dest);
185fcf5ef2aSThomas Huth         tcg_gen_goto_tb(n);
1861ffa4bceSEmilio G. Cota         tcg_gen_exit_tb((uintptr_t)dc->base.tb + n);
187fcf5ef2aSThomas Huth     } else {
188fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, dest);
1891ffa4bceSEmilio G. Cota         if (dc->base.singlestep_enabled) {
190fcf5ef2aSThomas Huth             gen_exception(dc, EXCP_DEBUG);
191fcf5ef2aSThomas Huth         }
192fcf5ef2aSThomas Huth         tcg_gen_exit_tb(0);
193fcf5ef2aSThomas Huth     }
194fcf5ef2aSThomas Huth }
195fcf5ef2aSThomas Huth 
1966da544a6SRichard Henderson static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0)
197fcf5ef2aSThomas Huth {
1981ffa4bceSEmilio G. Cota     target_ulong tmp_pc = dc->base.pc_next + n26 * 4;
199fcf5ef2aSThomas Huth 
200fcf5ef2aSThomas Huth     switch (op0) {
201fcf5ef2aSThomas Huth     case 0x00:     /* l.j */
202fcf5ef2aSThomas Huth         tcg_gen_movi_tl(jmp_pc, tmp_pc);
203fcf5ef2aSThomas Huth         break;
204fcf5ef2aSThomas Huth     case 0x01:     /* l.jal */
2051ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8);
206a8000cb4SRichard Henderson         /* Optimize jal being used to load the PC for PIC.  */
2071ffa4bceSEmilio G. Cota         if (tmp_pc == dc->base.pc_next + 8) {
208a8000cb4SRichard Henderson             return;
209a8000cb4SRichard Henderson         }
210fcf5ef2aSThomas Huth         tcg_gen_movi_tl(jmp_pc, tmp_pc);
211fcf5ef2aSThomas Huth         break;
212fcf5ef2aSThomas Huth     case 0x03:     /* l.bnf */
213fcf5ef2aSThomas Huth     case 0x04:     /* l.bf  */
214fcf5ef2aSThomas Huth         {
2151ffa4bceSEmilio G. Cota             TCGv t_next = tcg_const_tl(dc->base.pc_next + 8);
216784696d1SRichard Henderson             TCGv t_true = tcg_const_tl(tmp_pc);
217784696d1SRichard Henderson             TCGv t_zero = tcg_const_tl(0);
218784696d1SRichard Henderson 
219784696d1SRichard Henderson             tcg_gen_movcond_tl(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
220784696d1SRichard Henderson                                jmp_pc, cpu_sr_f, t_zero, t_true, t_next);
221784696d1SRichard Henderson 
222784696d1SRichard Henderson             tcg_temp_free(t_next);
223784696d1SRichard Henderson             tcg_temp_free(t_true);
224784696d1SRichard Henderson             tcg_temp_free(t_zero);
225fcf5ef2aSThomas Huth         }
226fcf5ef2aSThomas Huth         break;
227fcf5ef2aSThomas Huth     case 0x11:     /* l.jr */
228fcf5ef2aSThomas Huth         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
229fcf5ef2aSThomas Huth         break;
230fcf5ef2aSThomas Huth     case 0x12:     /* l.jalr */
2311ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_R[9], (dc->base.pc_next + 8));
232fcf5ef2aSThomas Huth         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
233fcf5ef2aSThomas Huth         break;
234fcf5ef2aSThomas Huth     default:
235fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
236fcf5ef2aSThomas Huth         break;
237fcf5ef2aSThomas Huth     }
238fcf5ef2aSThomas Huth 
239fcf5ef2aSThomas Huth     dc->delayed_branch = 2;
240fcf5ef2aSThomas Huth }
241fcf5ef2aSThomas Huth 
24297458071SRichard Henderson static void gen_ove_cy(DisasContext *dc)
2439ecaa27eSRichard Henderson {
2440c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
24597458071SRichard Henderson         gen_helper_ove_cy(cpu_env);
2469ecaa27eSRichard Henderson     }
2470c53d734SRichard Henderson }
2489ecaa27eSRichard Henderson 
24997458071SRichard Henderson static void gen_ove_ov(DisasContext *dc)
2509ecaa27eSRichard Henderson {
2510c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
25297458071SRichard Henderson         gen_helper_ove_ov(cpu_env);
2539ecaa27eSRichard Henderson     }
2540c53d734SRichard Henderson }
2559ecaa27eSRichard Henderson 
25697458071SRichard Henderson static void gen_ove_cyov(DisasContext *dc)
2579ecaa27eSRichard Henderson {
2580c53d734SRichard Henderson     if (dc->tb_flags & SR_OVE) {
25997458071SRichard Henderson         gen_helper_ove_cyov(cpu_env);
2609ecaa27eSRichard Henderson     }
2610c53d734SRichard Henderson }
2629ecaa27eSRichard Henderson 
2639ecaa27eSRichard Henderson static void gen_add(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2649ecaa27eSRichard Henderson {
2659ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2669ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2679ecaa27eSRichard Henderson 
26897458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, srcb, t0);
26997458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2709ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
27197458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2729ecaa27eSRichard Henderson     tcg_temp_free(t0);
2739ecaa27eSRichard Henderson 
2749ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2759ecaa27eSRichard Henderson     tcg_temp_free(res);
2769ecaa27eSRichard Henderson 
27797458071SRichard Henderson     gen_ove_cyov(dc);
2789ecaa27eSRichard Henderson }
2799ecaa27eSRichard Henderson 
2809ecaa27eSRichard Henderson static void gen_addc(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2819ecaa27eSRichard Henderson {
2829ecaa27eSRichard Henderson     TCGv t0 = tcg_const_tl(0);
2839ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
2849ecaa27eSRichard Henderson 
28597458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, srca, t0, cpu_sr_cy, t0);
28697458071SRichard Henderson     tcg_gen_add2_tl(res, cpu_sr_cy, res, cpu_sr_cy, srcb, t0);
28797458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, srca, srcb);
2889ecaa27eSRichard Henderson     tcg_gen_xor_tl(t0, res, srcb);
28997458071SRichard Henderson     tcg_gen_andc_tl(cpu_sr_ov, t0, cpu_sr_ov);
2909ecaa27eSRichard Henderson     tcg_temp_free(t0);
2919ecaa27eSRichard Henderson 
2929ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
2939ecaa27eSRichard Henderson     tcg_temp_free(res);
2949ecaa27eSRichard Henderson 
29597458071SRichard Henderson     gen_ove_cyov(dc);
2969ecaa27eSRichard Henderson }
2979ecaa27eSRichard Henderson 
2989ecaa27eSRichard Henderson static void gen_sub(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
2999ecaa27eSRichard Henderson {
3009ecaa27eSRichard Henderson     TCGv res = tcg_temp_new();
3019ecaa27eSRichard Henderson 
3029ecaa27eSRichard Henderson     tcg_gen_sub_tl(res, srca, srcb);
30397458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_cy, srca, srcb);
30497458071SRichard Henderson     tcg_gen_xor_tl(cpu_sr_ov, res, srcb);
30597458071SRichard Henderson     tcg_gen_and_tl(cpu_sr_ov, cpu_sr_ov, cpu_sr_cy);
30697458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_cy, srca, srcb);
3079ecaa27eSRichard Henderson 
3089ecaa27eSRichard Henderson     tcg_gen_mov_tl(dest, res);
3099ecaa27eSRichard Henderson     tcg_temp_free(res);
3109ecaa27eSRichard Henderson 
31197458071SRichard Henderson     gen_ove_cyov(dc);
3129ecaa27eSRichard Henderson }
3139ecaa27eSRichard Henderson 
3149ecaa27eSRichard Henderson static void gen_mul(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3159ecaa27eSRichard Henderson {
3169ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3179ecaa27eSRichard Henderson 
31897458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_ov, srca, srcb);
3199ecaa27eSRichard Henderson     tcg_gen_sari_tl(t0, dest, TARGET_LONG_BITS - 1);
32097458071SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_ov, cpu_sr_ov, t0);
3219ecaa27eSRichard Henderson     tcg_temp_free(t0);
3229ecaa27eSRichard Henderson 
32397458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
32497458071SRichard Henderson     gen_ove_ov(dc);
3259ecaa27eSRichard Henderson }
3269ecaa27eSRichard Henderson 
3279ecaa27eSRichard Henderson static void gen_mulu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3289ecaa27eSRichard Henderson {
32997458071SRichard Henderson     tcg_gen_muls2_tl(dest, cpu_sr_cy, srca, srcb);
33097458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_cy, cpu_sr_cy, 0);
3319ecaa27eSRichard Henderson 
33297458071SRichard Henderson     gen_ove_cy(dc);
3339ecaa27eSRichard Henderson }
3349ecaa27eSRichard Henderson 
3359ecaa27eSRichard Henderson static void gen_div(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3369ecaa27eSRichard Henderson {
3379ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3389ecaa27eSRichard Henderson 
33997458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_ov, srcb, 0);
3409ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3419ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
34297458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_ov);
3439ecaa27eSRichard Henderson     tcg_gen_div_tl(dest, srca, t0);
3449ecaa27eSRichard Henderson     tcg_temp_free(t0);
3459ecaa27eSRichard Henderson 
34697458071SRichard Henderson     tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
34797458071SRichard Henderson     gen_ove_ov(dc);
3489ecaa27eSRichard Henderson }
3499ecaa27eSRichard Henderson 
3509ecaa27eSRichard Henderson static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
3519ecaa27eSRichard Henderson {
3529ecaa27eSRichard Henderson     TCGv t0 = tcg_temp_new();
3539ecaa27eSRichard Henderson 
35497458071SRichard Henderson     tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_cy, srcb, 0);
3559ecaa27eSRichard Henderson     /* The result of divide-by-zero is undefined.
3569ecaa27eSRichard Henderson        Supress the host-side exception by dividing by 1.  */
35797458071SRichard Henderson     tcg_gen_or_tl(t0, srcb, cpu_sr_cy);
3589ecaa27eSRichard Henderson     tcg_gen_divu_tl(dest, srca, t0);
3599ecaa27eSRichard Henderson     tcg_temp_free(t0);
3609ecaa27eSRichard Henderson 
36197458071SRichard Henderson     gen_ove_cy(dc);
3629ecaa27eSRichard Henderson }
363fcf5ef2aSThomas Huth 
364cc5de49eSRichard Henderson static void gen_muld(DisasContext *dc, TCGv srca, TCGv srcb)
365cc5de49eSRichard Henderson {
366cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
367cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
368cc5de49eSRichard Henderson 
369cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
370cc5de49eSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
371cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
372cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
373cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_ov, 0);
374cc5de49eSRichard Henderson     } else {
375cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
376cc5de49eSRichard Henderson 
377cc5de49eSRichard Henderson         tcg_gen_muls2_i64(cpu_mac, high, t1, t2);
378cc5de49eSRichard Henderson         tcg_gen_sari_i64(t1, cpu_mac, 63);
379cc5de49eSRichard Henderson         tcg_gen_setcond_i64(TCG_COND_NE, t1, t1, high);
380cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
381cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_ov, t1);
382cc5de49eSRichard Henderson         tcg_gen_neg_tl(cpu_sr_ov, cpu_sr_ov);
383cc5de49eSRichard Henderson 
384cc5de49eSRichard Henderson         gen_ove_ov(dc);
385cc5de49eSRichard Henderson     }
386cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
387cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
388cc5de49eSRichard Henderson }
389cc5de49eSRichard Henderson 
390cc5de49eSRichard Henderson static void gen_muldu(DisasContext *dc, TCGv srca, TCGv srcb)
391cc5de49eSRichard Henderson {
392cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
393cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
394cc5de49eSRichard Henderson 
395cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
396cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
397cc5de49eSRichard Henderson     if (TARGET_LONG_BITS == 32) {
398cc5de49eSRichard Henderson         tcg_gen_mul_i64(cpu_mac, t1, t2);
399cc5de49eSRichard Henderson         tcg_gen_movi_tl(cpu_sr_cy, 0);
400cc5de49eSRichard Henderson     } else {
401cc5de49eSRichard Henderson         TCGv_i64 high = tcg_temp_new_i64();
402cc5de49eSRichard Henderson 
403cc5de49eSRichard Henderson         tcg_gen_mulu2_i64(cpu_mac, high, t1, t2);
404cc5de49eSRichard Henderson         tcg_gen_setcondi_i64(TCG_COND_NE, high, high, 0);
405cc5de49eSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_sr_cy, high);
406cc5de49eSRichard Henderson         tcg_temp_free_i64(high);
407cc5de49eSRichard Henderson 
408cc5de49eSRichard Henderson         gen_ove_cy(dc);
409cc5de49eSRichard Henderson     }
410cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
411cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
412cc5de49eSRichard Henderson }
413cc5de49eSRichard Henderson 
4146f7332baSRichard Henderson static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
4156f7332baSRichard Henderson {
4166f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4176f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4186f7332baSRichard Henderson 
4196f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4206f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4216f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4226f7332baSRichard Henderson 
4236f7332baSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
4246f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4256f7332baSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
4266f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4276f7332baSRichard Henderson     tcg_gen_andc_i64(t1, t1, t2);
4286f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4296f7332baSRichard Henderson 
4306f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4316f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4326f7332baSRichard Henderson #else
4336f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4346f7332baSRichard Henderson #endif
4356f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4366f7332baSRichard Henderson 
4376f7332baSRichard Henderson     gen_ove_ov(dc);
4386f7332baSRichard Henderson }
4396f7332baSRichard Henderson 
440cc5de49eSRichard Henderson static void gen_macu(DisasContext *dc, TCGv srca, TCGv srcb)
441cc5de49eSRichard Henderson {
442cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
443cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
444cc5de49eSRichard Henderson 
445cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
446cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
447cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
448cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
449cc5de49eSRichard Henderson 
450cc5de49eSRichard Henderson     /* Note that overflow is only computed during addition stage.  */
451cc5de49eSRichard Henderson     tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
452cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t1, cpu_mac, t1);
453cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t1);
454cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
455cc5de49eSRichard Henderson 
456cc5de49eSRichard Henderson     gen_ove_cy(dc);
457cc5de49eSRichard Henderson }
458cc5de49eSRichard Henderson 
4596f7332baSRichard Henderson static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
4606f7332baSRichard Henderson {
4616f7332baSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
4626f7332baSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
4636f7332baSRichard Henderson 
4646f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t1, srca);
4656f7332baSRichard Henderson     tcg_gen_ext_tl_i64(t2, srcb);
4666f7332baSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
4676f7332baSRichard Henderson 
4686f7332baSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
4696f7332baSRichard Henderson     tcg_gen_xor_i64(t2, cpu_mac, t1);
4706f7332baSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
4716f7332baSRichard Henderson     tcg_gen_xor_i64(t1, t1, cpu_mac);
4726f7332baSRichard Henderson     tcg_gen_and_i64(t1, t1, t2);
4736f7332baSRichard Henderson     tcg_temp_free_i64(t2);
4746f7332baSRichard Henderson 
4756f7332baSRichard Henderson #if TARGET_LONG_BITS == 32
4766f7332baSRichard Henderson     tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
4776f7332baSRichard Henderson #else
4786f7332baSRichard Henderson     tcg_gen_mov_i64(cpu_sr_ov, t1);
4796f7332baSRichard Henderson #endif
4806f7332baSRichard Henderson     tcg_temp_free_i64(t1);
4816f7332baSRichard Henderson 
4826f7332baSRichard Henderson     gen_ove_ov(dc);
4836f7332baSRichard Henderson }
4846f7332baSRichard Henderson 
485cc5de49eSRichard Henderson static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
486cc5de49eSRichard Henderson {
487cc5de49eSRichard Henderson     TCGv_i64 t1 = tcg_temp_new_i64();
488cc5de49eSRichard Henderson     TCGv_i64 t2 = tcg_temp_new_i64();
489cc5de49eSRichard Henderson 
490cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t1, srca);
491cc5de49eSRichard Henderson     tcg_gen_extu_tl_i64(t2, srcb);
492cc5de49eSRichard Henderson     tcg_gen_mul_i64(t1, t1, t2);
493cc5de49eSRichard Henderson 
494cc5de49eSRichard Henderson     /* Note that overflow is only computed during subtraction stage.  */
495cc5de49eSRichard Henderson     tcg_gen_setcond_i64(TCG_COND_LTU, t2, cpu_mac, t1);
496cc5de49eSRichard Henderson     tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
497cc5de49eSRichard Henderson     tcg_gen_trunc_i64_tl(cpu_sr_cy, t2);
498cc5de49eSRichard Henderson     tcg_temp_free_i64(t2);
499cc5de49eSRichard Henderson     tcg_temp_free_i64(t1);
500cc5de49eSRichard Henderson 
501cc5de49eSRichard Henderson     gen_ove_cy(dc);
502cc5de49eSRichard Henderson }
503cc5de49eSRichard Henderson 
504930c3d00SRichard Henderson static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
505930c3d00SRichard Henderson {
506930c3d00SRichard Henderson     TCGv ea = tcg_temp_new();
507930c3d00SRichard Henderson 
508930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
509930c3d00SRichard Henderson     tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
510930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_addr, ea);
511930c3d00SRichard Henderson     tcg_gen_mov_tl(cpu_lock_value, rd);
512930c3d00SRichard Henderson     tcg_temp_free(ea);
513930c3d00SRichard Henderson }
514930c3d00SRichard Henderson 
5156597c28dSRichard Henderson static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs)
516930c3d00SRichard Henderson {
517930c3d00SRichard Henderson     TCGv ea, val;
518930c3d00SRichard Henderson     TCGLabel *lab_fail, *lab_done;
519930c3d00SRichard Henderson 
520930c3d00SRichard Henderson     ea = tcg_temp_new();
521930c3d00SRichard Henderson     tcg_gen_addi_tl(ea, ra, ofs);
522930c3d00SRichard Henderson 
5236597c28dSRichard Henderson     /* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
5246597c28dSRichard Henderson        to cpu_R[0].  Since l.swa is quite often immediately followed by a
5256597c28dSRichard Henderson        branch, don't bother reallocating; finish the TB using the "real" R0.
5266597c28dSRichard Henderson        This also takes care of RB input across the branch.  */
5276597c28dSRichard Henderson     cpu_R[0] = cpu_R0;
5286597c28dSRichard Henderson 
529930c3d00SRichard Henderson     lab_fail = gen_new_label();
530930c3d00SRichard Henderson     lab_done = gen_new_label();
531930c3d00SRichard Henderson     tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
532930c3d00SRichard Henderson     tcg_temp_free(ea);
533930c3d00SRichard Henderson 
534930c3d00SRichard Henderson     val = tcg_temp_new();
535930c3d00SRichard Henderson     tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
5366597c28dSRichard Henderson                               cpu_R[b], dc->mem_idx, MO_TEUL);
53784775c43SRichard Henderson     tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
538930c3d00SRichard Henderson     tcg_temp_free(val);
539930c3d00SRichard Henderson 
540930c3d00SRichard Henderson     tcg_gen_br(lab_done);
541930c3d00SRichard Henderson 
542930c3d00SRichard Henderson     gen_set_label(lab_fail);
54384775c43SRichard Henderson     tcg_gen_movi_tl(cpu_sr_f, 0);
544930c3d00SRichard Henderson 
545930c3d00SRichard Henderson     gen_set_label(lab_done);
546930c3d00SRichard Henderson     tcg_gen_movi_tl(cpu_lock_addr, -1);
547930c3d00SRichard Henderson }
548930c3d00SRichard Henderson 
549fcf5ef2aSThomas Huth static void dec_calc(DisasContext *dc, uint32_t insn)
550fcf5ef2aSThomas Huth {
551fcf5ef2aSThomas Huth     uint32_t op0, op1, op2;
552fcf5ef2aSThomas Huth     uint32_t ra, rb, rd;
553fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 4);
554fcf5ef2aSThomas Huth     op1 = extract32(insn, 8, 2);
555fcf5ef2aSThomas Huth     op2 = extract32(insn, 6, 2);
556fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
557fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
558fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
559fcf5ef2aSThomas Huth 
560fcf5ef2aSThomas Huth     switch (op1) {
561cf2ae442SRichard Henderson     case 0:
562cf2ae442SRichard Henderson         switch (op0) {
563cf2ae442SRichard Henderson         case 0x0: /* l.add */
564fcf5ef2aSThomas Huth             LOG_DIS("l.add r%d, r%d, r%d\n", rd, ra, rb);
5659ecaa27eSRichard Henderson             gen_add(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
566cf2ae442SRichard Henderson             return;
567fcf5ef2aSThomas Huth 
568cf2ae442SRichard Henderson         case 0x1: /* l.addc */
569fcf5ef2aSThomas Huth             LOG_DIS("l.addc r%d, r%d, r%d\n", rd, ra, rb);
5709ecaa27eSRichard Henderson             gen_addc(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
571cf2ae442SRichard Henderson             return;
572fcf5ef2aSThomas Huth 
573cf2ae442SRichard Henderson         case 0x2: /* l.sub */
574fcf5ef2aSThomas Huth             LOG_DIS("l.sub r%d, r%d, r%d\n", rd, ra, rb);
5759ecaa27eSRichard Henderson             gen_sub(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
576cf2ae442SRichard Henderson             return;
577fcf5ef2aSThomas Huth 
578cf2ae442SRichard Henderson         case 0x3: /* l.and */
579fcf5ef2aSThomas Huth             LOG_DIS("l.and r%d, r%d, r%d\n", rd, ra, rb);
580fcf5ef2aSThomas Huth             tcg_gen_and_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
581cf2ae442SRichard Henderson             return;
582fcf5ef2aSThomas Huth 
583cf2ae442SRichard Henderson         case 0x4: /* l.or */
584fcf5ef2aSThomas Huth             LOG_DIS("l.or r%d, r%d, r%d\n", rd, ra, rb);
585fcf5ef2aSThomas Huth             tcg_gen_or_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
586cf2ae442SRichard Henderson             return;
587fcf5ef2aSThomas Huth 
588cf2ae442SRichard Henderson         case 0x5: /* l.xor */
589fcf5ef2aSThomas Huth             LOG_DIS("l.xor r%d, r%d, r%d\n", rd, ra, rb);
590fcf5ef2aSThomas Huth             tcg_gen_xor_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
591cf2ae442SRichard Henderson             return;
592cf2ae442SRichard Henderson 
593cf2ae442SRichard Henderson         case 0x8:
594cf2ae442SRichard Henderson             switch (op2) {
595cf2ae442SRichard Henderson             case 0: /* l.sll */
596cf2ae442SRichard Henderson                 LOG_DIS("l.sll r%d, r%d, r%d\n", rd, ra, rb);
597cf2ae442SRichard Henderson                 tcg_gen_shl_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
598cf2ae442SRichard Henderson                 return;
599cf2ae442SRichard Henderson             case 1: /* l.srl */
600cf2ae442SRichard Henderson                 LOG_DIS("l.srl r%d, r%d, r%d\n", rd, ra, rb);
601cf2ae442SRichard Henderson                 tcg_gen_shr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
602cf2ae442SRichard Henderson                 return;
603cf2ae442SRichard Henderson             case 2: /* l.sra */
604cf2ae442SRichard Henderson                 LOG_DIS("l.sra r%d, r%d, r%d\n", rd, ra, rb);
605cf2ae442SRichard Henderson                 tcg_gen_sar_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
606cf2ae442SRichard Henderson                 return;
607cf2ae442SRichard Henderson             case 3: /* l.ror */
608cf2ae442SRichard Henderson                 LOG_DIS("l.ror r%d, r%d, r%d\n", rd, ra, rb);
609cf2ae442SRichard Henderson                 tcg_gen_rotr_tl(cpu_R[rd], cpu_R[ra], cpu_R[rb]);
610cf2ae442SRichard Henderson                 return;
611fcf5ef2aSThomas Huth             }
612fcf5ef2aSThomas Huth             break;
613fcf5ef2aSThomas Huth 
614cf2ae442SRichard Henderson         case 0xc:
615cf2ae442SRichard Henderson             switch (op2) {
616cf2ae442SRichard Henderson             case 0: /* l.exths */
617cf2ae442SRichard Henderson                 LOG_DIS("l.exths r%d, r%d\n", rd, ra);
618cf2ae442SRichard Henderson                 tcg_gen_ext16s_tl(cpu_R[rd], cpu_R[ra]);
619cf2ae442SRichard Henderson                 return;
620cf2ae442SRichard Henderson             case 1: /* l.extbs */
621cf2ae442SRichard Henderson                 LOG_DIS("l.extbs r%d, r%d\n", rd, ra);
622cf2ae442SRichard Henderson                 tcg_gen_ext8s_tl(cpu_R[rd], cpu_R[ra]);
623cf2ae442SRichard Henderson                 return;
624cf2ae442SRichard Henderson             case 2: /* l.exthz */
625cf2ae442SRichard Henderson                 LOG_DIS("l.exthz r%d, r%d\n", rd, ra);
626cf2ae442SRichard Henderson                 tcg_gen_ext16u_tl(cpu_R[rd], cpu_R[ra]);
627cf2ae442SRichard Henderson                 return;
628cf2ae442SRichard Henderson             case 3: /* l.extbz */
629cf2ae442SRichard Henderson                 LOG_DIS("l.extbz r%d, r%d\n", rd, ra);
630cf2ae442SRichard Henderson                 tcg_gen_ext8u_tl(cpu_R[rd], cpu_R[ra]);
631cf2ae442SRichard Henderson                 return;
632fcf5ef2aSThomas Huth             }
633fcf5ef2aSThomas Huth             break;
634fcf5ef2aSThomas Huth 
635cf2ae442SRichard Henderson         case 0xd:
636cf2ae442SRichard Henderson             switch (op2) {
637cf2ae442SRichard Henderson             case 0: /* l.extws */
638cf2ae442SRichard Henderson                 LOG_DIS("l.extws r%d, r%d\n", rd, ra);
639cf2ae442SRichard Henderson                 tcg_gen_ext32s_tl(cpu_R[rd], cpu_R[ra]);
640cf2ae442SRichard Henderson                 return;
641cf2ae442SRichard Henderson             case 1: /* l.extwz */
642cf2ae442SRichard Henderson                 LOG_DIS("l.extwz r%d, r%d\n", rd, ra);
643cf2ae442SRichard Henderson                 tcg_gen_ext32u_tl(cpu_R[rd], cpu_R[ra]);
644cf2ae442SRichard Henderson                 return;
645fcf5ef2aSThomas Huth             }
646fcf5ef2aSThomas Huth             break;
647fcf5ef2aSThomas Huth 
648cf2ae442SRichard Henderson         case 0xe: /* l.cmov */
649fcf5ef2aSThomas Huth             LOG_DIS("l.cmov r%d, r%d, r%d\n", rd, ra, rb);
650fcf5ef2aSThomas Huth             {
651784696d1SRichard Henderson                 TCGv zero = tcg_const_tl(0);
652784696d1SRichard Henderson                 tcg_gen_movcond_tl(TCG_COND_NE, cpu_R[rd], cpu_sr_f, zero,
653784696d1SRichard Henderson                                    cpu_R[ra], cpu_R[rb]);
654784696d1SRichard Henderson                 tcg_temp_free(zero);
655fcf5ef2aSThomas Huth             }
656cf2ae442SRichard Henderson             return;
657fcf5ef2aSThomas Huth 
658cf2ae442SRichard Henderson         case 0xf: /* l.ff1 */
659fcf5ef2aSThomas Huth             LOG_DIS("l.ff1 r%d, r%d, r%d\n", rd, ra, rb);
660555baef8SRichard Henderson             tcg_gen_ctzi_tl(cpu_R[rd], cpu_R[ra], -1);
661555baef8SRichard Henderson             tcg_gen_addi_tl(cpu_R[rd], cpu_R[rd], 1);
662cf2ae442SRichard Henderson             return;
663cf2ae442SRichard Henderson         }
664fcf5ef2aSThomas Huth         break;
665cf2ae442SRichard Henderson 
666cf2ae442SRichard Henderson     case 1:
667cf2ae442SRichard Henderson         switch (op0) {
668cf2ae442SRichard Henderson         case 0xf: /* l.fl1 */
669fcf5ef2aSThomas Huth             LOG_DIS("l.fl1 r%d, r%d, r%d\n", rd, ra, rb);
670555baef8SRichard Henderson             tcg_gen_clzi_tl(cpu_R[rd], cpu_R[ra], TARGET_LONG_BITS);
671555baef8SRichard Henderson             tcg_gen_subfi_tl(cpu_R[rd], TARGET_LONG_BITS, cpu_R[rd]);
672cf2ae442SRichard Henderson             return;
673fcf5ef2aSThomas Huth         }
674fcf5ef2aSThomas Huth         break;
675fcf5ef2aSThomas Huth 
676cf2ae442SRichard Henderson     case 2:
677fcf5ef2aSThomas Huth         break;
678fcf5ef2aSThomas Huth 
679cf2ae442SRichard Henderson     case 3:
680cf2ae442SRichard Henderson         switch (op0) {
681cf2ae442SRichard Henderson         case 0x6: /* l.mul */
682cf2ae442SRichard Henderson             LOG_DIS("l.mul r%d, r%d, r%d\n", rd, ra, rb);
683cf2ae442SRichard Henderson             gen_mul(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
684cf2ae442SRichard Henderson             return;
685cf2ae442SRichard Henderson 
686cc5de49eSRichard Henderson         case 0x7: /* l.muld */
687cc5de49eSRichard Henderson             LOG_DIS("l.muld r%d, r%d\n", ra, rb);
688cc5de49eSRichard Henderson             gen_muld(dc, cpu_R[ra], cpu_R[rb]);
689cc5de49eSRichard Henderson             break;
690cc5de49eSRichard Henderson 
691cf2ae442SRichard Henderson         case 0x9: /* l.div */
692cf2ae442SRichard Henderson             LOG_DIS("l.div r%d, r%d, r%d\n", rd, ra, rb);
693cf2ae442SRichard Henderson             gen_div(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
694cf2ae442SRichard Henderson             return;
695cf2ae442SRichard Henderson 
696cf2ae442SRichard Henderson         case 0xa: /* l.divu */
697cf2ae442SRichard Henderson             LOG_DIS("l.divu r%d, r%d, r%d\n", rd, ra, rb);
698cf2ae442SRichard Henderson             gen_divu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
699cf2ae442SRichard Henderson             return;
700cf2ae442SRichard Henderson 
701cf2ae442SRichard Henderson         case 0xb: /* l.mulu */
702cf2ae442SRichard Henderson             LOG_DIS("l.mulu r%d, r%d, r%d\n", rd, ra, rb);
703cf2ae442SRichard Henderson             gen_mulu(dc, cpu_R[rd], cpu_R[ra], cpu_R[rb]);
704cf2ae442SRichard Henderson             return;
705cc5de49eSRichard Henderson 
706cc5de49eSRichard Henderson         case 0xc: /* l.muldu */
707cc5de49eSRichard Henderson             LOG_DIS("l.muldu r%d, r%d\n", ra, rb);
708cc5de49eSRichard Henderson             gen_muldu(dc, cpu_R[ra], cpu_R[rb]);
709cc5de49eSRichard Henderson             return;
710fcf5ef2aSThomas Huth         }
711fcf5ef2aSThomas Huth         break;
712fcf5ef2aSThomas Huth     }
713fcf5ef2aSThomas Huth     gen_illegal_exception(dc);
714fcf5ef2aSThomas Huth }
715fcf5ef2aSThomas Huth 
716fcf5ef2aSThomas Huth static void dec_misc(DisasContext *dc, uint32_t insn)
717fcf5ef2aSThomas Huth {
718fcf5ef2aSThomas Huth     uint32_t op0, op1;
719fcf5ef2aSThomas Huth     uint32_t ra, rb, rd;
7206da544a6SRichard Henderson     uint32_t L6, K5, K16, K5_11;
7216da544a6SRichard Henderson     int32_t I16, I5_11, N26;
722fcf5ef2aSThomas Huth     TCGMemOp mop;
7239ecaa27eSRichard Henderson     TCGv t0;
724fcf5ef2aSThomas Huth 
725fcf5ef2aSThomas Huth     op0 = extract32(insn, 26, 6);
726fcf5ef2aSThomas Huth     op1 = extract32(insn, 24, 2);
727fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
728fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
729fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
730fcf5ef2aSThomas Huth     L6 = extract32(insn, 5, 6);
731fcf5ef2aSThomas Huth     K5 = extract32(insn, 0, 5);
7326da544a6SRichard Henderson     K16 = extract32(insn, 0, 16);
7336da544a6SRichard Henderson     I16 = (int16_t)K16;
7346da544a6SRichard Henderson     N26 = sextract32(insn, 0, 26);
7356da544a6SRichard Henderson     K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
7366da544a6SRichard Henderson     I5_11 = (int16_t)K5_11;
737fcf5ef2aSThomas Huth 
738fcf5ef2aSThomas Huth     switch (op0) {
739fcf5ef2aSThomas Huth     case 0x00:    /* l.j */
740fcf5ef2aSThomas Huth         LOG_DIS("l.j %d\n", N26);
741fcf5ef2aSThomas Huth         gen_jump(dc, N26, 0, op0);
742fcf5ef2aSThomas Huth         break;
743fcf5ef2aSThomas Huth 
744fcf5ef2aSThomas Huth     case 0x01:    /* l.jal */
745fcf5ef2aSThomas Huth         LOG_DIS("l.jal %d\n", N26);
746fcf5ef2aSThomas Huth         gen_jump(dc, N26, 0, op0);
747fcf5ef2aSThomas Huth         break;
748fcf5ef2aSThomas Huth 
749fcf5ef2aSThomas Huth     case 0x03:    /* l.bnf */
750fcf5ef2aSThomas Huth         LOG_DIS("l.bnf %d\n", N26);
751fcf5ef2aSThomas Huth         gen_jump(dc, N26, 0, op0);
752fcf5ef2aSThomas Huth         break;
753fcf5ef2aSThomas Huth 
754fcf5ef2aSThomas Huth     case 0x04:    /* l.bf */
755fcf5ef2aSThomas Huth         LOG_DIS("l.bf %d\n", N26);
756fcf5ef2aSThomas Huth         gen_jump(dc, N26, 0, op0);
757fcf5ef2aSThomas Huth         break;
758fcf5ef2aSThomas Huth 
759fcf5ef2aSThomas Huth     case 0x05:
760fcf5ef2aSThomas Huth         switch (op1) {
761fcf5ef2aSThomas Huth         case 0x01:    /* l.nop */
762fcf5ef2aSThomas Huth             LOG_DIS("l.nop %d\n", I16);
763fcf5ef2aSThomas Huth             break;
764fcf5ef2aSThomas Huth 
765fcf5ef2aSThomas Huth         default:
766fcf5ef2aSThomas Huth             gen_illegal_exception(dc);
767fcf5ef2aSThomas Huth             break;
768fcf5ef2aSThomas Huth         }
769fcf5ef2aSThomas Huth         break;
770fcf5ef2aSThomas Huth 
771fcf5ef2aSThomas Huth     case 0x11:    /* l.jr */
772fcf5ef2aSThomas Huth         LOG_DIS("l.jr r%d\n", rb);
773fcf5ef2aSThomas Huth          gen_jump(dc, 0, rb, op0);
774fcf5ef2aSThomas Huth          break;
775fcf5ef2aSThomas Huth 
776fcf5ef2aSThomas Huth     case 0x12:    /* l.jalr */
777fcf5ef2aSThomas Huth         LOG_DIS("l.jalr r%d\n", rb);
778fcf5ef2aSThomas Huth         gen_jump(dc, 0, rb, op0);
779fcf5ef2aSThomas Huth         break;
780fcf5ef2aSThomas Huth 
781fcf5ef2aSThomas Huth     case 0x13:    /* l.maci */
7826da544a6SRichard Henderson         LOG_DIS("l.maci r%d, %d\n", ra, I16);
7836f7332baSRichard Henderson         t0 = tcg_const_tl(I16);
7846f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], t0);
7856f7332baSRichard Henderson         tcg_temp_free(t0);
786fcf5ef2aSThomas Huth         break;
787fcf5ef2aSThomas Huth 
788fcf5ef2aSThomas Huth     case 0x09:    /* l.rfe */
789fcf5ef2aSThomas Huth         LOG_DIS("l.rfe\n");
790fcf5ef2aSThomas Huth         {
791fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY)
792fcf5ef2aSThomas Huth             return;
793fcf5ef2aSThomas Huth #else
794fcf5ef2aSThomas Huth             if (dc->mem_idx == MMU_USER_IDX) {
795fcf5ef2aSThomas Huth                 gen_illegal_exception(dc);
796fcf5ef2aSThomas Huth                 return;
797fcf5ef2aSThomas Huth             }
798fcf5ef2aSThomas Huth             gen_helper_rfe(cpu_env);
7991ffa4bceSEmilio G. Cota             dc->base.is_jmp = DISAS_UPDATE;
800fcf5ef2aSThomas Huth #endif
801fcf5ef2aSThomas Huth         }
802fcf5ef2aSThomas Huth         break;
803fcf5ef2aSThomas Huth 
804930c3d00SRichard Henderson     case 0x1b: /* l.lwa */
805930c3d00SRichard Henderson         LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
8066597c28dSRichard Henderson         check_r0_write(rd);
807930c3d00SRichard Henderson         gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
808930c3d00SRichard Henderson         break;
809930c3d00SRichard Henderson 
810fcf5ef2aSThomas Huth     case 0x1c:    /* l.cust1 */
811fcf5ef2aSThomas Huth         LOG_DIS("l.cust1\n");
812fcf5ef2aSThomas Huth         break;
813fcf5ef2aSThomas Huth 
814fcf5ef2aSThomas Huth     case 0x1d:    /* l.cust2 */
815fcf5ef2aSThomas Huth         LOG_DIS("l.cust2\n");
816fcf5ef2aSThomas Huth         break;
817fcf5ef2aSThomas Huth 
818fcf5ef2aSThomas Huth     case 0x1e:    /* l.cust3 */
819fcf5ef2aSThomas Huth         LOG_DIS("l.cust3\n");
820fcf5ef2aSThomas Huth         break;
821fcf5ef2aSThomas Huth 
822fcf5ef2aSThomas Huth     case 0x1f:    /* l.cust4 */
823fcf5ef2aSThomas Huth         LOG_DIS("l.cust4\n");
824fcf5ef2aSThomas Huth         break;
825fcf5ef2aSThomas Huth 
826fcf5ef2aSThomas Huth     case 0x3c:    /* l.cust5 */
827fcf5ef2aSThomas Huth         LOG_DIS("l.cust5 r%d, r%d, r%d, %d, %d\n", rd, ra, rb, L6, K5);
828fcf5ef2aSThomas Huth         break;
829fcf5ef2aSThomas Huth 
830fcf5ef2aSThomas Huth     case 0x3d:    /* l.cust6 */
831fcf5ef2aSThomas Huth         LOG_DIS("l.cust6\n");
832fcf5ef2aSThomas Huth         break;
833fcf5ef2aSThomas Huth 
834fcf5ef2aSThomas Huth     case 0x3e:    /* l.cust7 */
835fcf5ef2aSThomas Huth         LOG_DIS("l.cust7\n");
836fcf5ef2aSThomas Huth         break;
837fcf5ef2aSThomas Huth 
838fcf5ef2aSThomas Huth     case 0x3f:    /* l.cust8 */
839fcf5ef2aSThomas Huth         LOG_DIS("l.cust8\n");
840fcf5ef2aSThomas Huth         break;
841fcf5ef2aSThomas Huth 
842fcf5ef2aSThomas Huth /* not used yet, open it when we need or64.  */
843fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64
844fcf5ef2aSThomas Huth     case 0x20:     l.ld
845fcf5ef2aSThomas Huth         LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
846fcf5ef2aSThomas Huth         check_ob64s(dc);
847fcf5ef2aSThomas Huth         mop = MO_TEQ;
848fcf5ef2aSThomas Huth         goto do_load;
849fcf5ef2aSThomas Huth #endif*/
850fcf5ef2aSThomas Huth 
851fcf5ef2aSThomas Huth     case 0x21:    /* l.lwz */
852fcf5ef2aSThomas Huth         LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
853fcf5ef2aSThomas Huth         mop = MO_TEUL;
854fcf5ef2aSThomas Huth         goto do_load;
855fcf5ef2aSThomas Huth 
856fcf5ef2aSThomas Huth     case 0x22:    /* l.lws */
857fcf5ef2aSThomas Huth         LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
858fcf5ef2aSThomas Huth         mop = MO_TESL;
859fcf5ef2aSThomas Huth         goto do_load;
860fcf5ef2aSThomas Huth 
861fcf5ef2aSThomas Huth     case 0x23:    /* l.lbz */
862fcf5ef2aSThomas Huth         LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
863fcf5ef2aSThomas Huth         mop = MO_UB;
864fcf5ef2aSThomas Huth         goto do_load;
865fcf5ef2aSThomas Huth 
866fcf5ef2aSThomas Huth     case 0x24:    /* l.lbs */
867fcf5ef2aSThomas Huth         LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
868fcf5ef2aSThomas Huth         mop = MO_SB;
869fcf5ef2aSThomas Huth         goto do_load;
870fcf5ef2aSThomas Huth 
871fcf5ef2aSThomas Huth     case 0x25:    /* l.lhz */
872fcf5ef2aSThomas Huth         LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
873fcf5ef2aSThomas Huth         mop = MO_TEUW;
874fcf5ef2aSThomas Huth         goto do_load;
875fcf5ef2aSThomas Huth 
876fcf5ef2aSThomas Huth     case 0x26:    /* l.lhs */
877fcf5ef2aSThomas Huth         LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
878fcf5ef2aSThomas Huth         mop = MO_TESW;
879fcf5ef2aSThomas Huth         goto do_load;
880fcf5ef2aSThomas Huth 
881fcf5ef2aSThomas Huth     do_load:
8826597c28dSRichard Henderson         check_r0_write(rd);
8836597c28dSRichard Henderson         t0 = tcg_temp_new();
8846da544a6SRichard Henderson         tcg_gen_addi_tl(t0, cpu_R[ra], I16);
885fcf5ef2aSThomas Huth         tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
886fcf5ef2aSThomas Huth         tcg_temp_free(t0);
887fcf5ef2aSThomas Huth         break;
888fcf5ef2aSThomas Huth 
889fcf5ef2aSThomas Huth     case 0x27:    /* l.addi */
890fcf5ef2aSThomas Huth         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
8916597c28dSRichard Henderson         check_r0_write(rd);
8929ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
8939ecaa27eSRichard Henderson         gen_add(dc, cpu_R[rd], cpu_R[ra], t0);
8949ecaa27eSRichard Henderson         tcg_temp_free(t0);
895fcf5ef2aSThomas Huth         break;
896fcf5ef2aSThomas Huth 
897fcf5ef2aSThomas Huth     case 0x28:    /* l.addic */
898fcf5ef2aSThomas Huth         LOG_DIS("l.addic r%d, r%d, %d\n", rd, ra, I16);
8996597c28dSRichard Henderson         check_r0_write(rd);
9009ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
9019ecaa27eSRichard Henderson         gen_addc(dc, cpu_R[rd], cpu_R[ra], t0);
9029ecaa27eSRichard Henderson         tcg_temp_free(t0);
903fcf5ef2aSThomas Huth         break;
904fcf5ef2aSThomas Huth 
905fcf5ef2aSThomas Huth     case 0x29:    /* l.andi */
9066da544a6SRichard Henderson         LOG_DIS("l.andi r%d, r%d, %d\n", rd, ra, K16);
9076597c28dSRichard Henderson         check_r0_write(rd);
9086da544a6SRichard Henderson         tcg_gen_andi_tl(cpu_R[rd], cpu_R[ra], K16);
909fcf5ef2aSThomas Huth         break;
910fcf5ef2aSThomas Huth 
911fcf5ef2aSThomas Huth     case 0x2a:    /* l.ori */
9126da544a6SRichard Henderson         LOG_DIS("l.ori r%d, r%d, %d\n", rd, ra, K16);
9136597c28dSRichard Henderson         check_r0_write(rd);
9146da544a6SRichard Henderson         tcg_gen_ori_tl(cpu_R[rd], cpu_R[ra], K16);
915fcf5ef2aSThomas Huth         break;
916fcf5ef2aSThomas Huth 
917fcf5ef2aSThomas Huth     case 0x2b:    /* l.xori */
918fcf5ef2aSThomas Huth         LOG_DIS("l.xori r%d, r%d, %d\n", rd, ra, I16);
9196597c28dSRichard Henderson         check_r0_write(rd);
9206da544a6SRichard Henderson         tcg_gen_xori_tl(cpu_R[rd], cpu_R[ra], I16);
921fcf5ef2aSThomas Huth         break;
922fcf5ef2aSThomas Huth 
923fcf5ef2aSThomas Huth     case 0x2c:    /* l.muli */
924fcf5ef2aSThomas Huth         LOG_DIS("l.muli r%d, r%d, %d\n", rd, ra, I16);
9256597c28dSRichard Henderson         check_r0_write(rd);
9269ecaa27eSRichard Henderson         t0 = tcg_const_tl(I16);
9279ecaa27eSRichard Henderson         gen_mul(dc, cpu_R[rd], cpu_R[ra], t0);
9289ecaa27eSRichard Henderson         tcg_temp_free(t0);
929fcf5ef2aSThomas Huth         break;
930fcf5ef2aSThomas Huth 
931fcf5ef2aSThomas Huth     case 0x2d:    /* l.mfspr */
9326da544a6SRichard Henderson         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, K16);
9336597c28dSRichard Henderson         check_r0_write(rd);
934fcf5ef2aSThomas Huth         {
935fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY)
936fcf5ef2aSThomas Huth             return;
937fcf5ef2aSThomas Huth #else
9386da544a6SRichard Henderson             TCGv_i32 ti = tcg_const_i32(K16);
939fcf5ef2aSThomas Huth             if (dc->mem_idx == MMU_USER_IDX) {
940fcf5ef2aSThomas Huth                 gen_illegal_exception(dc);
941fcf5ef2aSThomas Huth                 return;
942fcf5ef2aSThomas Huth             }
943fcf5ef2aSThomas Huth             gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
944fcf5ef2aSThomas Huth             tcg_temp_free_i32(ti);
945fcf5ef2aSThomas Huth #endif
946fcf5ef2aSThomas Huth         }
947fcf5ef2aSThomas Huth         break;
948fcf5ef2aSThomas Huth 
949fcf5ef2aSThomas Huth     case 0x30:    /* l.mtspr */
9506da544a6SRichard Henderson         LOG_DIS("l.mtspr r%d, r%d, %d\n", ra, rb, K5_11);
951fcf5ef2aSThomas Huth         {
952fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY)
953fcf5ef2aSThomas Huth             return;
954fcf5ef2aSThomas Huth #else
9556da544a6SRichard Henderson             TCGv_i32 im = tcg_const_i32(K5_11);
956fcf5ef2aSThomas Huth             if (dc->mem_idx == MMU_USER_IDX) {
957fcf5ef2aSThomas Huth                 gen_illegal_exception(dc);
958fcf5ef2aSThomas Huth                 return;
959fcf5ef2aSThomas Huth             }
960fcf5ef2aSThomas Huth             gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
961fcf5ef2aSThomas Huth             tcg_temp_free_i32(im);
962fcf5ef2aSThomas Huth #endif
963fcf5ef2aSThomas Huth         }
964fcf5ef2aSThomas Huth         break;
965fcf5ef2aSThomas Huth 
966930c3d00SRichard Henderson     case 0x33: /* l.swa */
9676da544a6SRichard Henderson         LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
9686597c28dSRichard Henderson         gen_swa(dc, rb, cpu_R[ra], I5_11);
969930c3d00SRichard Henderson         break;
970930c3d00SRichard Henderson 
971fcf5ef2aSThomas Huth /* not used yet, open it when we need or64.  */
972fcf5ef2aSThomas Huth /*#ifdef TARGET_OPENRISC64
973fcf5ef2aSThomas Huth     case 0x34:     l.sd
9746da544a6SRichard Henderson         LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
975fcf5ef2aSThomas Huth         check_ob64s(dc);
976fcf5ef2aSThomas Huth         mop = MO_TEQ;
977fcf5ef2aSThomas Huth         goto do_store;
978fcf5ef2aSThomas Huth #endif*/
979fcf5ef2aSThomas Huth 
980fcf5ef2aSThomas Huth     case 0x35:    /* l.sw */
9816da544a6SRichard Henderson         LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
982fcf5ef2aSThomas Huth         mop = MO_TEUL;
983fcf5ef2aSThomas Huth         goto do_store;
984fcf5ef2aSThomas Huth 
985fcf5ef2aSThomas Huth     case 0x36:    /* l.sb */
9866da544a6SRichard Henderson         LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
987fcf5ef2aSThomas Huth         mop = MO_UB;
988fcf5ef2aSThomas Huth         goto do_store;
989fcf5ef2aSThomas Huth 
990fcf5ef2aSThomas Huth     case 0x37:    /* l.sh */
9916da544a6SRichard Henderson         LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
992fcf5ef2aSThomas Huth         mop = MO_TEUW;
993fcf5ef2aSThomas Huth         goto do_store;
994fcf5ef2aSThomas Huth 
995fcf5ef2aSThomas Huth     do_store:
996fcf5ef2aSThomas Huth         {
997fcf5ef2aSThomas Huth             TCGv t0 = tcg_temp_new();
9986da544a6SRichard Henderson             tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
999fcf5ef2aSThomas Huth             tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
1000fcf5ef2aSThomas Huth             tcg_temp_free(t0);
1001fcf5ef2aSThomas Huth         }
1002fcf5ef2aSThomas Huth         break;
1003fcf5ef2aSThomas Huth 
1004fcf5ef2aSThomas Huth     default:
1005fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1006fcf5ef2aSThomas Huth         break;
1007fcf5ef2aSThomas Huth     }
1008fcf5ef2aSThomas Huth }
1009fcf5ef2aSThomas Huth 
1010fcf5ef2aSThomas Huth static void dec_mac(DisasContext *dc, uint32_t insn)
1011fcf5ef2aSThomas Huth {
1012fcf5ef2aSThomas Huth     uint32_t op0;
1013fcf5ef2aSThomas Huth     uint32_t ra, rb;
1014fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 4);
1015fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1016fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
1017fcf5ef2aSThomas Huth 
1018fcf5ef2aSThomas Huth     switch (op0) {
1019fcf5ef2aSThomas Huth     case 0x0001:    /* l.mac */
1020fcf5ef2aSThomas Huth         LOG_DIS("l.mac r%d, r%d\n", ra, rb);
10216f7332baSRichard Henderson         gen_mac(dc, cpu_R[ra], cpu_R[rb]);
1022fcf5ef2aSThomas Huth         break;
1023fcf5ef2aSThomas Huth 
1024fcf5ef2aSThomas Huth     case 0x0002:    /* l.msb */
1025fcf5ef2aSThomas Huth         LOG_DIS("l.msb r%d, r%d\n", ra, rb);
10266f7332baSRichard Henderson         gen_msb(dc, cpu_R[ra], cpu_R[rb]);
1027fcf5ef2aSThomas Huth         break;
1028fcf5ef2aSThomas Huth 
1029cc5de49eSRichard Henderson     case 0x0003:    /* l.macu */
1030cc5de49eSRichard Henderson         LOG_DIS("l.macu r%d, r%d\n", ra, rb);
1031cc5de49eSRichard Henderson         gen_macu(dc, cpu_R[ra], cpu_R[rb]);
1032cc5de49eSRichard Henderson         break;
1033cc5de49eSRichard Henderson 
1034cc5de49eSRichard Henderson     case 0x0004:    /* l.msbu */
1035cc5de49eSRichard Henderson         LOG_DIS("l.msbu r%d, r%d\n", ra, rb);
1036cc5de49eSRichard Henderson         gen_msbu(dc, cpu_R[ra], cpu_R[rb]);
1037cc5de49eSRichard Henderson         break;
1038cc5de49eSRichard Henderson 
1039fcf5ef2aSThomas Huth     default:
1040fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1041fcf5ef2aSThomas Huth         break;
1042fcf5ef2aSThomas Huth    }
1043fcf5ef2aSThomas Huth }
1044fcf5ef2aSThomas Huth 
1045fcf5ef2aSThomas Huth static void dec_logic(DisasContext *dc, uint32_t insn)
1046fcf5ef2aSThomas Huth {
1047fcf5ef2aSThomas Huth     uint32_t op0;
10486da544a6SRichard Henderson     uint32_t rd, ra, L6, S6;
1049fcf5ef2aSThomas Huth     op0 = extract32(insn, 6, 2);
1050fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
1051fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1052fcf5ef2aSThomas Huth     L6 = extract32(insn, 0, 6);
10536da544a6SRichard Henderson     S6 = L6 & (TARGET_LONG_BITS - 1);
1054fcf5ef2aSThomas Huth 
10556597c28dSRichard Henderson     check_r0_write(rd);
1056fcf5ef2aSThomas Huth     switch (op0) {
1057fcf5ef2aSThomas Huth     case 0x00:    /* l.slli */
1058fcf5ef2aSThomas Huth         LOG_DIS("l.slli r%d, r%d, %d\n", rd, ra, L6);
10596da544a6SRichard Henderson         tcg_gen_shli_tl(cpu_R[rd], cpu_R[ra], S6);
1060fcf5ef2aSThomas Huth         break;
1061fcf5ef2aSThomas Huth 
1062fcf5ef2aSThomas Huth     case 0x01:    /* l.srli */
1063fcf5ef2aSThomas Huth         LOG_DIS("l.srli r%d, r%d, %d\n", rd, ra, L6);
10646da544a6SRichard Henderson         tcg_gen_shri_tl(cpu_R[rd], cpu_R[ra], S6);
1065fcf5ef2aSThomas Huth         break;
1066fcf5ef2aSThomas Huth 
1067fcf5ef2aSThomas Huth     case 0x02:    /* l.srai */
1068fcf5ef2aSThomas Huth         LOG_DIS("l.srai r%d, r%d, %d\n", rd, ra, L6);
10696da544a6SRichard Henderson         tcg_gen_sari_tl(cpu_R[rd], cpu_R[ra], S6);
10706da544a6SRichard Henderson         break;
1071fcf5ef2aSThomas Huth 
1072fcf5ef2aSThomas Huth     case 0x03:    /* l.rori */
1073fcf5ef2aSThomas Huth         LOG_DIS("l.rori r%d, r%d, %d\n", rd, ra, L6);
10746da544a6SRichard Henderson         tcg_gen_rotri_tl(cpu_R[rd], cpu_R[ra], S6);
1075fcf5ef2aSThomas Huth         break;
1076fcf5ef2aSThomas Huth 
1077fcf5ef2aSThomas Huth     default:
1078fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1079fcf5ef2aSThomas Huth         break;
1080fcf5ef2aSThomas Huth     }
1081fcf5ef2aSThomas Huth }
1082fcf5ef2aSThomas Huth 
1083fcf5ef2aSThomas Huth static void dec_M(DisasContext *dc, uint32_t insn)
1084fcf5ef2aSThomas Huth {
1085fcf5ef2aSThomas Huth     uint32_t op0;
1086fcf5ef2aSThomas Huth     uint32_t rd;
1087fcf5ef2aSThomas Huth     uint32_t K16;
1088fcf5ef2aSThomas Huth     op0 = extract32(insn, 16, 1);
1089fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
1090fcf5ef2aSThomas Huth     K16 = extract32(insn, 0, 16);
1091fcf5ef2aSThomas Huth 
10926597c28dSRichard Henderson     check_r0_write(rd);
1093fcf5ef2aSThomas Huth     switch (op0) {
1094fcf5ef2aSThomas Huth     case 0x0:    /* l.movhi */
1095fcf5ef2aSThomas Huth         LOG_DIS("l.movhi  r%d, %d\n", rd, K16);
1096fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_R[rd], (K16 << 16));
1097fcf5ef2aSThomas Huth         break;
1098fcf5ef2aSThomas Huth 
1099fcf5ef2aSThomas Huth     case 0x1:    /* l.macrc */
1100fcf5ef2aSThomas Huth         LOG_DIS("l.macrc  r%d\n", rd);
11016f7332baSRichard Henderson         tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
11026f7332baSRichard Henderson         tcg_gen_movi_i64(cpu_mac, 0);
1103fcf5ef2aSThomas Huth         break;
1104fcf5ef2aSThomas Huth 
1105fcf5ef2aSThomas Huth     default:
1106fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1107fcf5ef2aSThomas Huth         break;
1108fcf5ef2aSThomas Huth     }
1109fcf5ef2aSThomas Huth }
1110fcf5ef2aSThomas Huth 
1111fcf5ef2aSThomas Huth static void dec_comp(DisasContext *dc, uint32_t insn)
1112fcf5ef2aSThomas Huth {
1113fcf5ef2aSThomas Huth     uint32_t op0;
1114fcf5ef2aSThomas Huth     uint32_t ra, rb;
1115fcf5ef2aSThomas Huth 
1116fcf5ef2aSThomas Huth     op0 = extract32(insn, 21, 5);
1117fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1118fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
1119fcf5ef2aSThomas Huth 
1120fcf5ef2aSThomas Huth     /* unsigned integers  */
1121fcf5ef2aSThomas Huth     tcg_gen_ext32u_tl(cpu_R[ra], cpu_R[ra]);
1122fcf5ef2aSThomas Huth     tcg_gen_ext32u_tl(cpu_R[rb], cpu_R[rb]);
1123fcf5ef2aSThomas Huth 
1124fcf5ef2aSThomas Huth     switch (op0) {
1125fcf5ef2aSThomas Huth     case 0x0:    /* l.sfeq */
1126fcf5ef2aSThomas Huth         LOG_DIS("l.sfeq  r%d, r%d\n", ra, rb);
112784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1128fcf5ef2aSThomas Huth         break;
1129fcf5ef2aSThomas Huth 
1130fcf5ef2aSThomas Huth     case 0x1:    /* l.sfne */
1131fcf5ef2aSThomas Huth         LOG_DIS("l.sfne  r%d, r%d\n", ra, rb);
113284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1133fcf5ef2aSThomas Huth         break;
1134fcf5ef2aSThomas Huth 
1135fcf5ef2aSThomas Huth     case 0x2:    /* l.sfgtu */
1136fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtu  r%d, r%d\n", ra, rb);
113784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1138fcf5ef2aSThomas Huth         break;
1139fcf5ef2aSThomas Huth 
1140fcf5ef2aSThomas Huth     case 0x3:    /* l.sfgeu */
1141fcf5ef2aSThomas Huth         LOG_DIS("l.sfgeu  r%d, r%d\n", ra, rb);
114284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1143fcf5ef2aSThomas Huth         break;
1144fcf5ef2aSThomas Huth 
1145fcf5ef2aSThomas Huth     case 0x4:    /* l.sfltu */
1146fcf5ef2aSThomas Huth         LOG_DIS("l.sfltu  r%d, r%d\n", ra, rb);
114784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1148fcf5ef2aSThomas Huth         break;
1149fcf5ef2aSThomas Huth 
1150fcf5ef2aSThomas Huth     case 0x5:    /* l.sfleu */
1151fcf5ef2aSThomas Huth         LOG_DIS("l.sfleu  r%d, r%d\n", ra, rb);
115284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1153fcf5ef2aSThomas Huth         break;
1154fcf5ef2aSThomas Huth 
1155fcf5ef2aSThomas Huth     case 0xa:    /* l.sfgts */
1156fcf5ef2aSThomas Huth         LOG_DIS("l.sfgts  r%d, r%d\n", ra, rb);
115784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1158fcf5ef2aSThomas Huth         break;
1159fcf5ef2aSThomas Huth 
1160fcf5ef2aSThomas Huth     case 0xb:    /* l.sfges */
1161fcf5ef2aSThomas Huth         LOG_DIS("l.sfges  r%d, r%d\n", ra, rb);
116284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1163fcf5ef2aSThomas Huth         break;
1164fcf5ef2aSThomas Huth 
1165fcf5ef2aSThomas Huth     case 0xc:    /* l.sflts */
1166fcf5ef2aSThomas Huth         LOG_DIS("l.sflts  r%d, r%d\n", ra, rb);
116784775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1168fcf5ef2aSThomas Huth         break;
1169fcf5ef2aSThomas Huth 
1170fcf5ef2aSThomas Huth     case 0xd:    /* l.sfles */
1171fcf5ef2aSThomas Huth         LOG_DIS("l.sfles  r%d, r%d\n", ra, rb);
117284775c43SRichard Henderson         tcg_gen_setcond_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], cpu_R[rb]);
1173fcf5ef2aSThomas Huth         break;
1174fcf5ef2aSThomas Huth 
1175fcf5ef2aSThomas Huth     default:
1176fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1177fcf5ef2aSThomas Huth         break;
1178fcf5ef2aSThomas Huth     }
1179fcf5ef2aSThomas Huth }
1180fcf5ef2aSThomas Huth 
1181fcf5ef2aSThomas Huth static void dec_compi(DisasContext *dc, uint32_t insn)
1182fcf5ef2aSThomas Huth {
11836da544a6SRichard Henderson     uint32_t op0, ra;
11846da544a6SRichard Henderson     int32_t I16;
1185fcf5ef2aSThomas Huth 
1186fcf5ef2aSThomas Huth     op0 = extract32(insn, 21, 5);
1187fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
11886da544a6SRichard Henderson     I16 = sextract32(insn, 0, 16);
1189fcf5ef2aSThomas Huth 
1190fcf5ef2aSThomas Huth     switch (op0) {
1191fcf5ef2aSThomas Huth     case 0x0:    /* l.sfeqi */
1192fcf5ef2aSThomas Huth         LOG_DIS("l.sfeqi  r%d, %d\n", ra, I16);
119384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_sr_f, cpu_R[ra], I16);
1194fcf5ef2aSThomas Huth         break;
1195fcf5ef2aSThomas Huth 
1196fcf5ef2aSThomas Huth     case 0x1:    /* l.sfnei */
1197fcf5ef2aSThomas Huth         LOG_DIS("l.sfnei  r%d, %d\n", ra, I16);
119884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_sr_f, cpu_R[ra], I16);
1199fcf5ef2aSThomas Huth         break;
1200fcf5ef2aSThomas Huth 
1201fcf5ef2aSThomas Huth     case 0x2:    /* l.sfgtui */
1202fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtui  r%d, %d\n", ra, I16);
120384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GTU, cpu_sr_f, cpu_R[ra], I16);
1204fcf5ef2aSThomas Huth         break;
1205fcf5ef2aSThomas Huth 
1206fcf5ef2aSThomas Huth     case 0x3:    /* l.sfgeui */
1207fcf5ef2aSThomas Huth         LOG_DIS("l.sfgeui  r%d, %d\n", ra, I16);
120884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GEU, cpu_sr_f, cpu_R[ra], I16);
1209fcf5ef2aSThomas Huth         break;
1210fcf5ef2aSThomas Huth 
1211fcf5ef2aSThomas Huth     case 0x4:    /* l.sfltui */
1212fcf5ef2aSThomas Huth         LOG_DIS("l.sfltui  r%d, %d\n", ra, I16);
121384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_sr_f, cpu_R[ra], I16);
1214fcf5ef2aSThomas Huth         break;
1215fcf5ef2aSThomas Huth 
1216fcf5ef2aSThomas Huth     case 0x5:    /* l.sfleui */
1217fcf5ef2aSThomas Huth         LOG_DIS("l.sfleui  r%d, %d\n", ra, I16);
121884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LEU, cpu_sr_f, cpu_R[ra], I16);
1219fcf5ef2aSThomas Huth         break;
1220fcf5ef2aSThomas Huth 
1221fcf5ef2aSThomas Huth     case 0xa:    /* l.sfgtsi */
1222fcf5ef2aSThomas Huth         LOG_DIS("l.sfgtsi  r%d, %d\n", ra, I16);
122384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GT, cpu_sr_f, cpu_R[ra], I16);
1224fcf5ef2aSThomas Huth         break;
1225fcf5ef2aSThomas Huth 
1226fcf5ef2aSThomas Huth     case 0xb:    /* l.sfgesi */
1227fcf5ef2aSThomas Huth         LOG_DIS("l.sfgesi  r%d, %d\n", ra, I16);
122884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_GE, cpu_sr_f, cpu_R[ra], I16);
1229fcf5ef2aSThomas Huth         break;
1230fcf5ef2aSThomas Huth 
1231fcf5ef2aSThomas Huth     case 0xc:    /* l.sfltsi */
1232fcf5ef2aSThomas Huth         LOG_DIS("l.sfltsi  r%d, %d\n", ra, I16);
123384775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LT, cpu_sr_f, cpu_R[ra], I16);
1234fcf5ef2aSThomas Huth         break;
1235fcf5ef2aSThomas Huth 
1236fcf5ef2aSThomas Huth     case 0xd:    /* l.sflesi */
1237fcf5ef2aSThomas Huth         LOG_DIS("l.sflesi  r%d, %d\n", ra, I16);
123884775c43SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_LE, cpu_sr_f, cpu_R[ra], I16);
1239fcf5ef2aSThomas Huth         break;
1240fcf5ef2aSThomas Huth 
1241fcf5ef2aSThomas Huth     default:
1242fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1243fcf5ef2aSThomas Huth         break;
1244fcf5ef2aSThomas Huth     }
1245fcf5ef2aSThomas Huth }
1246fcf5ef2aSThomas Huth 
1247*7de9729fSRichard Henderson static bool trans_l_sys(DisasContext *dc, arg_l_sys *a, uint32_t insn)
1248fcf5ef2aSThomas Huth {
1249*7de9729fSRichard Henderson     LOG_DIS("l.sys %d\n", a->k);
12501ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1251fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_SYSCALL);
12521ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1253*7de9729fSRichard Henderson     return true;
1254*7de9729fSRichard Henderson }
1255fcf5ef2aSThomas Huth 
1256*7de9729fSRichard Henderson static bool trans_l_trap(DisasContext *dc, arg_l_trap *a, uint32_t insn)
1257*7de9729fSRichard Henderson {
1258*7de9729fSRichard Henderson     LOG_DIS("l.trap %d\n", a->k);
12591ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1260fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_TRAP);
12611ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1262*7de9729fSRichard Henderson     return true;
1263*7de9729fSRichard Henderson }
1264fcf5ef2aSThomas Huth 
1265*7de9729fSRichard Henderson static bool trans_l_msync(DisasContext *dc, arg_l_msync *a, uint32_t insn)
1266*7de9729fSRichard Henderson {
1267fcf5ef2aSThomas Huth     LOG_DIS("l.msync\n");
126824fc5c0fSRichard Henderson     tcg_gen_mb(TCG_MO_ALL);
1269*7de9729fSRichard Henderson     return true;
1270fcf5ef2aSThomas Huth }
1271*7de9729fSRichard Henderson 
1272*7de9729fSRichard Henderson static bool trans_l_psync(DisasContext *dc, arg_l_psync *a, uint32_t insn)
1273*7de9729fSRichard Henderson {
1274*7de9729fSRichard Henderson     LOG_DIS("l.psync\n");
1275*7de9729fSRichard Henderson     return true;
1276*7de9729fSRichard Henderson }
1277*7de9729fSRichard Henderson 
1278*7de9729fSRichard Henderson static bool trans_l_csync(DisasContext *dc, arg_l_csync *a, uint32_t insn)
1279*7de9729fSRichard Henderson {
1280*7de9729fSRichard Henderson     LOG_DIS("l.csync\n");
1281*7de9729fSRichard Henderson     return true;
1282fcf5ef2aSThomas Huth }
1283fcf5ef2aSThomas Huth 
1284fcf5ef2aSThomas Huth static void dec_float(DisasContext *dc, uint32_t insn)
1285fcf5ef2aSThomas Huth {
1286fcf5ef2aSThomas Huth     uint32_t op0;
1287fcf5ef2aSThomas Huth     uint32_t ra, rb, rd;
1288fcf5ef2aSThomas Huth     op0 = extract32(insn, 0, 8);
1289fcf5ef2aSThomas Huth     ra = extract32(insn, 16, 5);
1290fcf5ef2aSThomas Huth     rb = extract32(insn, 11, 5);
1291fcf5ef2aSThomas Huth     rd = extract32(insn, 21, 5);
1292fcf5ef2aSThomas Huth 
1293fcf5ef2aSThomas Huth     switch (op0) {
1294fcf5ef2aSThomas Huth     case 0x00: /* lf.add.s */
1295fcf5ef2aSThomas Huth         LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
12966597c28dSRichard Henderson         check_r0_write(rd);
1297fcf5ef2aSThomas Huth         gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
12984e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1299fcf5ef2aSThomas Huth         break;
1300fcf5ef2aSThomas Huth 
1301fcf5ef2aSThomas Huth     case 0x01: /* lf.sub.s */
1302fcf5ef2aSThomas Huth         LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
13036597c28dSRichard Henderson         check_r0_write(rd);
1304fcf5ef2aSThomas Huth         gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13054e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1306fcf5ef2aSThomas Huth         break;
1307fcf5ef2aSThomas Huth 
1308fcf5ef2aSThomas Huth     case 0x02:    /* lf.mul.s */
1309fcf5ef2aSThomas Huth         LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
13106597c28dSRichard Henderson         check_r0_write(rd);
1311fcf5ef2aSThomas Huth         gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13124e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1313fcf5ef2aSThomas Huth         break;
1314fcf5ef2aSThomas Huth 
1315fcf5ef2aSThomas Huth     case 0x03: /* lf.div.s */
1316fcf5ef2aSThomas Huth         LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
13176597c28dSRichard Henderson         check_r0_write(rd);
1318fcf5ef2aSThomas Huth         gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13194e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1320fcf5ef2aSThomas Huth         break;
1321fcf5ef2aSThomas Huth 
1322fcf5ef2aSThomas Huth     case 0x04: /* lf.itof.s */
1323fcf5ef2aSThomas Huth         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
13246597c28dSRichard Henderson         check_r0_write(rd);
1325fcf5ef2aSThomas Huth         gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
13264e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1327fcf5ef2aSThomas Huth         break;
1328fcf5ef2aSThomas Huth 
1329fcf5ef2aSThomas Huth     case 0x05: /* lf.ftoi.s */
1330fcf5ef2aSThomas Huth         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
13316597c28dSRichard Henderson         check_r0_write(rd);
1332fcf5ef2aSThomas Huth         gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
13334e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1334fcf5ef2aSThomas Huth         break;
1335fcf5ef2aSThomas Huth 
1336fcf5ef2aSThomas Huth     case 0x06: /* lf.rem.s */
1337fcf5ef2aSThomas Huth         LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
13386597c28dSRichard Henderson         check_r0_write(rd);
1339fcf5ef2aSThomas Huth         gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13404e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1341fcf5ef2aSThomas Huth         break;
1342fcf5ef2aSThomas Huth 
1343fcf5ef2aSThomas Huth     case 0x07: /* lf.madd.s */
1344fcf5ef2aSThomas Huth         LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
13456597c28dSRichard Henderson         check_r0_write(rd);
1346762e22edSRichard Henderson         gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
1347762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
13484e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1349fcf5ef2aSThomas Huth         break;
1350fcf5ef2aSThomas Huth 
1351fcf5ef2aSThomas Huth     case 0x08: /* lf.sfeq.s */
1352fcf5ef2aSThomas Huth         LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
135384775c43SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13544e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1355fcf5ef2aSThomas Huth         break;
1356fcf5ef2aSThomas Huth 
1357fcf5ef2aSThomas Huth     case 0x09: /* lf.sfne.s */
1358fcf5ef2aSThomas Huth         LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
13594e2d3007SRichard Henderson         gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13604e2d3007SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
13614e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1362fcf5ef2aSThomas Huth         break;
1363fcf5ef2aSThomas Huth 
1364fcf5ef2aSThomas Huth     case 0x0a: /* lf.sfgt.s */
1365fcf5ef2aSThomas Huth         LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
13664e2d3007SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
13674e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1368fcf5ef2aSThomas Huth         break;
1369fcf5ef2aSThomas Huth 
1370fcf5ef2aSThomas Huth     case 0x0b: /* lf.sfge.s */
1371fcf5ef2aSThomas Huth         LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
13724e2d3007SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
13734e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1374fcf5ef2aSThomas Huth         break;
1375fcf5ef2aSThomas Huth 
1376fcf5ef2aSThomas Huth     case 0x0c: /* lf.sflt.s */
1377fcf5ef2aSThomas Huth         LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
137884775c43SRichard Henderson         gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13794e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1380fcf5ef2aSThomas Huth         break;
1381fcf5ef2aSThomas Huth 
1382fcf5ef2aSThomas Huth     case 0x0d: /* lf.sfle.s */
1383fcf5ef2aSThomas Huth         LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
138484775c43SRichard Henderson         gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
13854e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1386fcf5ef2aSThomas Huth         break;
1387fcf5ef2aSThomas Huth 
13884e2d3007SRichard Henderson #ifdef TARGET_OPENRISC64
13894e2d3007SRichard Henderson     case 0x10: /* lf.add.d */
1390fcf5ef2aSThomas Huth         LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
1391fcf5ef2aSThomas Huth         check_of64s(dc);
13926597c28dSRichard Henderson         check_r0_write(rd);
1393fcf5ef2aSThomas Huth         gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
13944e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1395fcf5ef2aSThomas Huth         break;
1396fcf5ef2aSThomas Huth 
13974e2d3007SRichard Henderson     case 0x11: /* lf.sub.d */
1398fcf5ef2aSThomas Huth         LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
1399fcf5ef2aSThomas Huth         check_of64s(dc);
14006597c28dSRichard Henderson         check_r0_write(rd);
1401fcf5ef2aSThomas Huth         gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
14024e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1403fcf5ef2aSThomas Huth         break;
1404fcf5ef2aSThomas Huth 
14054e2d3007SRichard Henderson     case 0x12: /* lf.mul.d */
1406fcf5ef2aSThomas Huth         LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
1407fcf5ef2aSThomas Huth         check_of64s(dc);
14086597c28dSRichard Henderson         check_r0_write(rd);
1409fcf5ef2aSThomas Huth         gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
14104e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1411fcf5ef2aSThomas Huth         break;
1412fcf5ef2aSThomas Huth 
14134e2d3007SRichard Henderson     case 0x13: /* lf.div.d */
1414fcf5ef2aSThomas Huth         LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
1415fcf5ef2aSThomas Huth         check_of64s(dc);
14166597c28dSRichard Henderson         check_r0_write(rd);
1417fcf5ef2aSThomas Huth         gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
14184e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1419fcf5ef2aSThomas Huth         break;
1420fcf5ef2aSThomas Huth 
14214e2d3007SRichard Henderson     case 0x14: /* lf.itof.d */
1422fcf5ef2aSThomas Huth         LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
1423fcf5ef2aSThomas Huth         check_of64s(dc);
14246597c28dSRichard Henderson         check_r0_write(rd);
1425fcf5ef2aSThomas Huth         gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
14264e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1427fcf5ef2aSThomas Huth         break;
1428fcf5ef2aSThomas Huth 
14294e2d3007SRichard Henderson     case 0x15: /* lf.ftoi.d */
1430fcf5ef2aSThomas Huth         LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
1431fcf5ef2aSThomas Huth         check_of64s(dc);
14326597c28dSRichard Henderson         check_r0_write(rd);
1433fcf5ef2aSThomas Huth         gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
14344e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1435fcf5ef2aSThomas Huth         break;
1436fcf5ef2aSThomas Huth 
14374e2d3007SRichard Henderson     case 0x16: /* lf.rem.d */
1438fcf5ef2aSThomas Huth         LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
1439fcf5ef2aSThomas Huth         check_of64s(dc);
14406597c28dSRichard Henderson         check_r0_write(rd);
1441fcf5ef2aSThomas Huth         gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
14424e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1443fcf5ef2aSThomas Huth         break;
1444fcf5ef2aSThomas Huth 
14454e2d3007SRichard Henderson     case 0x17: /* lf.madd.d */
1446fcf5ef2aSThomas Huth         LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
1447fcf5ef2aSThomas Huth         check_of64s(dc);
14486597c28dSRichard Henderson         check_r0_write(rd);
1449762e22edSRichard Henderson         gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
1450762e22edSRichard Henderson                                 cpu_R[ra], cpu_R[rb]);
14514e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1452fcf5ef2aSThomas Huth         break;
1453fcf5ef2aSThomas Huth 
14544e2d3007SRichard Henderson     case 0x18: /* lf.sfeq.d */
1455fcf5ef2aSThomas Huth         LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
1456fcf5ef2aSThomas Huth         check_of64s(dc);
145784775c43SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14584e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1459fcf5ef2aSThomas Huth         break;
1460fcf5ef2aSThomas Huth 
14614e2d3007SRichard Henderson     case 0x1a: /* lf.sfgt.d */
1462fcf5ef2aSThomas Huth         LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
1463fcf5ef2aSThomas Huth         check_of64s(dc);
14644e2d3007SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
14654e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1466fcf5ef2aSThomas Huth         break;
1467fcf5ef2aSThomas Huth 
14684e2d3007SRichard Henderson     case 0x1b: /* lf.sfge.d */
1469fcf5ef2aSThomas Huth         LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
1470fcf5ef2aSThomas Huth         check_of64s(dc);
14714e2d3007SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
14724e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1473fcf5ef2aSThomas Huth         break;
1474fcf5ef2aSThomas Huth 
14754e2d3007SRichard Henderson     case 0x19: /* lf.sfne.d */
1476fcf5ef2aSThomas Huth         LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
1477fcf5ef2aSThomas Huth         check_of64s(dc);
14784e2d3007SRichard Henderson         gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14794e2d3007SRichard Henderson         tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
14804e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1481fcf5ef2aSThomas Huth         break;
1482fcf5ef2aSThomas Huth 
14834e2d3007SRichard Henderson     case 0x1c: /* lf.sflt.d */
1484fcf5ef2aSThomas Huth         LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
1485fcf5ef2aSThomas Huth         check_of64s(dc);
148684775c43SRichard Henderson         gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14874e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1488fcf5ef2aSThomas Huth         break;
1489fcf5ef2aSThomas Huth 
14904e2d3007SRichard Henderson     case 0x1d: /* lf.sfle.d */
1491fcf5ef2aSThomas Huth         LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
1492fcf5ef2aSThomas Huth         check_of64s(dc);
149384775c43SRichard Henderson         gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
14944e2d3007SRichard Henderson         gen_helper_update_fpcsr(cpu_env);
1495fcf5ef2aSThomas Huth         break;
14964e2d3007SRichard Henderson #endif
1497fcf5ef2aSThomas Huth 
1498fcf5ef2aSThomas Huth     default:
1499fcf5ef2aSThomas Huth         gen_illegal_exception(dc);
1500fcf5ef2aSThomas Huth         break;
1501fcf5ef2aSThomas Huth     }
1502fcf5ef2aSThomas Huth }
1503fcf5ef2aSThomas Huth 
1504fcf5ef2aSThomas Huth static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
1505fcf5ef2aSThomas Huth {
1506fcf5ef2aSThomas Huth     uint32_t op0;
1507*7de9729fSRichard Henderson     uint32_t insn = cpu_ldl_code(&cpu->env, dc->base.pc_next);
1508fcf5ef2aSThomas Huth 
1509*7de9729fSRichard Henderson     /* Transition to the auto-generated decoder.  */
1510*7de9729fSRichard Henderson     if (decode(dc, insn)) {
1511*7de9729fSRichard Henderson         return;
1512*7de9729fSRichard Henderson     }
1513*7de9729fSRichard Henderson 
1514*7de9729fSRichard Henderson     op0 = extract32(insn, 26, 6);
1515fcf5ef2aSThomas Huth     switch (op0) {
1516fcf5ef2aSThomas Huth     case 0x06:
1517fcf5ef2aSThomas Huth         dec_M(dc, insn);
1518fcf5ef2aSThomas Huth         break;
1519fcf5ef2aSThomas Huth 
1520fcf5ef2aSThomas Huth     case 0x2e:
1521fcf5ef2aSThomas Huth         dec_logic(dc, insn);
1522fcf5ef2aSThomas Huth         break;
1523fcf5ef2aSThomas Huth 
1524fcf5ef2aSThomas Huth     case 0x2f:
1525fcf5ef2aSThomas Huth         dec_compi(dc, insn);
1526fcf5ef2aSThomas Huth         break;
1527fcf5ef2aSThomas Huth 
1528fcf5ef2aSThomas Huth     case 0x31:
1529fcf5ef2aSThomas Huth         dec_mac(dc, insn);
1530fcf5ef2aSThomas Huth         break;
1531fcf5ef2aSThomas Huth 
1532fcf5ef2aSThomas Huth     case 0x32:
1533fcf5ef2aSThomas Huth         dec_float(dc, insn);
1534fcf5ef2aSThomas Huth         break;
1535fcf5ef2aSThomas Huth 
1536fcf5ef2aSThomas Huth     case 0x38:
1537fcf5ef2aSThomas Huth         dec_calc(dc, insn);
1538fcf5ef2aSThomas Huth         break;
1539fcf5ef2aSThomas Huth 
1540fcf5ef2aSThomas Huth     case 0x39:
1541fcf5ef2aSThomas Huth         dec_comp(dc, insn);
1542fcf5ef2aSThomas Huth         break;
1543fcf5ef2aSThomas Huth 
1544fcf5ef2aSThomas Huth     default:
1545fcf5ef2aSThomas Huth         dec_misc(dc, insn);
1546fcf5ef2aSThomas Huth         break;
1547fcf5ef2aSThomas Huth     }
1548fcf5ef2aSThomas Huth }
1549fcf5ef2aSThomas Huth 
1550a4fd3ec3SEmilio G. Cota static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs)
1551fcf5ef2aSThomas Huth {
1552a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcb, DisasContext, base);
15539c489ea6SLluís Vilanova     CPUOpenRISCState *env = cs->env_ptr;
1554a4fd3ec3SEmilio G. Cota     int bound;
1555fcf5ef2aSThomas Huth 
1556a4fd3ec3SEmilio G. Cota     dc->mem_idx = cpu_mmu_index(env, false);
15571ffa4bceSEmilio G. Cota     dc->tb_flags = dc->base.tb->flags;
1558a01deb36SRichard Henderson     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
1559a4fd3ec3SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
1560a4fd3ec3SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
1561fcf5ef2aSThomas Huth }
1562fcf5ef2aSThomas Huth 
1563a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs)
1564a4fd3ec3SEmilio G. Cota {
1565a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(db, DisasContext, base);
1566fcf5ef2aSThomas Huth 
15676597c28dSRichard Henderson     /* Allow the TCG optimizer to see that R0 == 0,
15686597c28dSRichard Henderson        when it's true, which is the common case.  */
15696597c28dSRichard Henderson     if (dc->tb_flags & TB_FLAGS_R0_0) {
15706597c28dSRichard Henderson         cpu_R[0] = tcg_const_tl(0);
15716597c28dSRichard Henderson     } else {
15726597c28dSRichard Henderson         cpu_R[0] = cpu_R0;
15736597c28dSRichard Henderson     }
1574a4fd3ec3SEmilio G. Cota }
15756597c28dSRichard Henderson 
1576a4fd3ec3SEmilio G. Cota static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
1577a4fd3ec3SEmilio G. Cota {
1578a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1579a4fd3ec3SEmilio G. Cota 
15801ffa4bceSEmilio G. Cota     tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0)
1581a4fd3ec3SEmilio G. Cota                        | (dc->base.num_insns > 1 ? 2 : 0));
1582a4fd3ec3SEmilio G. Cota }
1583fcf5ef2aSThomas Huth 
1584a4fd3ec3SEmilio G. Cota static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
1585a4fd3ec3SEmilio G. Cota                                          const CPUBreakpoint *bp)
1586a4fd3ec3SEmilio G. Cota {
1587a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1588a4fd3ec3SEmilio G. Cota 
15891ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1590fcf5ef2aSThomas Huth     gen_exception(dc, EXCP_DEBUG);
15911ffa4bceSEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1592fcf5ef2aSThomas Huth     /* The address covered by the breakpoint must be included in
1593fcf5ef2aSThomas Huth        [tb->pc, tb->pc + tb->size) in order to for it to be
1594fcf5ef2aSThomas Huth        properly cleared -- thus we increment the PC here so that
1595fcf5ef2aSThomas Huth        the logic setting tb->size below does the right thing.  */
15961ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
1597a4fd3ec3SEmilio G. Cota     return true;
1598fcf5ef2aSThomas Huth }
1599fcf5ef2aSThomas Huth 
1600a4fd3ec3SEmilio G. Cota static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
1601a4fd3ec3SEmilio G. Cota {
1602a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
1603a4fd3ec3SEmilio G. Cota     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1604a4fd3ec3SEmilio G. Cota 
1605fcf5ef2aSThomas Huth     disas_openrisc_insn(dc, cpu);
16061ffa4bceSEmilio G. Cota     dc->base.pc_next += 4;
160724c32852SRichard Henderson 
1608fcf5ef2aSThomas Huth     /* delay slot */
1609fcf5ef2aSThomas Huth     if (dc->delayed_branch) {
1610fcf5ef2aSThomas Huth         dc->delayed_branch--;
1611fcf5ef2aSThomas Huth         if (!dc->delayed_branch) {
1612fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, jmp_pc);
161324c32852SRichard Henderson             tcg_gen_discard_tl(jmp_pc);
16141ffa4bceSEmilio G. Cota             dc->base.is_jmp = DISAS_UPDATE;
1615a4fd3ec3SEmilio G. Cota             return;
1616fcf5ef2aSThomas Huth         }
1617fcf5ef2aSThomas Huth     }
1618a4fd3ec3SEmilio G. Cota }
1619fcf5ef2aSThomas Huth 
1620a4fd3ec3SEmilio G. Cota static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
1621a4fd3ec3SEmilio G. Cota {
1622a4fd3ec3SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
162324c32852SRichard Henderson 
1624a01deb36SRichard Henderson     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
1625a01deb36SRichard Henderson         tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0);
1626a01deb36SRichard Henderson     }
1627a01deb36SRichard Henderson 
16281ffa4bceSEmilio G. Cota     tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4);
16291ffa4bceSEmilio G. Cota     if (dc->base.is_jmp == DISAS_NEXT) {
16301ffa4bceSEmilio G. Cota         dc->base.is_jmp = DISAS_UPDATE;
16311ffa4bceSEmilio G. Cota         tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
1632fcf5ef2aSThomas Huth     }
16331ffa4bceSEmilio G. Cota     if (unlikely(dc->base.singlestep_enabled)) {
1634fcf5ef2aSThomas Huth         gen_exception(dc, EXCP_DEBUG);
1635fcf5ef2aSThomas Huth     } else {
16361ffa4bceSEmilio G. Cota         switch (dc->base.is_jmp) {
1637a4fd3ec3SEmilio G. Cota         case DISAS_TOO_MANY:
16381ffa4bceSEmilio G. Cota             gen_goto_tb(dc, 0, dc->base.pc_next);
1639fcf5ef2aSThomas Huth             break;
16401ffa4bceSEmilio G. Cota         case DISAS_NORETURN:
1641fcf5ef2aSThomas Huth         case DISAS_JUMP:
16421ffa4bceSEmilio G. Cota         case DISAS_TB_JUMP:
1643fcf5ef2aSThomas Huth             break;
1644fcf5ef2aSThomas Huth         case DISAS_UPDATE:
1645fcf5ef2aSThomas Huth             /* indicate that the hash table must be used
1646fcf5ef2aSThomas Huth                to find the next TB */
1647fcf5ef2aSThomas Huth             tcg_gen_exit_tb(0);
1648fcf5ef2aSThomas Huth             break;
1649a4fd3ec3SEmilio G. Cota         default:
1650a4fd3ec3SEmilio G. Cota             g_assert_not_reached();
1651a4fd3ec3SEmilio G. Cota         }
1652fcf5ef2aSThomas Huth     }
1653fcf5ef2aSThomas Huth }
1654fcf5ef2aSThomas Huth 
1655a4fd3ec3SEmilio G. Cota static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
1656a4fd3ec3SEmilio G. Cota {
1657a4fd3ec3SEmilio G. Cota     DisasContext *s = container_of(dcbase, DisasContext, base);
1658fcf5ef2aSThomas Huth 
1659a4fd3ec3SEmilio G. Cota     qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first));
1660a4fd3ec3SEmilio G. Cota     log_target_disas(cs, s->base.pc_first, s->base.tb->size);
1661fcf5ef2aSThomas Huth }
1662a4fd3ec3SEmilio G. Cota 
1663a4fd3ec3SEmilio G. Cota static const TranslatorOps openrisc_tr_ops = {
1664a4fd3ec3SEmilio G. Cota     .init_disas_context = openrisc_tr_init_disas_context,
1665a4fd3ec3SEmilio G. Cota     .tb_start           = openrisc_tr_tb_start,
1666a4fd3ec3SEmilio G. Cota     .insn_start         = openrisc_tr_insn_start,
1667a4fd3ec3SEmilio G. Cota     .breakpoint_check   = openrisc_tr_breakpoint_check,
1668a4fd3ec3SEmilio G. Cota     .translate_insn     = openrisc_tr_translate_insn,
1669a4fd3ec3SEmilio G. Cota     .tb_stop            = openrisc_tr_tb_stop,
1670a4fd3ec3SEmilio G. Cota     .disas_log          = openrisc_tr_disas_log,
1671a4fd3ec3SEmilio G. Cota };
1672a4fd3ec3SEmilio G. Cota 
1673a4fd3ec3SEmilio G. Cota void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
1674a4fd3ec3SEmilio G. Cota {
1675a4fd3ec3SEmilio G. Cota     DisasContext ctx;
1676a4fd3ec3SEmilio G. Cota 
1677a4fd3ec3SEmilio G. Cota     translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb);
1678fcf5ef2aSThomas Huth }
1679fcf5ef2aSThomas Huth 
1680fcf5ef2aSThomas Huth void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
1681fcf5ef2aSThomas Huth                              fprintf_function cpu_fprintf,
1682fcf5ef2aSThomas Huth                              int flags)
1683fcf5ef2aSThomas Huth {
1684fcf5ef2aSThomas Huth     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
1685fcf5ef2aSThomas Huth     CPUOpenRISCState *env = &cpu->env;
1686fcf5ef2aSThomas Huth     int i;
1687fcf5ef2aSThomas Huth 
1688fcf5ef2aSThomas Huth     cpu_fprintf(f, "PC=%08x\n", env->pc);
1689fcf5ef2aSThomas Huth     for (i = 0; i < 32; ++i) {
1690d89e71e8SStafford Horne         cpu_fprintf(f, "R%02d=%08x%c", i, cpu_get_gpr(env, i),
1691fcf5ef2aSThomas Huth                     (i % 4) == 3 ? '\n' : ' ');
1692fcf5ef2aSThomas Huth     }
1693fcf5ef2aSThomas Huth }
1694fcf5ef2aSThomas Huth 
1695fcf5ef2aSThomas Huth void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
1696fcf5ef2aSThomas Huth                           target_ulong *data)
1697fcf5ef2aSThomas Huth {
1698fcf5ef2aSThomas Huth     env->pc = data[0];
1699a01deb36SRichard Henderson     env->dflag = data[1] & 1;
1700a01deb36SRichard Henderson     if (data[1] & 2) {
170124c32852SRichard Henderson         env->ppc = env->pc - 4;
170224c32852SRichard Henderson     }
1703fcf5ef2aSThomas Huth }
1704