Statistics
| Branch: | Revision:

root / target-lm32 / translate.c @ 3991c35e

History | View | Annotate | Download (32.2 kB)

1 17c0fa3d Michael Walle
/*
2 17c0fa3d Michael Walle
 *  LatticeMico32 main translation routines.
3 17c0fa3d Michael Walle
 *
4 17c0fa3d Michael Walle
 *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
5 17c0fa3d Michael Walle
 *
6 17c0fa3d Michael Walle
 * This library is free software; you can redistribute it and/or
7 17c0fa3d Michael Walle
 * modify it under the terms of the GNU Lesser General Public
8 17c0fa3d Michael Walle
 * License as published by the Free Software Foundation; either
9 17c0fa3d Michael Walle
 * version 2 of the License, or (at your option) any later version.
10 17c0fa3d Michael Walle
 *
11 17c0fa3d Michael Walle
 * This library is distributed in the hope that it will be useful,
12 17c0fa3d Michael Walle
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 17c0fa3d Michael Walle
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 17c0fa3d Michael Walle
 * Lesser General Public License for more details.
15 17c0fa3d Michael Walle
 *
16 17c0fa3d Michael Walle
 * You should have received a copy of the GNU Lesser General Public
17 17c0fa3d Michael Walle
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 17c0fa3d Michael Walle
 */
19 17c0fa3d Michael Walle
20 17c0fa3d Michael Walle
#include <stdarg.h>
21 17c0fa3d Michael Walle
#include <stdlib.h>
22 17c0fa3d Michael Walle
#include <stdio.h>
23 17c0fa3d Michael Walle
#include <string.h>
24 17c0fa3d Michael Walle
#include <inttypes.h>
25 17c0fa3d Michael Walle
#include <assert.h>
26 17c0fa3d Michael Walle
27 17c0fa3d Michael Walle
#include "cpu.h"
28 17c0fa3d Michael Walle
#include "exec-all.h"
29 17c0fa3d Michael Walle
#include "disas.h"
30 17c0fa3d Michael Walle
#include "helper.h"
31 17c0fa3d Michael Walle
#include "tcg-op.h"
32 17c0fa3d Michael Walle
#include "qemu-common.h"
33 17c0fa3d Michael Walle
34 17c0fa3d Michael Walle
#include "hw/lm32_pic.h"
35 17c0fa3d Michael Walle
36 17c0fa3d Michael Walle
#define GEN_HELPER 1
37 17c0fa3d Michael Walle
#include "helper.h"
38 17c0fa3d Michael Walle
39 17c0fa3d Michael Walle
#define DISAS_LM32 1
40 17c0fa3d Michael Walle
#if DISAS_LM32
41 17c0fa3d Michael Walle
#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
42 17c0fa3d Michael Walle
#else
43 17c0fa3d Michael Walle
#  define LOG_DIS(...) do { } while (0)
44 17c0fa3d Michael Walle
#endif
45 17c0fa3d Michael Walle
46 17c0fa3d Michael Walle
#define EXTRACT_FIELD(src, start, end) \
47 17c0fa3d Michael Walle
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
48 17c0fa3d Michael Walle
49 17c0fa3d Michael Walle
#define MEM_INDEX 0
50 17c0fa3d Michael Walle
51 17c0fa3d Michael Walle
static TCGv_ptr cpu_env;
52 17c0fa3d Michael Walle
static TCGv cpu_R[32];
53 17c0fa3d Michael Walle
static TCGv cpu_pc;
54 17c0fa3d Michael Walle
static TCGv cpu_ie;
55 17c0fa3d Michael Walle
static TCGv cpu_icc;
56 17c0fa3d Michael Walle
static TCGv cpu_dcc;
57 17c0fa3d Michael Walle
static TCGv cpu_cc;
58 17c0fa3d Michael Walle
static TCGv cpu_cfg;
59 17c0fa3d Michael Walle
static TCGv cpu_eba;
60 17c0fa3d Michael Walle
static TCGv cpu_dc;
61 17c0fa3d Michael Walle
static TCGv cpu_deba;
62 17c0fa3d Michael Walle
static TCGv cpu_bp[4];
63 17c0fa3d Michael Walle
static TCGv cpu_wp[4];
64 17c0fa3d Michael Walle
65 17c0fa3d Michael Walle
#include "gen-icount.h"
66 17c0fa3d Michael Walle
67 17c0fa3d Michael Walle
enum {
68 17c0fa3d Michael Walle
    OP_FMT_RI,
69 17c0fa3d Michael Walle
    OP_FMT_RR,
70 17c0fa3d Michael Walle
    OP_FMT_CR,
71 17c0fa3d Michael Walle
    OP_FMT_I
72 17c0fa3d Michael Walle
};
73 17c0fa3d Michael Walle
74 17c0fa3d Michael Walle
/* This is the state at translation time.  */
75 17c0fa3d Michael Walle
typedef struct DisasContext {
76 17c0fa3d Michael Walle
    CPUState *env;
77 17c0fa3d Michael Walle
    target_ulong pc;
78 17c0fa3d Michael Walle
79 17c0fa3d Michael Walle
    /* Decoder.  */
80 17c0fa3d Michael Walle
    int format;
81 17c0fa3d Michael Walle
    uint32_t ir;
82 17c0fa3d Michael Walle
    uint8_t opcode;
83 17c0fa3d Michael Walle
    uint8_t r0, r1, r2, csr;
84 17c0fa3d Michael Walle
    uint16_t imm5;
85 17c0fa3d Michael Walle
    uint16_t imm16;
86 17c0fa3d Michael Walle
    uint32_t imm26;
87 17c0fa3d Michael Walle
88 17c0fa3d Michael Walle
    unsigned int delayed_branch;
89 17c0fa3d Michael Walle
    unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
90 17c0fa3d Michael Walle
    int is_jmp;
91 17c0fa3d Michael Walle
92 17c0fa3d Michael Walle
    int nr_nops;
93 17c0fa3d Michael Walle
    struct TranslationBlock *tb;
94 17c0fa3d Michael Walle
    int singlestep_enabled;
95 17c0fa3d Michael Walle
} DisasContext;
96 17c0fa3d Michael Walle
97 17c0fa3d Michael Walle
static const char *regnames[] = {
98 17c0fa3d Michael Walle
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
99 17c0fa3d Michael Walle
    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
100 17c0fa3d Michael Walle
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
101 17c0fa3d Michael Walle
    "r24", "r25", "r26/gp", "r27/fp", "r28/sp", "r29/ra",
102 17c0fa3d Michael Walle
    "r30/ea", "r31/ba", "bp0", "bp1", "bp2", "bp3", "wp0",
103 17c0fa3d Michael Walle
    "wp1", "wp2", "wp3"
104 17c0fa3d Michael Walle
};
105 17c0fa3d Michael Walle
106 17c0fa3d Michael Walle
static inline int zero_extend(unsigned int val, int width)
107 17c0fa3d Michael Walle
{
108 17c0fa3d Michael Walle
    return val & ((1 << width) - 1);
109 17c0fa3d Michael Walle
}
110 17c0fa3d Michael Walle
111 17c0fa3d Michael Walle
static inline int sign_extend(unsigned int val, int width)
112 17c0fa3d Michael Walle
{
113 17c0fa3d Michael Walle
    int sval;
114 17c0fa3d Michael Walle
115 17c0fa3d Michael Walle
    /* LSL.  */
116 17c0fa3d Michael Walle
    val <<= 32 - width;
117 17c0fa3d Michael Walle
    sval = val;
118 17c0fa3d Michael Walle
    /* ASR.  */
119 17c0fa3d Michael Walle
    sval >>= 32 - width;
120 17c0fa3d Michael Walle
121 17c0fa3d Michael Walle
    return sval;
122 17c0fa3d Michael Walle
}
123 17c0fa3d Michael Walle
124 17c0fa3d Michael Walle
static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
125 17c0fa3d Michael Walle
{
126 17c0fa3d Michael Walle
    TCGv_i32 tmp = tcg_const_i32(index);
127 17c0fa3d Michael Walle
128 17c0fa3d Michael Walle
    gen_helper_raise_exception(tmp);
129 17c0fa3d Michael Walle
    tcg_temp_free_i32(tmp);
130 17c0fa3d Michael Walle
}
131 17c0fa3d Michael Walle
132 17c0fa3d Michael Walle
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
133 17c0fa3d Michael Walle
{
134 17c0fa3d Michael Walle
    TranslationBlock *tb;
135 17c0fa3d Michael Walle
136 17c0fa3d Michael Walle
    tb = dc->tb;
137 17c0fa3d Michael Walle
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
138 17c0fa3d Michael Walle
            likely(!dc->singlestep_enabled)) {
139 17c0fa3d Michael Walle
        tcg_gen_goto_tb(n);
140 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dest);
141 4b4a72e5 Stefan Weil
        tcg_gen_exit_tb((tcg_target_long)tb + n);
142 17c0fa3d Michael Walle
    } else {
143 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dest);
144 17c0fa3d Michael Walle
        if (dc->singlestep_enabled) {
145 17c0fa3d Michael Walle
            t_gen_raise_exception(dc, EXCP_DEBUG);
146 17c0fa3d Michael Walle
        }
147 17c0fa3d Michael Walle
        tcg_gen_exit_tb(0);
148 17c0fa3d Michael Walle
    }
