Statistics
| Branch: | Revision:

root / target-lm32 / translate.c @ fcda9863

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