149 17c0fa3d Michael Walle
}
150 17c0fa3d Michael Walle
151 17c0fa3d Michael Walle
static void dec_add(DisasContext *dc)
152 17c0fa3d Michael Walle
{
153 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
154 17c0fa3d Michael Walle
        if (dc->r0 == R_R0) {
155 17c0fa3d Michael Walle
            if (dc->r1 == R_R0 && dc->imm16 == 0) {
156 17c0fa3d Michael Walle
                LOG_DIS("nop\n");
157 17c0fa3d Michael Walle
            } else {
158 17c0fa3d Michael Walle
                LOG_DIS("mvi r%d, %d\n", dc->r1, sign_extend(dc->imm16, 16));
159 17c0fa3d Michael Walle
            }
160 17c0fa3d Michael Walle
        } else {
161 17c0fa3d Michael Walle
            LOG_DIS("addi r%d, r%d, %d\n", dc->r1, dc->r0,
162 17c0fa3d Michael Walle
                    sign_extend(dc->imm16, 16));
163 17c0fa3d Michael Walle
        }
164 17c0fa3d Michael Walle
    } else {
165 17c0fa3d Michael Walle
        LOG_DIS("add r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
166 17c0fa3d Michael Walle
    }
167 17c0fa3d Michael Walle
168 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
169 17c0fa3d Michael Walle
        tcg_gen_addi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
170 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
171 17c0fa3d Michael Walle
    } else {
172 17c0fa3d Michael Walle
        tcg_gen_add_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
173 17c0fa3d Michael Walle
    }
174 17c0fa3d Michael Walle
}
175 17c0fa3d Michael Walle
176 17c0fa3d Michael Walle
static void dec_and(DisasContext *dc)
177 17c0fa3d Michael Walle
{
178 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
179 17c0fa3d Michael Walle
        LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0,
180 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
181 17c0fa3d Michael Walle
    } else {
182 17c0fa3d Michael Walle
        LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
183 17c0fa3d Michael Walle
    }
184 17c0fa3d Michael Walle
185 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
186 17c0fa3d Michael Walle
        tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
187 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
188 17c0fa3d Michael Walle
    } else  {
189 17c0fa3d Michael Walle
        if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) {
190 17c0fa3d Michael Walle
            tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
191 17c0fa3d Michael Walle
            gen_helper_hlt();
192 17c0fa3d Michael Walle
        } else {
193 17c0fa3d Michael Walle
            tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
194 17c0fa3d Michael Walle
        }
195 17c0fa3d Michael Walle
    }
196 17c0fa3d Michael Walle
}
197 17c0fa3d Michael Walle
198 17c0fa3d Michael Walle
static void dec_andhi(DisasContext *dc)
199 17c0fa3d Michael Walle
{
200 17c0fa3d Michael Walle
    LOG_DIS("andhi r%d, r%d, %d\n", dc->r2, dc->r0, dc->imm16);
201 17c0fa3d Michael Walle
202 17c0fa3d Michael Walle
    tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
203 17c0fa3d Michael Walle
}
204 17c0fa3d Michael Walle
205 17c0fa3d Michael Walle
static void dec_b(DisasContext *dc)
206 17c0fa3d Michael Walle
{
207 17c0fa3d Michael Walle
    if (dc->r0 == R_RA) {
208 17c0fa3d Michael Walle
        LOG_DIS("ret\n");
209 17c0fa3d Michael Walle
    } else if (dc->r0 == R_EA) {
210 17c0fa3d Michael Walle
        LOG_DIS("eret\n");
211 17c0fa3d Michael Walle
    } else if (dc->r0 == R_BA) {
212 17c0fa3d Michael Walle
        LOG_DIS("bret\n");
213 17c0fa3d Michael Walle
    } else {
214 17c0fa3d Michael Walle
        LOG_DIS("b r%d\n", dc->r0);
215 17c0fa3d Michael Walle
    }
216 17c0fa3d Michael Walle
217 17c0fa3d Michael Walle
    /* restore IE.IE in case of an eret */
218 17c0fa3d Michael Walle
    if (dc->r0 == R_EA) {
219 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
220 17c0fa3d Michael Walle
        int l1 = gen_new_label();
221 17c0fa3d Michael Walle
        tcg_gen_andi_tl(t0, cpu_ie, IE_EIE);
222 17c0fa3d Michael Walle
        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
223 17c0fa3d Michael Walle
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1);
224 17c0fa3d Michael Walle
        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
225 17c0fa3d Michael Walle
        gen_set_label(l1);
226 17c0fa3d Michael Walle
        tcg_temp_free(t0);
227 17c0fa3d Michael Walle
    } else if (dc->r0 == R_BA) {
228 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
229 17c0fa3d Michael Walle
        int l1 = gen_new_label();
230 17c0fa3d Michael Walle
        tcg_gen_andi_tl(t0, cpu_ie, IE_BIE);
231 17c0fa3d Michael Walle
        tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
232 17c0fa3d Michael Walle
        tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1);
233 17c0fa3d Michael Walle
        tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
234 17c0fa3d Michael Walle
        gen_set_label(l1);
235 17c0fa3d Michael Walle
        tcg_temp_free(t0);
236 17c0fa3d Michael Walle
    }
237 17c0fa3d Michael Walle
    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
238 17c0fa3d Michael Walle
239 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_JUMP;
240 17c0fa3d Michael Walle
}
241 17c0fa3d Michael Walle
242 17c0fa3d Michael Walle
static void dec_bi(DisasContext *dc)
243 17c0fa3d Michael Walle
{
244 17c0fa3d Michael Walle
    LOG_DIS("bi %d\n", sign_extend(dc->imm26 << 2, 26));
245 17c0fa3d Michael Walle
246 17c0fa3d Michael Walle
    gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
247 17c0fa3d Michael Walle
248 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_TB_JUMP;
249 17c0fa3d Michael Walle
}
250 17c0fa3d Michael Walle
251 17c0fa3d Michael Walle
static inline void gen_cond_branch(DisasContext *dc, int cond)
252 17c0fa3d Michael Walle
{
253 17c0fa3d Michael Walle
    int l1;
254 17c0fa3d Michael Walle
255 17c0fa3d Michael Walle
    l1 = gen_new_label();
256 17c0fa3d Michael Walle
    tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1);
257 17c0fa3d Michael Walle
    gen_goto_tb(dc, 0, dc->pc + 4);
258 17c0fa3d Michael Walle
    gen_set_label(l1);
259 17c0fa3d Michael Walle
    gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16)));
260 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_TB_JUMP;
261 17c0fa3d Michael Walle
}
262 17c0fa3d Michael Walle
263 17c0fa3d Michael Walle
static void dec_be(DisasContext *dc)
264 17c0fa3d Michael Walle
{
265 17c0fa3d Michael Walle
    LOG_DIS("be r%d, r%d, %d\n", dc->r0, dc->r1,
266 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16) * 4);
267 17c0fa3d Michael Walle
268 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_EQ);
269 17c0fa3d Michael Walle
}
270 17c0fa3d Michael Walle
271 17c0fa3d Michael Walle
static void dec_bg(DisasContext *dc)
272 17c0fa3d Michael Walle
{
273 17c0fa3d Michael Walle
    LOG_DIS("bg r%d, r%d, %d\n", dc->r0, dc->r1,
274 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16 * 4));
275 17c0fa3d Michael Walle
276 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_GT);
277 17c0fa3d Michael Walle
}
278 17c0fa3d Michael Walle
279 17c0fa3d Michael Walle
static void dec_bge(DisasContext *dc)
280 17c0fa3d Michael Walle
{
281 17c0fa3d Michael Walle
    LOG_DIS("bge r%d, r%d, %d\n", dc->r0, dc->r1,
282 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16) * 4);
283 17c0fa3d Michael Walle
284 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_GE);
285 17c0fa3d Michael Walle
}
286 17c0fa3d Michael Walle
287 17c0fa3d Michael Walle
static void dec_bgeu(DisasContext *dc)
288 17c0fa3d Michael Walle
{
289 17c0fa3d Michael Walle
    LOG_DIS("bgeu r%d, r%d, %d\n", dc->r0, dc->r1,
290 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16) * 4);
291 17c0fa3d Michael Walle
292 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_GEU);
293 17c0fa3d Michael Walle
}
294 17c0fa3d Michael Walle
295 17c0fa3d Michael Walle
static void dec_bgu(DisasContext *dc)
296 17c0fa3d Michael Walle
{
297 17c0fa3d Michael Walle
    LOG_DIS("bgu r%d, r%d, %d\n", dc->r0, dc->r1,
298 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16) * 4);
299 17c0fa3d Michael Walle
300 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_GTU);
301 17c0fa3d Michael Walle
}
302 17c0fa3d Michael Walle
303 17c0fa3d Michael Walle
static void dec_bne(DisasContext *dc)
304 17c0fa3d Michael Walle
{
305 17c0fa3d Michael Walle
    LOG_DIS("bne r%d, r%d, %d\n", dc->r0, dc->r1,
306 17c0fa3d Michael Walle
            sign_extend(dc->imm16, 16) * 4);
307 17c0fa3d Michael Walle
308 17c0fa3d Michael Walle
    gen_cond_branch(dc, TCG_COND_NE);
309 17c0fa3d Michael Walle
}
310 17c0fa3d Michael Walle
311 17c0fa3d Michael Walle
static void dec_call(DisasContext *dc)
312 17c0fa3d Michael Walle
{
313 17c0fa3d Michael Walle
    LOG_DIS("call r%d\n", dc->r0);
314 17c0fa3d Michael Walle
315 17c0fa3d Michael Walle
    tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
316 17c0fa3d Michael Walle
    tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
317 17c0fa3d Michael Walle
318 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_JUMP;
319 17c0fa3d Michael Walle
}
320 17c0fa3d Michael Walle
321 17c0fa3d Michael Walle
static void dec_calli(DisasContext *dc)
322 17c0fa3d Michael Walle
{
323 17c0fa3d Michael Walle
    LOG_DIS("calli %d\n", sign_extend(dc->imm26, 26) * 4);
324 17c0fa3d Michael Walle
325 17c0fa3d Michael Walle
    tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
326 17c0fa3d Michael Walle
    gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
327 17c0fa3d Michael Walle
328 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_TB_JUMP;
329 17c0fa3d Michael Walle
}
330 17c0fa3d Michael Walle
331 17c0fa3d Michael Walle
static inline void gen_compare(DisasContext *dc, int cond)
332 17c0fa3d Michael Walle
{
333 17c0fa3d Michael Walle
    int rX = (dc->format == OP_FMT_RR) ? dc->r2 : dc->r1;
334 17c0fa3d Michael Walle
    int rY = (dc->format == OP_FMT_RR) ? dc->r0 : dc->r0;
335 17c0fa3d Michael Walle
    int rZ = (dc->format == OP_FMT_RR) ? dc->r1 : -1;
336 17c0fa3d Michael Walle
337 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
338 17c0fa3d Michael Walle
        tcg_gen_setcondi_tl(cond, cpu_R[rX], cpu_R[rY],
339 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
340 17c0fa3d Michael Walle
    } else {
341 17c0fa3d Michael Walle
        tcg_gen_setcond_tl(cond, cpu_R[rX], cpu_R[rY], cpu_R[rZ]);
342 17c0fa3d Michael Walle
    }
343 17c0fa3d Michael Walle
}
344 17c0fa3d Michael Walle
345 17c0fa3d Michael Walle
static void dec_cmpe(DisasContext *dc)
346 17c0fa3d Michael Walle
{
347 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
348 17c0fa3d Michael Walle
        LOG_DIS("cmpei r%d, r%d, %d\n", dc->r0, dc->r1,
349 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
350 17c0fa3d Michael Walle
    } else {
351 17c0fa3d Michael Walle
        LOG_DIS("cmpe r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
352 17c0fa3d Michael Walle
    }
353 17c0fa3d Michael Walle
354 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_EQ);
355 17c0fa3d Michael Walle
}
356 17c0fa3d Michael Walle
357 17c0fa3d Michael Walle
static void dec_cmpg(DisasContext *dc)
358 17c0fa3d Michael Walle
{
359 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
360 17c0fa3d Michael Walle
        LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r0, dc->r1,
361 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
362 17c0fa3d Michael Walle
    } else {
363 17c0fa3d Michael Walle
        LOG_DIS("cmpg r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
364 17c0fa3d Michael Walle
    }
365 17c0fa3d Michael Walle
366 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_GT);
367 17c0fa3d Michael Walle
}
368 17c0fa3d Michael Walle
369 17c0fa3d Michael Walle
static void dec_cmpge(DisasContext *dc)
370 17c0fa3d Michael Walle
{
371 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
372 17c0fa3d Michael Walle
        LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r0, dc->r1,
373 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
374 17c0fa3d Michael Walle
    } else {
375 17c0fa3d Michael Walle
        LOG_DIS("cmpge r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
376 17c0fa3d Michael Walle
    }
377 17c0fa3d Michael Walle
378 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_GE);
379 17c0fa3d Michael Walle
}
380 17c0fa3d Michael Walle
381 17c0fa3d Michael Walle
static void dec_cmpgeu(DisasContext *dc)
382 17c0fa3d Michael Walle
{
383 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
384 17c0fa3d Michael Walle
        LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r0, dc->r1,
385 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
386 17c0fa3d Michael Walle
    } else {
387 17c0fa3d Michael Walle
        LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
388 17c0fa3d Michael Walle
    }
389 17c0fa3d Michael Walle
390 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_GEU);
391 17c0fa3d Michael Walle
}
392 17c0fa3d Michael Walle
393 17c0fa3d Michael Walle
static void dec_cmpgu(DisasContext *dc)
394 17c0fa3d Michael Walle
{
395 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
396 17c0fa3d Michael Walle
        LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r0, dc->r1,
397 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
398 17c0fa3d Michael Walle
    } else {
399 17c0fa3d Michael Walle
        LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
400 17c0fa3d Michael Walle
    }
401 17c0fa3d Michael Walle
402 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_GTU);
403 17c0fa3d Michael Walle
}
404 17c0fa3d Michael Walle
405 17c0fa3d Michael Walle
static void dec_cmpne(DisasContext *dc)
406 17c0fa3d Michael Walle
{
407 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
408 17c0fa3d Michael Walle
        LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r0, dc->r1,
409 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
410 17c0fa3d Michael Walle
    } else {
411 17c0fa3d Michael Walle
        LOG_DIS("cmpne r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
412 17c0fa3d Michael Walle
    }
413 17c0fa3d Michael Walle
414 17c0fa3d Michael Walle
    gen_compare(dc, TCG_COND_NE);
415 17c0fa3d Michael Walle
}
416 17c0fa3d Michael Walle
417 17c0fa3d Michael Walle
static void dec_divu(DisasContext *dc)
418 17c0fa3d Michael Walle
{
419 17c0fa3d Michael Walle
    int l1;
420 17c0fa3d Michael Walle
421 17c0fa3d Michael Walle
    LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
422 17c0fa3d Michael Walle
423 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
424 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware divider is not available\n");
425 17c0fa3d Michael Walle
    }
426 17c0fa3d Michael Walle
427 17c0fa3d Michael Walle
    l1 = gen_new_label();
428 17c0fa3d Michael Walle
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
429 17c0fa3d Michael Walle
    tcg_gen_movi_tl(cpu_pc, dc->pc);
430 17c0fa3d Michael Walle
    t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
431 17c0fa3d Michael Walle
    gen_set_label(l1);
432 17c0fa3d Michael Walle
    tcg_gen_divu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
433 17c0fa3d Michael Walle
}
434 17c0fa3d Michael Walle
435 17c0fa3d Michael Walle
static void dec_lb(DisasContext *dc)
436 17c0fa3d Michael Walle
{
437 17c0fa3d Michael Walle
    TCGv t0;
438 17c0fa3d Michael Walle
439 17c0fa3d Michael Walle
    LOG_DIS("lb r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
440 17c0fa3d Michael Walle
441 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
442 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
443 17c0fa3d Michael Walle
    tcg_gen_qemu_ld8s(cpu_R[dc->r1], t0, MEM_INDEX);
444 17c0fa3d Michael Walle
    tcg_temp_free(t0);
445 17c0fa3d Michael Walle
}
446 17c0fa3d Michael Walle
447 17c0fa3d Michael Walle
static void dec_lbu(DisasContext *dc)
448 17c0fa3d Michael Walle
{
449 17c0fa3d Michael Walle
    TCGv t0;
450 17c0fa3d Michael Walle
451 17c0fa3d Michael Walle
    LOG_DIS("lbu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
452 17c0fa3d Michael Walle
453 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
454 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
455 17c0fa3d Michael Walle
    tcg_gen_qemu_ld8u(cpu_R[dc->r1], t0, MEM_INDEX);
456 17c0fa3d Michael Walle
    tcg_temp_free(t0);
457 17c0fa3d Michael Walle
}
458 17c0fa3d Michael Walle
459 17c0fa3d Michael Walle
static void dec_lh(DisasContext *dc)
460 17c0fa3d Michael Walle
{
461 17c0fa3d Michael Walle
    TCGv t0;
462 17c0fa3d Michael Walle
463 17c0fa3d Michael Walle
    LOG_DIS("lh r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
464 17c0fa3d Michael Walle
465 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
466 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
467 17c0fa3d Michael Walle
    tcg_gen_qemu_ld16s(cpu_R[dc->r1], t0, MEM_INDEX);
468 17c0fa3d Michael Walle
    tcg_temp_free(t0);
469 17c0fa3d Michael Walle
}
470 17c0fa3d Michael Walle
471 17c0fa3d Michael Walle
static void dec_lhu(DisasContext *dc)
472 17c0fa3d Michael Walle
{
473 17c0fa3d Michael Walle
    TCGv t0;
474 17c0fa3d Michael Walle
475 17c0fa3d Michael Walle
    LOG_DIS("lhu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
476 17c0fa3d Michael Walle
477 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
478 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
479 17c0fa3d Michael Walle
    tcg_gen_qemu_ld16u(cpu_R[dc->r1], t0, MEM_INDEX);
480 17c0fa3d Michael Walle
    tcg_temp_free(t0);
481 17c0fa3d Michael Walle
}
482 17c0fa3d Michael Walle
483 17c0fa3d Michael Walle
static void dec_lw(DisasContext *dc)
484 17c0fa3d Michael Walle
{
485 17c0fa3d Michael Walle
    TCGv t0;
486 17c0fa3d Michael Walle
487 17c0fa3d Michael Walle
    LOG_DIS("lw r%d, (r%d+%d)\n", dc->r1, dc->r0, sign_extend(dc->imm16, 16));
488 17c0fa3d Michael Walle
489 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
490 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
491 17c0fa3d Michael Walle
    tcg_gen_qemu_ld32s(cpu_R[dc->r1], t0, MEM_INDEX);
492 17c0fa3d Michael Walle
    tcg_temp_free(t0);
493 17c0fa3d Michael Walle
}
494 17c0fa3d Michael Walle
495 17c0fa3d Michael Walle
static void dec_modu(DisasContext *dc)
496 17c0fa3d Michael Walle
{
497 17c0fa3d Michael Walle
    int l1;
498 17c0fa3d Michael Walle
499 17c0fa3d Michael Walle
    LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1);
500 17c0fa3d Michael Walle
501 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
502 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware divider is not available\n");
503 17c0fa3d Michael Walle
    }
504 17c0fa3d Michael Walle
505 17c0fa3d Michael Walle
    l1 = gen_new_label();
506 17c0fa3d Michael Walle
    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
507 17c0fa3d Michael Walle
    tcg_gen_movi_tl(cpu_pc, dc->pc);
508 17c0fa3d Michael Walle
    t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
509 17c0fa3d Michael Walle
    gen_set_label(l1);
510 17c0fa3d Michael Walle
    tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
511 17c0fa3d Michael Walle
}
512 17c0fa3d Michael Walle
513 17c0fa3d Michael Walle
static void dec_mul(DisasContext *dc)
514 17c0fa3d Michael Walle
{
515 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
516 17c0fa3d Michael Walle
        LOG_DIS("muli r%d, r%d, %d\n", dc->r0, dc->r1,
517 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
518 17c0fa3d Michael Walle
    } else {
519 17c0fa3d Michael Walle
        LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
520 17c0fa3d Michael Walle
    }
521 17c0fa3d Michael Walle
522 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_MULTIPLY)) {
523 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware multiplier is not available\n");
524 17c0fa3d Michael Walle
    }
525 17c0fa3d Michael Walle
526 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
527 17c0fa3d Michael Walle
        tcg_gen_muli_tl(cpu_R[dc->r1], cpu_R[dc->r0],
528 17c0fa3d Michael Walle
                sign_extend(dc->imm16, 16));
529 17c0fa3d Michael Walle
    } else {
530 17c0fa3d Michael Walle
        tcg_gen_mul_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
531 17c0fa3d Michael Walle
    }
532 17c0fa3d Michael Walle
}
533 17c0fa3d Michael Walle
534 17c0fa3d Michael Walle
static void dec_nor(DisasContext *dc)
535 17c0fa3d Michael Walle
{
536 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
537 17c0fa3d Michael Walle
        LOG_DIS("nori r%d, r%d, %d\n", dc->r0, dc->r1,
538 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
539 17c0fa3d Michael Walle
    } else {
540 17c0fa3d Michael Walle
        LOG_DIS("nor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
541 17c0fa3d Michael Walle
    }
542 17c0fa3d Michael Walle
543 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
544 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
545 17c0fa3d Michael Walle
        tcg_gen_movi_tl(t0, zero_extend(dc->imm16, 16));
546 17c0fa3d Michael Walle
        tcg_gen_nor_tl(cpu_R[dc->r1], cpu_R[dc->r0], t0);
547 17c0fa3d Michael Walle
        tcg_temp_free(t0);
548 17c0fa3d Michael Walle
    } else {
549 17c0fa3d Michael Walle
        tcg_gen_nor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
550 17c0fa3d Michael Walle
    }
551 17c0fa3d Michael Walle
}
552 17c0fa3d Michael Walle
553 17c0fa3d Michael Walle
static void dec_or(DisasContext *dc)
554 17c0fa3d Michael Walle
{
555 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
556 17c0fa3d Michael Walle
        LOG_DIS("ori r%d, r%d, %d\n", dc->r1, dc->r0,
557 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
558 17c0fa3d Michael Walle
    } else {
559 17c0fa3d Michael Walle
        if (dc->r1 == R_R0) {
560 17c0fa3d Michael Walle
            LOG_DIS("mv r%d, r%d\n", dc->r2, dc->r0);
561 17c0fa3d Michael Walle
        } else {
562 17c0fa3d Michael Walle
            LOG_DIS("or r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
563 17c0fa3d Michael Walle
        }
564 17c0fa3d Michael Walle
    }
565 17c0fa3d Michael Walle
566 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
567 17c0fa3d Michael Walle
        tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
568 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
569 17c0fa3d Michael Walle
    } else {
570 17c0fa3d Michael Walle
        tcg_gen_or_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
571 17c0fa3d Michael Walle
    }
572 17c0fa3d Michael Walle
}
573 17c0fa3d Michael Walle
574 17c0fa3d Michael Walle
static void dec_orhi(DisasContext *dc)
575 17c0fa3d Michael Walle
{
576 17c0fa3d Michael Walle
    if (dc->r0 == R_R0) {
577 17c0fa3d Michael Walle
        LOG_DIS("mvhi r%d, %d\n", dc->r1, dc->imm16);
578 17c0fa3d Michael Walle
    } else {
579 17c0fa3d Michael Walle
        LOG_DIS("orhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16);
580 17c0fa3d Michael Walle
    }
581 17c0fa3d Michael Walle
582 17c0fa3d Michael Walle
    tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
583 17c0fa3d Michael Walle
}
584 17c0fa3d Michael Walle
585 fcda9863 Michael Walle
static void dec_scall(DisasContext *dc)
586 17c0fa3d Michael Walle
{
587 17c0fa3d Michael Walle
    if (dc->imm5 == 7) {
588 17c0fa3d Michael Walle
        LOG_DIS("scall\n");
589 17c0fa3d Michael Walle
    } else if (dc->imm5 == 2) {
590 17c0fa3d Michael Walle
        LOG_DIS("break\n");
591 17c0fa3d Michael Walle
    } else {
592 17c0fa3d Michael Walle
        cpu_abort(dc->env, "invalid opcode\n");
593 17c0fa3d Michael Walle
    }
594 17c0fa3d Michael Walle
595 17c0fa3d Michael Walle
    if (dc->imm5 == 7) {
596 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dc->pc);
597 17c0fa3d Michael Walle
        t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
598 17c0fa3d Michael Walle
    } else {
599 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dc->pc);
600 17c0fa3d Michael Walle
        t_gen_raise_exception(dc, EXCP_BREAKPOINT);
601 17c0fa3d Michael Walle
    }
602 17c0fa3d Michael Walle
}
603 17c0fa3d Michael Walle
604 17c0fa3d Michael Walle
static void dec_rcsr(DisasContext *dc)
605 17c0fa3d Michael Walle
{
606 17c0fa3d Michael Walle
    LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr);
607 17c0fa3d Michael Walle
608 17c0fa3d Michael Walle
    switch (dc->csr) {
609 17c0fa3d Michael Walle
    case CSR_IE:
610 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie);
611 17c0fa3d Michael Walle
        break;
612 17c0fa3d Michael Walle
    case CSR_IM:
613 17c0fa3d Michael Walle
        gen_helper_rcsr_im(cpu_R[dc->r2]);
614 17c0fa3d Michael Walle
        break;
615 17c0fa3d Michael Walle
    case CSR_IP:
616 17c0fa3d Michael Walle
        gen_helper_rcsr_ip(cpu_R[dc->r2]);
617 17c0fa3d Michael Walle
        break;
618 17c0fa3d Michael Walle
    case CSR_CC:
619 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc);
620 17c0fa3d Michael Walle
        break;
621 17c0fa3d Michael Walle
    case CSR_CFG:
622 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg);
623 17c0fa3d Michael Walle
        break;
624 17c0fa3d Michael Walle
    case CSR_EBA:
625 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba);
626 17c0fa3d Michael Walle
        break;
627 17c0fa3d Michael Walle
    case CSR_DC:
628 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc);
629 17c0fa3d Michael Walle
        break;
630 17c0fa3d Michael Walle
    case CSR_DEBA:
631 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba);
632 17c0fa3d Michael Walle
        break;
633 17c0fa3d Michael Walle
    case CSR_JTX:
634 17c0fa3d Michael Walle
        gen_helper_rcsr_jtx(cpu_R[dc->r2]);
635 17c0fa3d Michael Walle
        break;
636 17c0fa3d Michael Walle
    case CSR_JRX:
637 17c0fa3d Michael Walle
        gen_helper_rcsr_jrx(cpu_R[dc->r2]);
638 17c0fa3d Michael Walle
        break;
639 17c0fa3d Michael Walle
    case CSR_ICC:
640 17c0fa3d Michael Walle
    case CSR_DCC:
641 17c0fa3d Michael Walle
    case CSR_BP0:
642 17c0fa3d Michael Walle
    case CSR_BP1:
643 17c0fa3d Michael Walle
    case CSR_BP2:
644 17c0fa3d Michael Walle
    case CSR_BP3:
645 17c0fa3d Michael Walle
    case CSR_WP0:
646 17c0fa3d Michael Walle
    case CSR_WP1:
647 17c0fa3d Michael Walle
    case CSR_WP2:
648 17c0fa3d Michael Walle
    case CSR_WP3:
649 17c0fa3d Michael Walle
        cpu_abort(dc->env, "invalid read access csr=%x\n", dc->csr);
650 17c0fa3d Michael Walle
        break;
651 17c0fa3d Michael Walle
    default:
652 17c0fa3d Michael Walle
        cpu_abort(dc->env, "read_csr: unknown csr=%x\n", dc->csr);
653 17c0fa3d Michael Walle
        break;
654 17c0fa3d Michael Walle
    }
655 17c0fa3d Michael Walle
}
656 17c0fa3d Michael Walle
657 17c0fa3d Michael Walle
static void dec_sb(DisasContext *dc)
658 17c0fa3d Michael Walle
{
659 17c0fa3d Michael Walle
    TCGv t0;
660 17c0fa3d Michael Walle
661 17c0fa3d Michael Walle
    LOG_DIS("sb (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
662 17c0fa3d Michael Walle
663 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
664 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
665 17c0fa3d Michael Walle
    tcg_gen_qemu_st8(cpu_R[dc->r1], t0, MEM_INDEX);
666 17c0fa3d Michael Walle
    tcg_temp_free(t0);
667 17c0fa3d Michael Walle
}
668 17c0fa3d Michael Walle
669 17c0fa3d Michael Walle
static void dec_sextb(DisasContext *dc)
670 17c0fa3d Michael Walle
{
671 17c0fa3d Michael Walle
    LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0);
672 17c0fa3d Michael Walle
673 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
674 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware sign extender is not available\n");
675 17c0fa3d Michael Walle
    }
676 17c0fa3d Michael Walle
677 17c0fa3d Michael Walle
    tcg_gen_ext8s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
678 17c0fa3d Michael Walle
}
679 17c0fa3d Michael Walle
680 17c0fa3d Michael Walle
static void dec_sexth(DisasContext *dc)
681 17c0fa3d Michael Walle
{
682 17c0fa3d Michael Walle
    LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0);
683 17c0fa3d Michael Walle
684 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
685 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware sign extender is not available\n");
686 17c0fa3d Michael Walle
    }
687 17c0fa3d Michael Walle
688 17c0fa3d Michael Walle
    tcg_gen_ext16s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
689 17c0fa3d Michael Walle
}
690 17c0fa3d Michael Walle
691 17c0fa3d Michael Walle
static void dec_sh(DisasContext *dc)
692 17c0fa3d Michael Walle
{
693 17c0fa3d Michael Walle
    TCGv t0;
694 17c0fa3d Michael Walle
695 17c0fa3d Michael Walle
    LOG_DIS("sh (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
696 17c0fa3d Michael Walle
697 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
698 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
699 17c0fa3d Michael Walle
    tcg_gen_qemu_st16(cpu_R[dc->r1], t0, MEM_INDEX);
700 17c0fa3d Michael Walle
    tcg_temp_free(t0);
701 17c0fa3d Michael Walle
}
702 17c0fa3d Michael Walle
703 17c0fa3d Michael Walle
static void dec_sl(DisasContext *dc)
704 17c0fa3d Michael Walle
{
705 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
706 17c0fa3d Michael Walle
        LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
707 17c0fa3d Michael Walle
    } else {
708 17c0fa3d Michael Walle
        LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
709 17c0fa3d Michael Walle
    }
710 17c0fa3d Michael Walle
711 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
712 17c0fa3d Michael Walle
        cpu_abort(dc->env, "hardware shifter is not available\n");
713 17c0fa3d Michael Walle
    }
714 17c0fa3d Michael Walle
715 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
716 17c0fa3d Michael Walle
        tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
717 17c0fa3d Michael Walle
    } else {
718 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
719 17c0fa3d Michael Walle
        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
720 17c0fa3d Michael Walle
        tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
721 17c0fa3d Michael Walle
        tcg_temp_free(t0);
722 17c0fa3d Michael Walle
    }
723 17c0fa3d Michael Walle
}
724 17c0fa3d Michael Walle
725 17c0fa3d Michael Walle
static void dec_sr(DisasContext *dc)
726 17c0fa3d Michael Walle
{
727 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
728 17c0fa3d Michael Walle
        LOG_DIS("sri r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
729 17c0fa3d Michael Walle
    } else {
730 17c0fa3d Michael Walle
        LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
731 17c0fa3d Michael Walle
    }
732 17c0fa3d Michael Walle
733 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
734 17c0fa3d Michael Walle
        if (dc->format == OP_FMT_RI) {
735 17c0fa3d Michael Walle
            /* TODO: check r1 == 1 during runtime */
736 17c0fa3d Michael Walle
        } else {
737 17c0fa3d Michael Walle
            if (dc->imm5 != 1) {
738 17c0fa3d Michael Walle
                cpu_abort(dc->env, "hardware shifter is not available\n");
739 17c0fa3d Michael Walle
            }
740 17c0fa3d Michael Walle
        }
741 17c0fa3d Michael Walle
    }
742 17c0fa3d Michael Walle
743 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
744 17c0fa3d Michael Walle
        tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
745 17c0fa3d Michael Walle
    } else {
746 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
747 17c0fa3d Michael Walle
        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
748 17c0fa3d Michael Walle
        tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
749 17c0fa3d Michael Walle
        tcg_temp_free(t0);
750 17c0fa3d Michael Walle
    }
751 17c0fa3d Michael Walle
}
752 17c0fa3d Michael Walle
753 17c0fa3d Michael Walle
static void dec_sru(DisasContext *dc)
754 17c0fa3d Michael Walle
{
755 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
756 17c0fa3d Michael Walle
        LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
757 17c0fa3d Michael Walle
    } else {
758 17c0fa3d Michael Walle
        LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
759 17c0fa3d Michael Walle
    }
760 17c0fa3d Michael Walle
761 17c0fa3d Michael Walle
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
762 17c0fa3d Michael Walle
        if (dc->format == OP_FMT_RI) {
763 17c0fa3d Michael Walle
            /* TODO: check r1 == 1 during runtime */
764 17c0fa3d Michael Walle
        } else {
765 17c0fa3d Michael Walle
            if (dc->imm5 != 1) {
766 17c0fa3d Michael Walle
                cpu_abort(dc->env, "hardware shifter is not available\n");
767 17c0fa3d Michael Walle
            }
768 17c0fa3d Michael Walle
        }
769 17c0fa3d Michael Walle
    }
770 17c0fa3d Michael Walle
771 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
772 17c0fa3d Michael Walle
        tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
773 17c0fa3d Michael Walle
    } else {
774 17c0fa3d Michael Walle
        TCGv t0 = tcg_temp_new();
775 17c0fa3d Michael Walle
        tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
776 17c0fa3d Michael Walle
        tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
777 17c0fa3d Michael Walle
        tcg_temp_free(t0);
778 17c0fa3d Michael Walle
    }
779 17c0fa3d Michael Walle
}
780 17c0fa3d Michael Walle
781 17c0fa3d Michael Walle
static void dec_sub(DisasContext *dc)
782 17c0fa3d Michael Walle
{
783 17c0fa3d Michael Walle
    LOG_DIS("sub r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
784 17c0fa3d Michael Walle
785 17c0fa3d Michael Walle
    tcg_gen_sub_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
786 17c0fa3d Michael Walle
}
787 17c0fa3d Michael Walle
788 17c0fa3d Michael Walle
static void dec_sw(DisasContext *dc)
789 17c0fa3d Michael Walle
{
790 17c0fa3d Michael Walle
    TCGv t0;
791 17c0fa3d Michael Walle
792 17c0fa3d Michael Walle
    LOG_DIS("sw (r%d+%d), r%d\n", dc->r0, sign_extend(dc->imm16, 16), dc->r1);
793 17c0fa3d Michael Walle
794 17c0fa3d Michael Walle
    t0 = tcg_temp_new();
795 17c0fa3d Michael Walle
    tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
796 17c0fa3d Michael Walle
    tcg_gen_qemu_st32(cpu_R[dc->r1], t0, MEM_INDEX);
797 17c0fa3d Michael Walle
    tcg_temp_free(t0);
798 17c0fa3d Michael Walle
}
799 17c0fa3d Michael Walle
800 17c0fa3d Michael Walle
static void dec_user(DisasContext *dc)
801 17c0fa3d Michael Walle
{
802 17c0fa3d Michael Walle
    LOG_DIS("user");
803 17c0fa3d Michael Walle
804 17c0fa3d Michael Walle
    cpu_abort(dc->env, "user insn undefined\n");
805 17c0fa3d Michael Walle
}
806 17c0fa3d Michael Walle
807 17c0fa3d Michael Walle
static void dec_wcsr(DisasContext *dc)
808 17c0fa3d Michael Walle
{
809 17c0fa3d Michael Walle
    int no;
810 17c0fa3d Michael Walle
811 17c0fa3d Michael Walle
    LOG_DIS("wcsr r%d, %d\n", dc->r1, dc->csr);
812 17c0fa3d Michael Walle
813 17c0fa3d Michael Walle
    switch (dc->csr) {
814 17c0fa3d Michael Walle
    case CSR_IE:
815 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]);
816 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
817 17c0fa3d Michael Walle
        dc->is_jmp = DISAS_UPDATE;
818 17c0fa3d Michael Walle
        break;
819 17c0fa3d Michael Walle
    case CSR_IM:
820 17c0fa3d Michael Walle
        /* mark as an io operation because it could cause an interrupt */
821 17c0fa3d Michael Walle
        if (use_icount) {
822 17c0fa3d Michael Walle
            gen_io_start();
823 17c0fa3d Michael Walle
        }
824 17c0fa3d Michael Walle
        gen_helper_wcsr_im(cpu_R[dc->r1]);
825 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
826 17c0fa3d Michael Walle
        if (use_icount) {
827 17c0fa3d Michael Walle
            gen_io_end();
828 17c0fa3d Michael Walle
        }
829 17c0fa3d Michael Walle
        dc->is_jmp = DISAS_UPDATE;
830 17c0fa3d Michael Walle
        break;
831 17c0fa3d Michael Walle
    case CSR_IP:
832 17c0fa3d Michael Walle
        /* mark as an io operation because it could cause an interrupt */
833 17c0fa3d Michael Walle
        if (use_icount) {
834 17c0fa3d Michael Walle
            gen_io_start();
835 17c0fa3d Michael Walle
        }
836 17c0fa3d Michael Walle
        gen_helper_wcsr_ip(cpu_R[dc->r1]);
837 17c0fa3d Michael Walle
        tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
838 17c0fa3d Michael Walle
        if (use_icount) {
839 17c0fa3d Michael Walle
            gen_io_end();
840 17c0fa3d Michael Walle
        }
841 17c0fa3d Michael Walle
        dc->is_jmp = DISAS_UPDATE;
842 17c0fa3d Michael Walle
        break;
843 17c0fa3d Michael Walle
    case CSR_ICC:
844 17c0fa3d Michael Walle
        /* TODO */
845 17c0fa3d Michael Walle
        break;
846 17c0fa3d Michael Walle
    case CSR_DCC:
847 17c0fa3d Michael Walle
        /* TODO */
848 17c0fa3d Michael Walle
        break;
849 17c0fa3d Michael Walle
    case CSR_EBA:
850 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]);
851 17c0fa3d Michael Walle
        break;
852 17c0fa3d Michael Walle
    case CSR_DEBA:
853 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]);
854 17c0fa3d Michael Walle
        break;
855 17c0fa3d Michael Walle
    case CSR_JTX:
856 17c0fa3d Michael Walle
        gen_helper_wcsr_jtx(cpu_R[dc->r1]);
857 17c0fa3d Michael Walle
        break;
858 17c0fa3d Michael Walle
    case CSR_JRX:
859 17c0fa3d Michael Walle
        gen_helper_wcsr_jrx(cpu_R[dc->r1]);
860 17c0fa3d Michael Walle
        break;
861 17c0fa3d Michael Walle
    case CSR_DC:
862 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_dc, cpu_R[dc->r1]);
863 17c0fa3d Michael Walle
        break;
864 17c0fa3d Michael Walle
    case CSR_BP0:
865 17c0fa3d Michael Walle
    case CSR_BP1:
866 17c0fa3d Michael Walle
    case CSR_BP2:
867 17c0fa3d Michael Walle
    case CSR_BP3:
868 17c0fa3d Michael Walle
        no = dc->csr - CSR_BP0;
869 17c0fa3d Michael Walle
        if (dc->env->num_bps <= no) {
870 17c0fa3d Michael Walle
            cpu_abort(dc->env, "breakpoint #%i is not available\n", no);
871 17c0fa3d Michael Walle
        }
872 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_bp[no], cpu_R[dc->r1]);
873 17c0fa3d Michael Walle
        break;
874 17c0fa3d Michael Walle
    case CSR_WP0:
875 17c0fa3d Michael Walle
    case CSR_WP1:
876 17c0fa3d Michael Walle
    case CSR_WP2:
877 17c0fa3d Michael Walle
    case CSR_WP3:
878 17c0fa3d Michael Walle
        no = dc->csr - CSR_WP0;
879 17c0fa3d Michael Walle
        if (dc->env->num_wps <= no) {
880 17c0fa3d Michael Walle
            cpu_abort(dc->env, "watchpoint #%i is not available\n", no);
881 17c0fa3d Michael Walle
        }
882 17c0fa3d Michael Walle
        tcg_gen_mov_tl(cpu_wp[no], cpu_R[dc->r1]);
883 17c0fa3d Michael Walle
        break;
884 17c0fa3d Michael Walle
    case CSR_CC:
885 17c0fa3d Michael Walle
    case CSR_CFG:
886 17c0fa3d Michael Walle
        cpu_abort(dc->env, "invalid write access csr=%x\n", dc->csr);
887 17c0fa3d Michael Walle
        break;
888 17c0fa3d Michael Walle
    default:
889 17c0fa3d Michael Walle
        cpu_abort(dc->env, "write_csr unknown csr=%x\n", dc->csr);
890 17c0fa3d Michael Walle
        break;
891 17c0fa3d Michael Walle
    }
892 17c0fa3d Michael Walle
}
893 17c0fa3d Michael Walle
894 17c0fa3d Michael Walle
static void dec_xnor(DisasContext *dc)
895 17c0fa3d Michael Walle
{
896 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
897 17c0fa3d Michael Walle
        LOG_DIS("xnori r%d, r%d, %d\n", dc->r0, dc->r1,
898 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
899 17c0fa3d Michael Walle
    } else {
900 17c0fa3d Michael Walle
        if (dc->r1 == R_R0) {
901 17c0fa3d Michael Walle
            LOG_DIS("not r%d, r%d\n", dc->r2, dc->r0);
902 17c0fa3d Michael Walle
        } else {
903 17c0fa3d Michael Walle
            LOG_DIS("xnor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
904 17c0fa3d Michael Walle
        }
905 17c0fa3d Michael Walle
    }
906 17c0fa3d Michael Walle
907 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
908 17c0fa3d Michael Walle
        tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
909 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
910 17c0fa3d Michael Walle
        tcg_gen_not_tl(cpu_R[dc->r1], cpu_R[dc->r1]);
911 17c0fa3d Michael Walle
    } else {
912 17c0fa3d Michael Walle
        tcg_gen_eqv_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
913 17c0fa3d Michael Walle
    }
914 17c0fa3d Michael Walle
}
915 17c0fa3d Michael Walle
916 17c0fa3d Michael Walle
static void dec_xor(DisasContext *dc)
917 17c0fa3d Michael Walle
{
918 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
919 17c0fa3d Michael Walle
        LOG_DIS("xori r%d, r%d, %d\n", dc->r0, dc->r1,
920 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
921 17c0fa3d Michael Walle
    } else {
922 17c0fa3d Michael Walle
        LOG_DIS("xor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
923 17c0fa3d Michael Walle
    }
924 17c0fa3d Michael Walle
925 17c0fa3d Michael Walle
    if (dc->format == OP_FMT_RI) {
926 17c0fa3d Michael Walle
        tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
927 17c0fa3d Michael Walle
                zero_extend(dc->imm16, 16));
928 17c0fa3d Michael Walle
    } else {
929 17c0fa3d Michael Walle
        tcg_gen_xor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
930 17c0fa3d Michael Walle
    }
931 17c0fa3d Michael Walle
}
932 17c0fa3d Michael Walle
933 a5086f95 Michael Walle
static void dec_ill(DisasContext *dc)
934 a5086f95 Michael Walle
{
935 a5086f95 Michael Walle
    cpu_abort(dc->env, "unknown opcode 0x%02x\n", dc->opcode);
936 a5086f95 Michael Walle
}
937 17c0fa3d Michael Walle
938 a5086f95 Michael Walle
typedef void (*DecoderInfo)(DisasContext *dc);
939 17c0fa3d Michael Walle
static const DecoderInfo decinfo[] = {
940 a5086f95 Michael Walle
    dec_sru, dec_nor, dec_mul, dec_sh, dec_lb, dec_sr, dec_xor, dec_lh,
941 a5086f95 Michael Walle
    dec_and, dec_xnor, dec_lw, dec_lhu, dec_sb, dec_add, dec_or, dec_sl,
942 a5086f95 Michael Walle
    dec_lbu, dec_be, dec_bg, dec_bge, dec_bgeu, dec_bgu, dec_sw, dec_bne,
943 a5086f95 Michael Walle
    dec_andhi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_orhi,
944 a5086f95 Michael Walle
    dec_cmpne,
945 a5086f95 Michael Walle
    dec_sru, dec_nor, dec_mul, dec_divu, dec_rcsr, dec_sr, dec_xor, dec_ill,
946 a5086f95 Michael Walle
    dec_and, dec_xnor, dec_ill, dec_scall, dec_sextb, dec_add, dec_or, dec_sl,
947 a5086f95 Michael Walle
    dec_b, dec_modu, dec_sub, dec_user, dec_wcsr, dec_ill, dec_call, dec_sexth,
948 a5086f95 Michael Walle
    dec_bi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_calli,
949 a5086f95 Michael Walle
    dec_cmpne
950 17c0fa3d Michael Walle
};
951 17c0fa3d Michael Walle
952 17c0fa3d Michael Walle
static inline void decode(DisasContext *dc)
953 17c0fa3d Michael Walle
{
954 17c0fa3d Michael Walle
    uint32_t ir;
955 17c0fa3d Michael Walle
956 17c0fa3d Michael Walle
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
957 17c0fa3d Michael Walle
        tcg_gen_debug_insn_start(dc->pc);
958 17c0fa3d Michael Walle
    }
959 17c0fa3d Michael Walle
960 17c0fa3d Michael Walle
    dc->ir = ir = ldl_code(dc->pc);
961 17c0fa3d Michael Walle
    LOG_DIS("%8.8x\t", dc->ir);
962 17c0fa3d Michael Walle
963 17c0fa3d Michael Walle
    /* try guessing 'empty' instruction memory, although it may be a valid
964 17c0fa3d Michael Walle
     * instruction sequence (eg. srui r0, r0, 0) */
965 17c0fa3d Michael Walle
    if (dc->ir) {
966 17c0fa3d Michael Walle
        dc->nr_nops = 0;
967 17c0fa3d Michael Walle
    } else {
968 17c0fa3d Michael Walle
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
969 17c0fa3d Michael Walle
        dc->nr_nops++;
970 17c0fa3d Michael Walle
        if (dc->nr_nops > 4) {
971 17c0fa3d Michael Walle
            cpu_abort(dc->env, "fetching nop sequence\n");
972 17c0fa3d Michael Walle
        }
973 17c0fa3d Michael Walle
    }
974 17c0fa3d Michael Walle
975 17c0fa3d Michael Walle
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
976 17c0fa3d Michael Walle
977 17c0fa3d Michael Walle
    dc->imm5 = EXTRACT_FIELD(ir, 0, 4);
978 17c0fa3d Michael Walle
    dc->imm16 = EXTRACT_FIELD(ir, 0, 15);
979 17c0fa3d Michael Walle
    dc->imm26 = EXTRACT_FIELD(ir, 0, 25);
980 17c0fa3d Michael Walle
981 17c0fa3d Michael Walle
    dc->csr = EXTRACT_FIELD(ir, 21, 25);
982 17c0fa3d Michael Walle
    dc->r0 = EXTRACT_FIELD(ir, 21, 25);
983 17c0fa3d Michael Walle
    dc->r1 = EXTRACT_FIELD(ir, 16, 20);
984 17c0fa3d Michael Walle
    dc->r2 = EXTRACT_FIELD(ir, 11, 15);
985 17c0fa3d Michael Walle
986 17c0fa3d Michael Walle
    /* bit 31 seems to indicate insn type.  */
987 17c0fa3d Michael Walle
    if (ir & (1 << 31)) {
988 17c0fa3d Michael Walle
        dc->format = OP_FMT_RR;
989 17c0fa3d Michael Walle
    } else {
990 17c0fa3d Michael Walle
        dc->format = OP_FMT_RI;
991 17c0fa3d Michael Walle
    }
992 17c0fa3d Michael Walle
993 a5086f95 Michael Walle
    assert(ARRAY_SIZE(decinfo) == 64);
994 a5086f95 Michael Walle
    assert(dc->opcode < 64);
995 17c0fa3d Michael Walle
996 a5086f95 Michael Walle
    decinfo[dc->opcode](dc);
997 17c0fa3d Michael Walle
}
998 17c0fa3d Michael Walle
999 17c0fa3d Michael Walle
static void check_breakpoint(CPUState *env, DisasContext *dc)
1000 17c0fa3d Michael Walle
{
1001 17c0fa3d Michael Walle
    CPUBreakpoint *bp;
1002 17c0fa3d Michael Walle
1003 17c0fa3d Michael Walle
    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1004 17c0fa3d Michael Walle
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1005 17c0fa3d Michael Walle
            if (bp->pc == dc->pc) {
1006 17c0fa3d Michael Walle
                tcg_gen_movi_tl(cpu_pc, dc->pc);
1007 17c0fa3d Michael Walle
                t_gen_raise_exception(dc, EXCP_DEBUG);
1008 17c0fa3d Michael Walle
                dc->is_jmp = DISAS_UPDATE;
1009 17c0fa3d Michael Walle
             }
1010 17c0fa3d Michael Walle
        }
1011 17c0fa3d Michael Walle
    }
1012 17c0fa3d Michael Walle
}
1013 17c0fa3d Michael Walle
1014 17c0fa3d Michael Walle
/* generate intermediate code for basic block 'tb'.  */
1015 17c0fa3d Michael Walle
static void gen_intermediate_code_internal(CPUState *env,
1016 17c0fa3d Michael Walle
        TranslationBlock *tb, int search_pc)
1017 17c0fa3d Michael Walle
{
1018 17c0fa3d Michael Walle
    struct DisasContext ctx, *dc = &ctx;
1019 17c0fa3d Michael Walle
    uint16_t *gen_opc_end;
1020 17c0fa3d Michael Walle
    uint32_t pc_start;
1021 17c0fa3d Michael Walle
    int j, lj;
1022 17c0fa3d Michael Walle
    uint32_t next_page_start;
1023 17c0fa3d Michael Walle
    int num_insns;
1024 17c0fa3d Michael Walle
    int max_insns;
1025 17c0fa3d Michael Walle
1026 17c0fa3d Michael Walle
    qemu_log_try_set_file(stderr);
1027 17c0fa3d Michael Walle
1028 17c0fa3d Michael Walle
    pc_start = tb->pc;
1029 17c0fa3d Michael Walle
    dc->env = env;
1030 17c0fa3d Michael Walle
    dc->tb = tb;
1031 17c0fa3d Michael Walle
1032 17c0fa3d Michael Walle
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1033 17c0fa3d Michael Walle
1034 17c0fa3d Michael Walle
    dc->is_jmp = DISAS_NEXT;
1035 17c0fa3d Michael Walle
    dc->pc = pc_start;
1036 17c0fa3d Michael Walle
    dc->singlestep_enabled = env->singlestep_enabled;
1037 17c0fa3d Michael Walle
    dc->nr_nops = 0;
1038 17c0fa3d Michael Walle
1039 17c0fa3d Michael Walle
    if (pc_start & 3) {
1040 17c0fa3d Michael Walle
        cpu_abort(env, "LM32: unaligned PC=%x\n", pc_start);
1041 17c0fa3d Michael Walle
    }
1042 17c0fa3d Michael Walle
1043 17c0fa3d Michael Walle
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1044 17c0fa3d Michael Walle
        qemu_log("-----------------------------------------\n");
1045 17c0fa3d Michael Walle
        log_cpu_state(env, 0);
1046 17c0fa3d Michael Walle
    }
1047 17c0fa3d Michael Walle
1048 17c0fa3d Michael Walle
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1049 17c0fa3d Michael Walle
    lj = -1;
1050 17c0fa3d Michael Walle
    num_insns = 0;
1051 17c0fa3d Michael Walle
    max_insns = tb->cflags & CF_COUNT_MASK;
1052 17c0fa3d Michael Walle
    if (max_insns == 0) {
1053 17c0fa3d Michael Walle
        max_insns = CF_COUNT_MASK;
1054 17c0fa3d Michael Walle
    }
1055 17c0fa3d Michael Walle
1056 17c0fa3d Michael Walle
    gen_icount_start();
1057 17c0fa3d Michael Walle
    do {
1058 17c0fa3d Michael Walle
        check_breakpoint(env, dc);
1059 17c0fa3d Michael Walle
1060 17c0fa3d Michael Walle
        if (search_pc) {
1061 17c0fa3d Michael Walle
            j = gen_opc_ptr - gen_opc_buf;
1062 17c0fa3d Michael Walle
            if (lj < j) {
1063 17c0fa3d Michael Walle
                lj++;
1064 17c0fa3d Michael Walle
                while (lj < j) {
1065 17c0fa3d Michael Walle
                    gen_opc_instr_start[lj++] = 0;
1066 17c0fa3d Michael Walle
                }
1067 17c0fa3d Michael Walle
            }
1068 17c0fa3d Michael Walle
            gen_opc_pc[lj] = dc->pc;
1069 17c0fa3d Michael Walle
            gen_opc_instr_start[lj] = 1;
1070 17c0fa3d Michael Walle
            gen_opc_icount[lj] = num_insns;
1071 17c0fa3d Michael Walle
        }
1072 17c0fa3d Michael Walle
1073 17c0fa3d Michael Walle
        /* Pretty disas.  */
1074 17c0fa3d Michael Walle
        LOG_DIS("%8.8x:\t", dc->pc);
1075 17c0fa3d Michael Walle
1076 17c0fa3d Michael Walle
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1077 17c0fa3d Michael Walle
            gen_io_start();
1078 17c0fa3d Michael Walle
        }
1079 17c0fa3d Michael Walle
1080 17c0fa3d Michael Walle
        decode(dc);
1081 17c0fa3d Michael Walle
        dc->pc += 4;
1082 17c0fa3d Michael Walle
        num_insns++;
1083 17c0fa3d Michael Walle
1084 17c0fa3d Michael Walle
    } while (!dc->is_jmp
1085 17c0fa3d Michael Walle
         && gen_opc_ptr < gen_opc_end
1086 17c0fa3d Michael Walle
         && !env->singlestep_enabled
1087 17c0fa3d Michael Walle
         && !singlestep
1088 17c0fa3d Michael Walle
         && (dc->pc < next_page_start)
1089 17c0fa3d Michael Walle
         && num_insns < max_insns);
1090 17c0fa3d Michael Walle
1091 17c0fa3d Michael Walle
    if (tb->cflags & CF_LAST_IO) {
1092 17c0fa3d Michael Walle
        gen_io_end();
1093 17c0fa3d Michael Walle
    }
1094 17c0fa3d Michael Walle
1095 17c0fa3d Michael Walle
    if (unlikely(env->singlestep_enabled)) {
1096 17c0fa3d Michael Walle
        if (dc->is_jmp == DISAS_NEXT) {
1097 17c0fa3d Michael Walle
            tcg_gen_movi_tl(cpu_pc, dc->pc);
1098 17c0fa3d Michael Walle
        }
1099 17c0fa3d Michael Walle
        t_gen_raise_exception(dc, EXCP_DEBUG);
1100 17c0fa3d Michael Walle
    } else {
1101 17c0fa3d Michael Walle
        switch (dc->is_jmp) {
1102 17c0fa3d Michael Walle
        case DISAS_NEXT:
1103 17c0fa3d Michael Walle
            gen_goto_tb(dc, 1, dc->pc);
1104 17c0fa3d Michael Walle
            break;
1105 17c0fa3d Michael Walle
        default:
1106 17c0fa3d Michael Walle
        case DISAS_JUMP:
1107 17c0fa3d Michael Walle
        case DISAS_UPDATE:
1108 17c0fa3d Michael Walle
            /* indicate that the hash table must be used
1109 17c0fa3d Michael Walle
               to find the next TB */
1110 17c0fa3d Michael Walle
            tcg_gen_exit_tb(0);
1111 17c0fa3d Michael Walle
            break;
1112 17c0fa3d Michael Walle
        case DISAS_TB_JUMP:
1113 17c0fa3d Michael Walle
            /* nothing more to generate */
1114 17c0fa3d Michael Walle
            break;
1115 17c0fa3d Michael Walle
        }
1116 17c0fa3d Michael Walle
    }
1117 17c0fa3d Michael Walle
1118 17c0fa3d Michael Walle
    gen_icount_end(tb, num_insns);
1119 17c0fa3d Michael Walle
    *gen_opc_ptr = INDEX_op_end;
1120 17c0fa3d Michael Walle
    if (search_pc) {
1121 17c0fa3d Michael Walle
        j = gen_opc_ptr - gen_opc_buf;
1122 17c0fa3d Michael Walle
        lj++;
1123 17c0fa3d Michael Walle
        while (lj <= j) {
1124 17c0fa3d Michael Walle
            gen_opc_instr_start[lj++] = 0;
1125 17c0fa3d Michael Walle
        }
1126 17c0fa3d Michael Walle
    } else {
1127 17c0fa3d Michael Walle
        tb->size = dc->pc - pc_start;
1128 17c0fa3d Michael Walle
        tb->icount = num_insns;
1129 17c0fa3d Michael Walle
    }
1130 17c0fa3d Michael Walle
1131 17c0fa3d Michael Walle
#ifdef DEBUG_DISAS
1132 17c0fa3d Michael Walle
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1133 17c0fa3d Michael Walle
        qemu_log("\n");
1134 17c0fa3d Michael Walle
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1135 17c0fa3d Michael Walle
        qemu_log("\nisize=%d osize=%zd\n",
1136 17c0fa3d Michael Walle
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1137 17c0fa3d Michael Walle
    }
1138 17c0fa3d Michael Walle
#endif
1139 17c0fa3d Michael Walle
}
1140 17c0fa3d Michael Walle
1141 17c0fa3d Michael Walle
void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
1142 17c0fa3d Michael Walle
{
1143 17c0fa3d Michael Walle
    gen_intermediate_code_internal(env, tb, 0);
1144 17c0fa3d Michael Walle
}
1145 17c0fa3d Michael Walle
1146 17c0fa3d Michael Walle
void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
1147 17c0fa3d Michael Walle
{
1148 17c0fa3d Michael Walle
    gen_intermediate_code_internal(env, tb, 1);
1149 17c0fa3d Michael Walle
}
1150 17c0fa3d Michael Walle
1151 17c0fa3d Michael Walle
void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1152 17c0fa3d Michael Walle
                     int flags)
1153 17c0fa3d Michael Walle
{
1154 17c0fa3d Michael Walle
    int i;
1155 17c0fa3d Michael Walle
1156 17c0fa3d Michael Walle
    if (!env || !f) {
1157 17c0fa3d Michael Walle
        return;
1158 17c0fa3d Michael Walle
    }
1159 17c0fa3d Michael Walle
1160 17c0fa3d Michael Walle
    cpu_fprintf(f, "IN: PC=%x %s\n",
1161 17c0fa3d Michael Walle
                env->pc, lookup_symbol(env->pc));
1162 17c0fa3d Michael Walle
1163 17c0fa3d Michael Walle
    cpu_fprintf(f, "ie=%8.8x (IE=%x EIE=%x BIE=%x) im=%8.8x ip=%8.8x\n",
1164 17c0fa3d Michael Walle
             env->ie,
1165 17c0fa3d Michael Walle
             (env->ie & IE_IE) ? 1 : 0,
1166 17c0fa3d Michael Walle
             (env->ie & IE_EIE) ? 1 : 0,
1167 17c0fa3d Michael Walle
             (env->ie & IE_BIE) ? 1 : 0,
1168 17c0fa3d Michael Walle
             lm32_pic_get_im(env->pic_state),
1169 17c0fa3d Michael Walle
             lm32_pic_get_ip(env->pic_state));
1170 17c0fa3d Michael Walle
    cpu_fprintf(f, "eba=%8.8x deba=%8.8x\n",
1171 17c0fa3d Michael Walle
             env->eba,
1172 17c0fa3d Michael Walle
             env->deba);
1173 17c0fa3d Michael Walle
1174 17c0fa3d Michael Walle
    for (i = 0; i < 32; i++) {
1175 17c0fa3d Michael Walle
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1176 17c0fa3d Michael Walle
        if ((i + 1) % 4 == 0) {
1177 17c0fa3d Michael Walle
            cpu_fprintf(f, "\n");
1178 17c0fa3d Michael Walle
        }
1179 17c0fa3d Michael Walle
    }
1180 17c0fa3d Michael Walle
    cpu_fprintf(f, "\n\n");
1181 17c0fa3d Michael Walle
}
1182 17c0fa3d Michael Walle
1183 e87b7cb0 Stefan Weil
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
1184 17c0fa3d Michael Walle
{
1185 17c0fa3d Michael Walle
    env->pc = gen_opc_pc[pc_pos];
1186 17c0fa3d Michael Walle
}
1187 17c0fa3d Michael Walle
1188 17c0fa3d Michael Walle
void lm32_translate_init(void)
1189 17c0fa3d Michael Walle
{
1190 17c0fa3d Michael Walle
    int i;
1191 17c0fa3d Michael Walle
1192 17c0fa3d Michael Walle
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1193 17c0fa3d Michael Walle
1194 17c0fa3d Michael Walle
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1195 17c0fa3d Michael Walle
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1196 17c0fa3d Michael Walle
                          offsetof(CPUState, regs[i]),
1197 17c0fa3d Michael Walle
                          regnames[i]);
1198 17c0fa3d Michael Walle
    }
1199 17c0fa3d Michael Walle
1200 17c0fa3d Michael Walle
    for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) {
1201 17c0fa3d Michael Walle
        cpu_bp[i] = tcg_global_mem_new(TCG_AREG0,
1202 17c0fa3d Michael Walle
                          offsetof(CPUState, bp[i]),
1203 17c0fa3d Michael Walle
                          regnames[32+i]);
1204 17c0fa3d Michael Walle
    }
1205 17c0fa3d Michael Walle
1206 17c0fa3d Michael Walle
    for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) {
1207 17c0fa3d Michael Walle
        cpu_wp[i] = tcg_global_mem_new(TCG_AREG0,
1208 17c0fa3d Michael Walle
                          offsetof(CPUState, wp[i]),
1209 17c0fa3d Michael Walle
                          regnames[36+i]);
1210 17c0fa3d Michael Walle
    }
1211 17c0fa3d Michael Walle
1212 17c0fa3d Michael Walle
    cpu_pc = tcg_global_mem_new(TCG_AREG0,
1213 17c0fa3d Michael Walle
                    offsetof(CPUState, pc),
1214 17c0fa3d Michael Walle
                    "pc");
1215 17c0fa3d Michael Walle
    cpu_ie = tcg_global_mem_new(TCG_AREG0,
1216 17c0fa3d Michael Walle
                    offsetof(CPUState, ie),
1217 17c0fa3d Michael Walle
                    "ie");
1218 17c0fa3d Michael Walle
    cpu_icc = tcg_global_mem_new(TCG_AREG0,
1219 17c0fa3d Michael Walle
                    offsetof(CPUState, icc),
1220 17c0fa3d Michael Walle
                    "icc");
1221 17c0fa3d Michael Walle
    cpu_dcc = tcg_global_mem_new(TCG_AREG0,
1222 17c0fa3d Michael Walle
                    offsetof(CPUState, dcc),
1223 17c0fa3d Michael Walle
                    "dcc");
1224 17c0fa3d Michael Walle
    cpu_cc = tcg_global_mem_new(TCG_AREG0,
1225 17c0fa3d Michael Walle
                    offsetof(CPUState, cc),
1226 17c0fa3d Michael Walle
                    "cc");
1227 17c0fa3d Michael Walle
    cpu_cfg = tcg_global_mem_new(TCG_AREG0,
1228 17c0fa3d Michael Walle
                    offsetof(CPUState, cfg),
1229 17c0fa3d Michael Walle
                    "cfg");
1230 17c0fa3d Michael Walle
    cpu_eba = tcg_global_mem_new(TCG_AREG0,
1231 17c0fa3d Michael Walle
                    offsetof(CPUState, eba),
1232 17c0fa3d Michael Walle
                    "eba");
1233 17c0fa3d Michael Walle
    cpu_dc = tcg_global_mem_new(TCG_AREG0,
1234 17c0fa3d Michael Walle
                    offsetof(CPUState, dc),
1235 17c0fa3d Michael Walle
                    "dc");
1236 17c0fa3d Michael Walle
    cpu_deba = tcg_global_mem_new(TCG_AREG0,
1237 17c0fa3d Michael Walle
                    offsetof(CPUState, deba),
1238 17c0fa3d Michael Walle
                    "deba");
1239 17c0fa3d Michael Walle
}