Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ 5169202b

History | View | Annotate | Download (38.1 kB)

1 4acb54ba Edgar E. Iglesias
/*
2 4acb54ba Edgar E. Iglesias
 *  Xilinx MicroBlaze emulation for qemu: main translation routines.
3 4acb54ba Edgar E. Iglesias
 *
4 4acb54ba Edgar E. Iglesias
 *  Copyright (c) 2009 Edgar E. Iglesias.
5 4acb54ba Edgar E. Iglesias
 *
6 4acb54ba Edgar E. Iglesias
 * This library is free software; you can redistribute it and/or
7 4acb54ba Edgar E. Iglesias
 * modify it under the terms of the GNU Lesser General Public
8 4acb54ba Edgar E. Iglesias
 * License as published by the Free Software Foundation; either
9 4acb54ba Edgar E. Iglesias
 * version 2 of the License, or (at your option) any later version.
10 4acb54ba Edgar E. Iglesias
 *
11 4acb54ba Edgar E. Iglesias
 * This library is distributed in the hope that it will be useful,
12 4acb54ba Edgar E. Iglesias
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 4acb54ba Edgar E. Iglesias
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4acb54ba Edgar E. Iglesias
 * Lesser General Public License for more details.
15 4acb54ba Edgar E. Iglesias
 *
16 4acb54ba Edgar E. Iglesias
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 4acb54ba Edgar E. Iglesias
 */
19 4acb54ba Edgar E. Iglesias
20 4acb54ba Edgar E. Iglesias
#include <stdarg.h>
21 4acb54ba Edgar E. Iglesias
#include <stdlib.h>
22 4acb54ba Edgar E. Iglesias
#include <stdio.h>
23 4acb54ba Edgar E. Iglesias
#include <string.h>
24 4acb54ba Edgar E. Iglesias
#include <inttypes.h>
25 4acb54ba Edgar E. Iglesias
#include <assert.h>
26 4acb54ba Edgar E. Iglesias
27 4acb54ba Edgar E. Iglesias
#include "cpu.h"
28 4acb54ba Edgar E. Iglesias
#include "exec-all.h"
29 4acb54ba Edgar E. Iglesias
#include "disas.h"
30 4acb54ba Edgar E. Iglesias
#include "tcg-op.h"
31 4acb54ba Edgar E. Iglesias
#include "helper.h"
32 4acb54ba Edgar E. Iglesias
#include "microblaze-decode.h"
33 4acb54ba Edgar E. Iglesias
#include "qemu-common.h"
34 4acb54ba Edgar E. Iglesias
35 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 1
36 4acb54ba Edgar E. Iglesias
#include "helper.h"
37 4acb54ba Edgar E. Iglesias
38 4acb54ba Edgar E. Iglesias
#define SIM_COMPAT 0
39 4acb54ba Edgar E. Iglesias
#define DISAS_GNU 1
40 4acb54ba Edgar E. Iglesias
#define DISAS_MB 1
41 4acb54ba Edgar E. Iglesias
#if DISAS_MB && !SIM_COMPAT
42 4acb54ba Edgar E. Iglesias
#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
43 4acb54ba Edgar E. Iglesias
#else
44 4acb54ba Edgar E. Iglesias
#  define LOG_DIS(...) do { } while (0)
45 4acb54ba Edgar E. Iglesias
#endif
46 4acb54ba Edgar E. Iglesias
47 4acb54ba Edgar E. Iglesias
#define D(x)
48 4acb54ba Edgar E. Iglesias
49 4acb54ba Edgar E. Iglesias
#define EXTRACT_FIELD(src, start, end) \
50 4acb54ba Edgar E. Iglesias
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
51 4acb54ba Edgar E. Iglesias
52 4acb54ba Edgar E. Iglesias
static TCGv env_debug;
53 4acb54ba Edgar E. Iglesias
static TCGv_ptr cpu_env;
54 4acb54ba Edgar E. Iglesias
static TCGv cpu_R[32];
55 4acb54ba Edgar E. Iglesias
static TCGv cpu_SR[18];
56 4acb54ba Edgar E. Iglesias
static TCGv env_imm;
57 4acb54ba Edgar E. Iglesias
static TCGv env_btaken;
58 4acb54ba Edgar E. Iglesias
static TCGv env_btarget;
59 4acb54ba Edgar E. Iglesias
static TCGv env_iflags;
60 4acb54ba Edgar E. Iglesias
61 4acb54ba Edgar E. Iglesias
#include "gen-icount.h"
62 4acb54ba Edgar E. Iglesias
63 4acb54ba Edgar E. Iglesias
/* This is the state at translation time.  */
64 4acb54ba Edgar E. Iglesias
typedef struct DisasContext {
65 4acb54ba Edgar E. Iglesias
    CPUState *env;
66 4acb54ba Edgar E. Iglesias
    target_ulong pc, ppc;
67 4acb54ba Edgar E. Iglesias
    target_ulong cache_pc;
68 4acb54ba Edgar E. Iglesias
69 4acb54ba Edgar E. Iglesias
    /* Decoder.  */
70 4acb54ba Edgar E. Iglesias
    int type_b;
71 4acb54ba Edgar E. Iglesias
    uint32_t ir;
72 4acb54ba Edgar E. Iglesias
    uint8_t opcode;
73 4acb54ba Edgar E. Iglesias
    uint8_t rd, ra, rb;
74 4acb54ba Edgar E. Iglesias
    uint16_t imm;
75 4acb54ba Edgar E. Iglesias
76 4acb54ba Edgar E. Iglesias
    unsigned int cpustate_changed;
77 4acb54ba Edgar E. Iglesias
    unsigned int delayed_branch;
78 4acb54ba Edgar E. Iglesias
    unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
79 4acb54ba Edgar E. Iglesias
    unsigned int clear_imm;
80 4acb54ba Edgar E. Iglesias
    int is_jmp;
81 4acb54ba Edgar E. Iglesias
82 4acb54ba Edgar E. Iglesias
#define JMP_NOJMP    0
83 4acb54ba Edgar E. Iglesias
#define JMP_DIRECT   1
84 4acb54ba Edgar E. Iglesias
#define JMP_INDIRECT 2
85 4acb54ba Edgar E. Iglesias
    unsigned int jmp;
86 4acb54ba Edgar E. Iglesias
    uint32_t jmp_pc;
87 4acb54ba Edgar E. Iglesias
88 4acb54ba Edgar E. Iglesias
    int abort_at_next_insn;
89 4acb54ba Edgar E. Iglesias
    int nr_nops;
90 4acb54ba Edgar E. Iglesias
    struct TranslationBlock *tb;
91 4acb54ba Edgar E. Iglesias
    int singlestep_enabled;
92 4acb54ba Edgar E. Iglesias
} DisasContext;
93 4acb54ba Edgar E. Iglesias
94 4acb54ba Edgar E. Iglesias
const static char *regnames[] =
95 4acb54ba Edgar E. Iglesias
{
96 4acb54ba Edgar E. Iglesias
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
97 4acb54ba Edgar E. Iglesias
    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
98 4acb54ba Edgar E. Iglesias
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
99 4acb54ba Edgar E. Iglesias
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
100 4acb54ba Edgar E. Iglesias
};
101 4acb54ba Edgar E. Iglesias
102 4acb54ba Edgar E. Iglesias
const static char *special_regnames[] =
103 4acb54ba Edgar E. Iglesias
{
104 4acb54ba Edgar E. Iglesias
    "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
105 4acb54ba Edgar E. Iglesias
    "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
106 4acb54ba Edgar E. Iglesias
    "sr16", "sr17", "sr18"
107 4acb54ba Edgar E. Iglesias
};
108 4acb54ba Edgar E. Iglesias
109 4acb54ba Edgar E. Iglesias
/* Sign extend at translation time.  */
110 4acb54ba Edgar E. Iglesias
static inline int sign_extend(unsigned int val, unsigned int width)
111 4acb54ba Edgar E. Iglesias
{
112 4acb54ba Edgar E. Iglesias
        int sval;
113 4acb54ba Edgar E. Iglesias
114 4acb54ba Edgar E. Iglesias
        /* LSL.  */
115 4acb54ba Edgar E. Iglesias
        val <<= 31 - width;
116 4acb54ba Edgar E. Iglesias
        sval = val;
117 4acb54ba Edgar E. Iglesias
        /* ASR.  */
118 4acb54ba Edgar E. Iglesias
        sval >>= 31 - width;
119 4acb54ba Edgar E. Iglesias
        return sval;
120 4acb54ba Edgar E. Iglesias
}
121 4acb54ba Edgar E. Iglesias
122 4acb54ba Edgar E. Iglesias
static inline void t_sync_flags(DisasContext *dc)
123 4acb54ba Edgar E. Iglesias
{
124 4acb54ba Edgar E. Iglesias
    /* Synch the tb dependant flags between translator and runtime.  */
125 4acb54ba Edgar E. Iglesias
    if (dc->tb_flags != dc->synced_flags) {
126 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_iflags, dc->tb_flags);
127 4acb54ba Edgar E. Iglesias
        dc->synced_flags = dc->tb_flags;
128 4acb54ba Edgar E. Iglesias
    }
129 4acb54ba Edgar E. Iglesias
}
130 4acb54ba Edgar E. Iglesias
131 4acb54ba Edgar E. Iglesias
static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
132 4acb54ba Edgar E. Iglesias
{
133 4acb54ba Edgar E. Iglesias
    TCGv_i32 tmp = tcg_const_i32(index);
134 4acb54ba Edgar E. Iglesias
135 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
136 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
137 4acb54ba Edgar E. Iglesias
    gen_helper_raise_exception(tmp);
138 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i32(tmp);
139 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_UPDATE;
140 4acb54ba Edgar E. Iglesias
}
141 4acb54ba Edgar E. Iglesias
142 4acb54ba Edgar E. Iglesias
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
143 4acb54ba Edgar E. Iglesias
{
144 4acb54ba Edgar E. Iglesias
    TranslationBlock *tb;
145 4acb54ba Edgar E. Iglesias
    tb = dc->tb;
146 4acb54ba Edgar E. Iglesias
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
147 4acb54ba Edgar E. Iglesias
        tcg_gen_goto_tb(n);
148 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
149 4acb54ba Edgar E. Iglesias
        tcg_gen_exit_tb((long)tb + n);
150 4acb54ba Edgar E. Iglesias
    } else {
151 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
152 4acb54ba Edgar E. Iglesias
        tcg_gen_exit_tb(0);
153 4acb54ba Edgar E. Iglesias
    }
154 4acb54ba Edgar E. Iglesias
}
155 4acb54ba Edgar E. Iglesias
156 4acb54ba Edgar E. Iglesias
static inline TCGv *dec_alu_op_b(DisasContext *dc)
157 4acb54ba Edgar E. Iglesias
{
158 4acb54ba Edgar E. Iglesias
    if (dc->type_b) {
159 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & IMM_FLAG)
160 4acb54ba Edgar E. Iglesias
            tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
161 4acb54ba Edgar E. Iglesias
        else
162 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
163 4acb54ba Edgar E. Iglesias
        return &env_imm;
164 4acb54ba Edgar E. Iglesias
    } else
165 4acb54ba Edgar E. Iglesias
        return &cpu_R[dc->rb];
166 4acb54ba Edgar E. Iglesias
}
167 4acb54ba Edgar E. Iglesias
168 4acb54ba Edgar E. Iglesias
static void dec_add(DisasContext *dc)
169 4acb54ba Edgar E. Iglesias
{
170 4acb54ba Edgar E. Iglesias
    unsigned int k, c;
171 4acb54ba Edgar E. Iglesias
172 4acb54ba Edgar E. Iglesias
    k = dc->opcode & 4;
173 4acb54ba Edgar E. Iglesias
    c = dc->opcode & 2;
174 4acb54ba Edgar E. Iglesias
175 4acb54ba Edgar E. Iglesias
    LOG_DIS("add%s%s%s r%d r%d r%d\n",
176 4acb54ba Edgar E. Iglesias
            dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
177 4acb54ba Edgar E. Iglesias
            dc->rd, dc->ra, dc->rb);
178 4acb54ba Edgar E. Iglesias
179 4acb54ba Edgar E. Iglesias
    if (k && !c && dc->rd)
180 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
181 4acb54ba Edgar E. Iglesias
    else if (dc->rd)
182 4acb54ba Edgar E. Iglesias
        gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
183 4acb54ba Edgar E. Iglesias
                         tcg_const_tl(k), tcg_const_tl(c));
184 4acb54ba Edgar E. Iglesias
    else {
185 4acb54ba Edgar E. Iglesias
        TCGv d = tcg_temp_new();
186 4acb54ba Edgar E. Iglesias
        gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
187 4acb54ba Edgar E. Iglesias
                         tcg_const_tl(k), tcg_const_tl(c));
188 4acb54ba Edgar E. Iglesias
        tcg_temp_free(d);
189 4acb54ba Edgar E. Iglesias
    }
190 4acb54ba Edgar E. Iglesias
}
191 4acb54ba Edgar E. Iglesias
192 4acb54ba Edgar E. Iglesias
static void dec_sub(DisasContext *dc)
193 4acb54ba Edgar E. Iglesias
{
194 4acb54ba Edgar E. Iglesias
    unsigned int u, cmp, k, c;
195 4acb54ba Edgar E. Iglesias
196 4acb54ba Edgar E. Iglesias
    u = dc->imm & 2;
197 4acb54ba Edgar E. Iglesias
    k = dc->opcode & 4;
198 4acb54ba Edgar E. Iglesias
    c = dc->opcode & 2;
199 4acb54ba Edgar E. Iglesias
    cmp = (dc->imm & 1) && (!dc->type_b) && k;
200 4acb54ba Edgar E. Iglesias
201 4acb54ba Edgar E. Iglesias
    if (cmp) {
202 4acb54ba Edgar E. Iglesias
        LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
203 4acb54ba Edgar E. Iglesias
        if (dc->rd) {
204 4acb54ba Edgar E. Iglesias
            if (u)
205 4acb54ba Edgar E. Iglesias
                gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
206 4acb54ba Edgar E. Iglesias
            else
207 4acb54ba Edgar E. Iglesias
                gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
208 4acb54ba Edgar E. Iglesias
        }
209 4acb54ba Edgar E. Iglesias
    } else {
210 4acb54ba Edgar E. Iglesias
        LOG_DIS("sub%s%s r%d, r%d r%d\n",
211 4acb54ba Edgar E. Iglesias
                 k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
212 4acb54ba Edgar E. Iglesias
213 4acb54ba Edgar E. Iglesias
        if (!k || c) {
214 4acb54ba Edgar E. Iglesias
            TCGv t;
215 4acb54ba Edgar E. Iglesias
            t = tcg_temp_new();
216 4acb54ba Edgar E. Iglesias
            if (dc->rd)
217 4acb54ba Edgar E. Iglesias
                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
218 4acb54ba Edgar E. Iglesias
                                 tcg_const_tl(k), tcg_const_tl(c));
219 4acb54ba Edgar E. Iglesias
            else
220 4acb54ba Edgar E. Iglesias
                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
221 4acb54ba Edgar E. Iglesias
                                 tcg_const_tl(k), tcg_const_tl(c));
222 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t);
223 4acb54ba Edgar E. Iglesias
        }
224 4acb54ba Edgar E. Iglesias
        else if (dc->rd)
225 4acb54ba Edgar E. Iglesias
            tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
226 4acb54ba Edgar E. Iglesias
    }
227 4acb54ba Edgar E. Iglesias
}
228 4acb54ba Edgar E. Iglesias
229 4acb54ba Edgar E. Iglesias
static void dec_pattern(DisasContext *dc)
230 4acb54ba Edgar E. Iglesias
{
231 4acb54ba Edgar E. Iglesias
    unsigned int mode;
232 4acb54ba Edgar E. Iglesias
    int l1;
233 4acb54ba Edgar E. Iglesias
234 4acb54ba Edgar E. Iglesias
    mode = dc->opcode & 3;
235 4acb54ba Edgar E. Iglesias
    switch (mode) {
236 4acb54ba Edgar E. Iglesias
        case 0:
237 4acb54ba Edgar E. Iglesias
            /* pcmpbf.  */
238 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
239 4acb54ba Edgar E. Iglesias
            if (dc->rd)
240 4acb54ba Edgar E. Iglesias
                gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
241 4acb54ba Edgar E. Iglesias
            break;
242 4acb54ba Edgar E. Iglesias
        case 2:
243 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
244 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
245 4acb54ba Edgar E. Iglesias
                TCGv t0 = tcg_temp_local_new();
246 4acb54ba Edgar E. Iglesias
                l1 = gen_new_label();
247 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 1);
248 4acb54ba Edgar E. Iglesias
                tcg_gen_brcond_tl(TCG_COND_EQ,
249 4acb54ba Edgar E. Iglesias
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
250 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 0);
251 4acb54ba Edgar E. Iglesias
                gen_set_label(l1);
252 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
253 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t0);
254 4acb54ba Edgar E. Iglesias
            }
255 4acb54ba Edgar E. Iglesias
            break;
256 4acb54ba Edgar E. Iglesias
        case 3:
257 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
258 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
259 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
260 4acb54ba Edgar E. Iglesias
                TCGv t0 = tcg_temp_local_new();
261 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 1);
262 4acb54ba Edgar E. Iglesias
                tcg_gen_brcond_tl(TCG_COND_NE,
263 4acb54ba Edgar E. Iglesias
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
264 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 0);
265 4acb54ba Edgar E. Iglesias
                gen_set_label(l1);
266 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
267 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t0);
268 4acb54ba Edgar E. Iglesias
            }
269 4acb54ba Edgar E. Iglesias
            break;
270 4acb54ba Edgar E. Iglesias
        default:
271 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env,
272 4acb54ba Edgar E. Iglesias
                      "unsupported pattern insn opcode=%x\n", dc->opcode);
273 4acb54ba Edgar E. Iglesias
            break;
274 4acb54ba Edgar E. Iglesias
    }
275 4acb54ba Edgar E. Iglesias
}
276 4acb54ba Edgar E. Iglesias
277 4acb54ba Edgar E. Iglesias
static void dec_and(DisasContext *dc)
278 4acb54ba Edgar E. Iglesias
{
279 4acb54ba Edgar E. Iglesias
    unsigned int not;
280 4acb54ba Edgar E. Iglesias
281 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
282 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
283 4acb54ba Edgar E. Iglesias
        return;
284 4acb54ba Edgar E. Iglesias
    }
285 4acb54ba Edgar E. Iglesias
286 4acb54ba Edgar E. Iglesias
    not = dc->opcode & (1 << 1);
287 4acb54ba Edgar E. Iglesias
    LOG_DIS("and%s\n", not ? "n" : "");
288 4acb54ba Edgar E. Iglesias
289 4acb54ba Edgar E. Iglesias
    if (!dc->rd)
290 4acb54ba Edgar E. Iglesias
        return;
291 4acb54ba Edgar E. Iglesias
292 4acb54ba Edgar E. Iglesias
    if (not) {
293 4acb54ba Edgar E. Iglesias
        TCGv t = tcg_temp_new();
294 4acb54ba Edgar E. Iglesias
        tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
295 4acb54ba Edgar E. Iglesias
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
296 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
297 4acb54ba Edgar E. Iglesias
    } else
298 4acb54ba Edgar E. Iglesias
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
299 4acb54ba Edgar E. Iglesias
}
300 4acb54ba Edgar E. Iglesias
301 4acb54ba Edgar E. Iglesias
static void dec_or(DisasContext *dc)
302 4acb54ba Edgar E. Iglesias
{
303 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
304 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
305 4acb54ba Edgar E. Iglesias
        return;
306 4acb54ba Edgar E. Iglesias
    }
307 4acb54ba Edgar E. Iglesias
308 4acb54ba Edgar E. Iglesias
    LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
309 4acb54ba Edgar E. Iglesias
    if (dc->rd)
310 4acb54ba Edgar E. Iglesias
        tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
311 4acb54ba Edgar E. Iglesias
}
312 4acb54ba Edgar E. Iglesias
313 4acb54ba Edgar E. Iglesias
static void dec_xor(DisasContext *dc)
314 4acb54ba Edgar E. Iglesias
{
315 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
316 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
317 4acb54ba Edgar E. Iglesias
        return;
318 4acb54ba Edgar E. Iglesias
    }
319 4acb54ba Edgar E. Iglesias
320 4acb54ba Edgar E. Iglesias
    LOG_DIS("xor r%d\n", dc->rd);
321 4acb54ba Edgar E. Iglesias
    if (dc->rd)
322 4acb54ba Edgar E. Iglesias
        tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
323 4acb54ba Edgar E. Iglesias
}
324 4acb54ba Edgar E. Iglesias
325 4acb54ba Edgar E. Iglesias
static void read_carry(DisasContext *dc, TCGv d)
326 4acb54ba Edgar E. Iglesias
{
327 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
328 4acb54ba Edgar E. Iglesias
}
329 4acb54ba Edgar E. Iglesias
330 4acb54ba Edgar E. Iglesias
static void write_carry(DisasContext *dc, TCGv v)
331 4acb54ba Edgar E. Iglesias
{
332 4acb54ba Edgar E. Iglesias
    TCGv t0 = tcg_temp_new();
333 4acb54ba Edgar E. Iglesias
    tcg_gen_shli_tl(t0, v, 31);
334 4acb54ba Edgar E. Iglesias
    tcg_gen_sari_tl(t0, t0, 31);
335 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(env_debug, t0);
336 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
337 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
338 4acb54ba Edgar E. Iglesias
                    ~(MSR_C | MSR_CC));
339 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
340 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
341 4acb54ba Edgar E. Iglesias
}
342 4acb54ba Edgar E. Iglesias
343 4acb54ba Edgar E. Iglesias
344 4acb54ba Edgar E. Iglesias
static inline void msr_read(DisasContext *dc, TCGv d)
345 4acb54ba Edgar E. Iglesias
{
346 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
347 4acb54ba Edgar E. Iglesias
}
348 4acb54ba Edgar E. Iglesias
349 4acb54ba Edgar E. Iglesias
static inline void msr_write(DisasContext *dc, TCGv v)
350 4acb54ba Edgar E. Iglesias
{
351 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 1;
352 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_MSR], v);
353 4acb54ba Edgar E. Iglesias
    /* PVR, we have a processor version register.  */
354 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10));
355 4acb54ba Edgar E. Iglesias
}
356 4acb54ba Edgar E. Iglesias
357 4acb54ba Edgar E. Iglesias
static void dec_msr(DisasContext *dc)
358 4acb54ba Edgar E. Iglesias
{
359 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
360 4acb54ba Edgar E. Iglesias
    unsigned int sr, to, rn;
361 4acb54ba Edgar E. Iglesias
362 4acb54ba Edgar E. Iglesias
    sr = dc->imm & ((1 << 14) - 1);
363 4acb54ba Edgar E. Iglesias
    to = dc->imm & (1 << 14);
364 4acb54ba Edgar E. Iglesias
    dc->type_b = 1;
365 4acb54ba Edgar E. Iglesias
    if (to)
366 4acb54ba Edgar E. Iglesias
        dc->cpustate_changed = 1;
367 4acb54ba Edgar E. Iglesias
368 4acb54ba Edgar E. Iglesias
    /* msrclr and msrset.  */
369 4acb54ba Edgar E. Iglesias
    if (!(dc->imm & (1 << 15))) {
370 4acb54ba Edgar E. Iglesias
        unsigned int clr = dc->ir & (1 << 16);
371 4acb54ba Edgar E. Iglesias
372 4acb54ba Edgar E. Iglesias
        LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
373 4acb54ba Edgar E. Iglesias
                dc->rd, dc->imm);
374 4acb54ba Edgar E. Iglesias
        if (dc->rd)
375 4acb54ba Edgar E. Iglesias
            msr_read(dc, cpu_R[dc->rd]);
376 4acb54ba Edgar E. Iglesias
377 4acb54ba Edgar E. Iglesias
        t0 = tcg_temp_new();
378 4acb54ba Edgar E. Iglesias
        t1 = tcg_temp_new();
379 4acb54ba Edgar E. Iglesias
        msr_read(dc, t0);
380 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
381 4acb54ba Edgar E. Iglesias
382 4acb54ba Edgar E. Iglesias
        if (clr) {
383 4acb54ba Edgar E. Iglesias
            tcg_gen_not_tl(t1, t1);
384 4acb54ba Edgar E. Iglesias
            tcg_gen_and_tl(t0, t0, t1);
385 4acb54ba Edgar E. Iglesias
        } else
386 4acb54ba Edgar E. Iglesias
            tcg_gen_or_tl(t0, t0, t1);
387 4acb54ba Edgar E. Iglesias
        msr_write(dc, t0);
388 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t0);
389 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t1);
390 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
391 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
392 4acb54ba Edgar E. Iglesias
        return;
393 4acb54ba Edgar E. Iglesias
    }
394 4acb54ba Edgar E. Iglesias
395 4acb54ba Edgar E. Iglesias
#if !defined(CONFIG_USER_ONLY)
396 4acb54ba Edgar E. Iglesias
    /* Catch read/writes to the mmu block.  */
397 4acb54ba Edgar E. Iglesias
    if ((sr & ~0xff) == 0x1000) {
398 4acb54ba Edgar E. Iglesias
        sr &= 7;
399 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
400 4acb54ba Edgar E. Iglesias
        if (to)
401 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
402 4acb54ba Edgar E. Iglesias
        else
403 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
404 4acb54ba Edgar E. Iglesias
        return;
405 4acb54ba Edgar E. Iglesias
    }
406 4acb54ba Edgar E. Iglesias
#endif
407 4acb54ba Edgar E. Iglesias
408 4acb54ba Edgar E. Iglesias
    if (to) {
409 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
410 4acb54ba Edgar E. Iglesias
        switch (sr) {
411 4acb54ba Edgar E. Iglesias
            case 0:
412 4acb54ba Edgar E. Iglesias
                break;
413 4acb54ba Edgar E. Iglesias
            case 1:
414 4acb54ba Edgar E. Iglesias
                msr_write(dc, cpu_R[dc->ra]);
415 4acb54ba Edgar E. Iglesias
                break;
416 4acb54ba Edgar E. Iglesias
            case 0x3:
417 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
418 4acb54ba Edgar E. Iglesias
                break;
419 4acb54ba Edgar E. Iglesias
            case 0x5:
420 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
421 4acb54ba Edgar E. Iglesias
                break;
422 4acb54ba Edgar E. Iglesias
            case 0x7:
423 4acb54ba Edgar E. Iglesias
                /* Ignored at the moment.  */
424 4acb54ba Edgar E. Iglesias
                break;
425 4acb54ba Edgar E. Iglesias
            default:
426 4acb54ba Edgar E. Iglesias
                cpu_abort(dc->env, "unknown mts reg %x\n", sr);
427 4acb54ba Edgar E. Iglesias
                break;
428 4acb54ba Edgar E. Iglesias
        }
429 4acb54ba Edgar E. Iglesias
    } else {
430 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
431 4acb54ba Edgar E. Iglesias
432 4acb54ba Edgar E. Iglesias
        switch (sr) {
433 4acb54ba Edgar E. Iglesias
            case 0:
434 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
435 4acb54ba Edgar E. Iglesias
                break;
436 4acb54ba Edgar E. Iglesias
            case 1:
437 4acb54ba Edgar E. Iglesias
                msr_read(dc, cpu_R[dc->rd]);
438 4acb54ba Edgar E. Iglesias
                break;
439 4acb54ba Edgar E. Iglesias
            case 0x3:
440 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
441 4acb54ba Edgar E. Iglesias
                break;
442 4acb54ba Edgar E. Iglesias
            case 0x5:
443 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
444 4acb54ba Edgar E. Iglesias
                break;
445 4acb54ba Edgar E. Iglesias
             case 0x7:
446 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_R[dc->rd], 0);
447 4acb54ba Edgar E. Iglesias
                break;
448 4acb54ba Edgar E. Iglesias
            case 0xb:
449 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
450 4acb54ba Edgar E. Iglesias
                break;
451 4acb54ba Edgar E. Iglesias
            case 0x2000:
452 4acb54ba Edgar E. Iglesias
            case 0x2001:
453 4acb54ba Edgar E. Iglesias
            case 0x2002:
454 4acb54ba Edgar E. Iglesias
            case 0x2003:
455 4acb54ba Edgar E. Iglesias
            case 0x2004:
456 4acb54ba Edgar E. Iglesias
            case 0x2005:
457 4acb54ba Edgar E. Iglesias
            case 0x2006:
458 4acb54ba Edgar E. Iglesias
            case 0x2007:
459 4acb54ba Edgar E. Iglesias
            case 0x2008:
460 4acb54ba Edgar E. Iglesias
            case 0x2009:
461 4acb54ba Edgar E. Iglesias
            case 0x200a:
462 4acb54ba Edgar E. Iglesias
            case 0x200b:
463 4acb54ba Edgar E. Iglesias
            case 0x200c:
464 4acb54ba Edgar E. Iglesias
                rn = sr & 0xf;
465 4acb54ba Edgar E. Iglesias
                tcg_gen_ld_tl(cpu_R[dc->rd],
466 4acb54ba Edgar E. Iglesias
                              cpu_env, offsetof(CPUState, pvr.regs[rn]));
467 4acb54ba Edgar E. Iglesias
                break;
468 4acb54ba Edgar E. Iglesias
            default:
469 4acb54ba Edgar E. Iglesias
                cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
470 4acb54ba Edgar E. Iglesias
                break;
471 4acb54ba Edgar E. Iglesias
        }
472 4acb54ba Edgar E. Iglesias
    }
473 4acb54ba Edgar E. Iglesias
}
474 4acb54ba Edgar E. Iglesias
475 4acb54ba Edgar E. Iglesias
/* 64-bit signed mul, lower result in d and upper in d2.  */
476 4acb54ba Edgar E. Iglesias
static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
477 4acb54ba Edgar E. Iglesias
{
478 4acb54ba Edgar E. Iglesias
    TCGv_i64 t0, t1;
479 4acb54ba Edgar E. Iglesias
480 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new_i64();
481 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new_i64();
482 4acb54ba Edgar E. Iglesias
483 4acb54ba Edgar E. Iglesias
    tcg_gen_ext_i32_i64(t0, a);
484 4acb54ba Edgar E. Iglesias
    tcg_gen_ext_i32_i64(t1, b);
485 4acb54ba Edgar E. Iglesias
    tcg_gen_mul_i64(t0, t0, t1);
486 4acb54ba Edgar E. Iglesias
487 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d, t0);
488 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_i64(t0, t0, 32);
489 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d2, t0);
490 4acb54ba Edgar E. Iglesias
491 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t0);
492 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t1);
493 4acb54ba Edgar E. Iglesias
}
494 4acb54ba Edgar E. Iglesias
495 4acb54ba Edgar E. Iglesias
/* 64-bit unsigned muls, lower result in d and upper in d2.  */
496 4acb54ba Edgar E. Iglesias
static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
497 4acb54ba Edgar E. Iglesias
{
498 4acb54ba Edgar E. Iglesias
    TCGv_i64 t0, t1;
499 4acb54ba Edgar E. Iglesias
500 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new_i64();
501 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new_i64();
502 4acb54ba Edgar E. Iglesias
503 4acb54ba Edgar E. Iglesias
    tcg_gen_extu_i32_i64(t0, a);
504 4acb54ba Edgar E. Iglesias
    tcg_gen_extu_i32_i64(t1, b);
505 4acb54ba Edgar E. Iglesias
    tcg_gen_mul_i64(t0, t0, t1);
506 4acb54ba Edgar E. Iglesias
507 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d, t0);
508 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_i64(t0, t0, 32);
509 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d2, t0);
510 4acb54ba Edgar E. Iglesias
511 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t0);
512 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t1);
513 4acb54ba Edgar E. Iglesias
}
514 4acb54ba Edgar E. Iglesias
515 4acb54ba Edgar E. Iglesias
/* Multiplier unit.  */
516 4acb54ba Edgar E. Iglesias
static void dec_mul(DisasContext *dc)
517 4acb54ba Edgar E. Iglesias
{
518 4acb54ba Edgar E. Iglesias
    TCGv d[2];
519 4acb54ba Edgar E. Iglesias
    unsigned int subcode;
520 4acb54ba Edgar E. Iglesias
521 4acb54ba Edgar E. Iglesias
    subcode = dc->imm & 3;
522 4acb54ba Edgar E. Iglesias
    d[0] = tcg_temp_new();
523 4acb54ba Edgar E. Iglesias
    d[1] = tcg_temp_new();
524 4acb54ba Edgar E. Iglesias
525 4acb54ba Edgar E. Iglesias
    if (dc->type_b) {
526 4acb54ba Edgar E. Iglesias
        LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
527 4acb54ba Edgar E. Iglesias
        t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
528 4acb54ba Edgar E. Iglesias
        goto done;
529 4acb54ba Edgar E. Iglesias
    }
530 4acb54ba Edgar E. Iglesias
531 4acb54ba Edgar E. Iglesias
    switch (subcode) {
532 4acb54ba Edgar E. Iglesias
        case 0:
533 4acb54ba Edgar E. Iglesias
            LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
534 4acb54ba Edgar E. Iglesias
            t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
535 4acb54ba Edgar E. Iglesias
            break;
536 4acb54ba Edgar E. Iglesias
        case 1:
537 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
538 4acb54ba Edgar E. Iglesias
            t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
539 4acb54ba Edgar E. Iglesias
            break;
540 4acb54ba Edgar E. Iglesias
        case 2:
541 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
542 4acb54ba Edgar E. Iglesias
            t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
543 4acb54ba Edgar E. Iglesias
            break;
544 4acb54ba Edgar E. Iglesias
        case 3:
545 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
546 4acb54ba Edgar E. Iglesias
            t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
547 4acb54ba Edgar E. Iglesias
            break;
548 4acb54ba Edgar E. Iglesias
        default:
549 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
550 4acb54ba Edgar E. Iglesias
            break;
551 4acb54ba Edgar E. Iglesias
    }
552 4acb54ba Edgar E. Iglesias
done:
553 4acb54ba Edgar E. Iglesias
    tcg_temp_free(d[0]);
554 4acb54ba Edgar E. Iglesias
    tcg_temp_free(d[1]);
555 4acb54ba Edgar E. Iglesias
}
556 4acb54ba Edgar E. Iglesias
557 4acb54ba Edgar E. Iglesias
/* Div unit.  */
558 4acb54ba Edgar E. Iglesias
static void dec_div(DisasContext *dc)
559 4acb54ba Edgar E. Iglesias
{
560 4acb54ba Edgar E. Iglesias
    unsigned int u;
561 4acb54ba Edgar E. Iglesias
562 4acb54ba Edgar E. Iglesias
    u = dc->imm & 2; 
563 4acb54ba Edgar E. Iglesias
    LOG_DIS("div\n");
564 4acb54ba Edgar E. Iglesias
565 4acb54ba Edgar E. Iglesias
    /* FIXME: support div by zero exceptions.  */
566 4acb54ba Edgar E. Iglesias
    if (u)
567 4acb54ba Edgar E. Iglesias
        gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
568 4acb54ba Edgar E. Iglesias
    else
569 4acb54ba Edgar E. Iglesias
        gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
570 4acb54ba Edgar E. Iglesias
    if (!dc->rd)
571 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], 0);
572 4acb54ba Edgar E. Iglesias
}
573 4acb54ba Edgar E. Iglesias
574 4acb54ba Edgar E. Iglesias
static void dec_barrel(DisasContext *dc)
575 4acb54ba Edgar E. Iglesias
{
576 4acb54ba Edgar E. Iglesias
    TCGv t0;
577 4acb54ba Edgar E. Iglesias
    unsigned int s, t;
578 4acb54ba Edgar E. Iglesias
579 4acb54ba Edgar E. Iglesias
    s = dc->imm & (1 << 10);
580 4acb54ba Edgar E. Iglesias
    t = dc->imm & (1 << 9);
581 4acb54ba Edgar E. Iglesias
582 4acb54ba Edgar E. Iglesias
    LOG_DIS("bs%s%s r%d r%d r%d\n",
583 4acb54ba Edgar E. Iglesias
            s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
584 4acb54ba Edgar E. Iglesias
585 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
586 4acb54ba Edgar E. Iglesias
587 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
588 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, 31);
589 4acb54ba Edgar E. Iglesias
590 4acb54ba Edgar E. Iglesias
    if (s)
591 4acb54ba Edgar E. Iglesias
        tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
592 4acb54ba Edgar E. Iglesias
    else {
593 4acb54ba Edgar E. Iglesias
        if (t)
594 4acb54ba Edgar E. Iglesias
            tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
595 4acb54ba Edgar E. Iglesias
        else
596 4acb54ba Edgar E. Iglesias
            tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
597 4acb54ba Edgar E. Iglesias
    }
598 4acb54ba Edgar E. Iglesias
}
599 4acb54ba Edgar E. Iglesias
600 4acb54ba Edgar E. Iglesias
static void dec_bit(DisasContext *dc)
601 4acb54ba Edgar E. Iglesias
{
602 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
603 4acb54ba Edgar E. Iglesias
    unsigned int op;
604 4acb54ba Edgar E. Iglesias
605 4acb54ba Edgar E. Iglesias
    op = dc->ir & ((1 << 8) - 1);
606 4acb54ba Edgar E. Iglesias
    switch (op) {
607 4acb54ba Edgar E. Iglesias
        case 0x21:
608 4acb54ba Edgar E. Iglesias
            /* src.  */
609 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
610 4acb54ba Edgar E. Iglesias
611 4acb54ba Edgar E. Iglesias
            LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
612 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
613 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
614 4acb54ba Edgar E. Iglesias
                t1 = tcg_temp_new();
615 4acb54ba Edgar E. Iglesias
                read_carry(dc, t1);
616 4acb54ba Edgar E. Iglesias
                tcg_gen_shli_tl(t1, t1, 31);
617 4acb54ba Edgar E. Iglesias
618 4acb54ba Edgar E. Iglesias
                tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
619 4acb54ba Edgar E. Iglesias
                tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
620 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t1);
621 4acb54ba Edgar E. Iglesias
            }
622 4acb54ba Edgar E. Iglesias
623 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
624 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
625 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
626 4acb54ba Edgar E. Iglesias
            break;
627 4acb54ba Edgar E. Iglesias
628 4acb54ba Edgar E. Iglesias
        case 0x1:
629 4acb54ba Edgar E. Iglesias
        case 0x41:
630 4acb54ba Edgar E. Iglesias
            /* srl.  */
631 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
632 4acb54ba Edgar E. Iglesias
            LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
633 4acb54ba Edgar E. Iglesias
634 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
635 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
636 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
637 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
638 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
639 4acb54ba Edgar E. Iglesias
                if (op == 0x41)
640 4acb54ba Edgar E. Iglesias
                    tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
641 4acb54ba Edgar E. Iglesias
                else
642 4acb54ba Edgar E. Iglesias
                    tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
643 4acb54ba Edgar E. Iglesias
            }
644 4acb54ba Edgar E. Iglesias
            break;
645 4acb54ba Edgar E. Iglesias
        case 0x60:
646 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
647 4acb54ba Edgar E. Iglesias
            tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
648 4acb54ba Edgar E. Iglesias
            break;
649 4acb54ba Edgar E. Iglesias
        case 0x61:
650 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
651 4acb54ba Edgar E. Iglesias
            tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
652 4acb54ba Edgar E. Iglesias
            break;
653 4acb54ba Edgar E. Iglesias
        case 0x64:
654 4acb54ba Edgar E. Iglesias
            /* wdc.  */
655 4acb54ba Edgar E. Iglesias
            LOG_DIS("wdc r%d\n", dc->ra);
656 4acb54ba Edgar E. Iglesias
            break;
657 4acb54ba Edgar E. Iglesias
        case 0x68:
658 4acb54ba Edgar E. Iglesias
            /* wic.  */
659 4acb54ba Edgar E. Iglesias
            LOG_DIS("wic r%d\n", dc->ra);
660 4acb54ba Edgar E. Iglesias
            break;
661 4acb54ba Edgar E. Iglesias
        default:
662 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
663 4acb54ba Edgar E. Iglesias
                     dc->pc, op, dc->rd, dc->ra, dc->rb);
664 4acb54ba Edgar E. Iglesias
            break;
665 4acb54ba Edgar E. Iglesias
    }
666 4acb54ba Edgar E. Iglesias
}
667 4acb54ba Edgar E. Iglesias
668 4acb54ba Edgar E. Iglesias
static inline void sync_jmpstate(DisasContext *dc)
669 4acb54ba Edgar E. Iglesias
{
670 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
671 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_INDIRECT;
672 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
673 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
674 4acb54ba Edgar E. Iglesias
    }
675 4acb54ba Edgar E. Iglesias
}
676 4acb54ba Edgar E. Iglesias
677 4acb54ba Edgar E. Iglesias
static void dec_imm(DisasContext *dc)
678 4acb54ba Edgar E. Iglesias
{
679 4acb54ba Edgar E. Iglesias
    LOG_DIS("imm %x\n", dc->imm << 16);
680 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_imm, (dc->imm << 16));
681 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= IMM_FLAG;
682 4acb54ba Edgar E. Iglesias
    dc->clear_imm = 0;
683 4acb54ba Edgar E. Iglesias
}
684 4acb54ba Edgar E. Iglesias
685 4acb54ba Edgar E. Iglesias
static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
686 4acb54ba Edgar E. Iglesias
                            unsigned int size)
687 4acb54ba Edgar E. Iglesias
{
688 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
689 4acb54ba Edgar E. Iglesias
690 4acb54ba Edgar E. Iglesias
    if (size == 1) {
691 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld8u(dst, addr, mem_index);
692 4acb54ba Edgar E. Iglesias
    } else if (size == 2) {
693 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld16u(dst, addr, mem_index);
694 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
695 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld32u(dst, addr, mem_index);
696 4acb54ba Edgar E. Iglesias
    } else
697 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect load size %d\n", size);
698 4acb54ba Edgar E. Iglesias
}
699 4acb54ba Edgar E. Iglesias
700 4acb54ba Edgar E. Iglesias
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
701 4acb54ba Edgar E. Iglesias
{
702 4acb54ba Edgar E. Iglesias
    unsigned int extimm = dc->tb_flags & IMM_FLAG;
703 4acb54ba Edgar E. Iglesias
704 4acb54ba Edgar E. Iglesias
    /* Treat the fast cases first.  */
705 4acb54ba Edgar E. Iglesias
    if (!dc->type_b) {
706 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
707 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
708 4acb54ba Edgar E. Iglesias
        return t;
709 4acb54ba Edgar E. Iglesias
    }
710 4acb54ba Edgar E. Iglesias
    /* Immediate.  */
711 4acb54ba Edgar E. Iglesias
    if (!extimm) {
712 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0) {
713 4acb54ba Edgar E. Iglesias
            return &cpu_R[dc->ra];
714 4acb54ba Edgar E. Iglesias
        }
715 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
716 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
717 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
718 4acb54ba Edgar E. Iglesias
    } else {
719 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
720 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
721 4acb54ba Edgar E. Iglesias
    }
722 4acb54ba Edgar E. Iglesias
723 4acb54ba Edgar E. Iglesias
    return t;
724 4acb54ba Edgar E. Iglesias
}
725 4acb54ba Edgar E. Iglesias
726 4acb54ba Edgar E. Iglesias
static void dec_load(DisasContext *dc)
727 4acb54ba Edgar E. Iglesias
{
728 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
729 4acb54ba Edgar E. Iglesias
    unsigned int size;
730 4acb54ba Edgar E. Iglesias
731 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
732 4acb54ba Edgar E. Iglesias
733 4acb54ba Edgar E. Iglesias
    LOG_DIS("l %x %d\n", dc->opcode, size);
734 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
735 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
736 4acb54ba Edgar E. Iglesias
737 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
738 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
739 4acb54ba Edgar E. Iglesias
    if (dc->rd)
740 4acb54ba Edgar E. Iglesias
        gen_load(dc, cpu_R[dc->rd], *addr, size);
741 4acb54ba Edgar E. Iglesias
    else {
742 4acb54ba Edgar E. Iglesias
        gen_load(dc, env_imm, *addr, size);
743 4acb54ba Edgar E. Iglesias
    }
744 4acb54ba Edgar E. Iglesias
745 4acb54ba Edgar E. Iglesias
    if (addr == &t)
746 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
747 4acb54ba Edgar E. Iglesias
}
748 4acb54ba Edgar E. Iglesias
749 4acb54ba Edgar E. Iglesias
static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
750 4acb54ba Edgar E. Iglesias
                      unsigned int size)
751 4acb54ba Edgar E. Iglesias
{
752 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
753 4acb54ba Edgar E. Iglesias
754 4acb54ba Edgar E. Iglesias
    if (size == 1)
755 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st8(val, addr, mem_index);
756 4acb54ba Edgar E. Iglesias
    else if (size == 2) {
757 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st16(val, addr, mem_index);
758 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
759 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st32(val, addr, mem_index);
760 4acb54ba Edgar E. Iglesias
    } else
761 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect store size %d\n", size);
762 4acb54ba Edgar E. Iglesias
}
763 4acb54ba Edgar E. Iglesias
764 4acb54ba Edgar E. Iglesias
static void dec_store(DisasContext *dc)
765 4acb54ba Edgar E. Iglesias
{
766 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
767 4acb54ba Edgar E. Iglesias
    unsigned int size;
768 4acb54ba Edgar E. Iglesias
769 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
770 4acb54ba Edgar E. Iglesias
771 4acb54ba Edgar E. Iglesias
    LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
772 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
773 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
774 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
775 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
776 4acb54ba Edgar E. Iglesias
    gen_store(dc, *addr, cpu_R[dc->rd], size);
777 4acb54ba Edgar E. Iglesias
    if (addr == &t)
778 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
779 4acb54ba Edgar E. Iglesias
}
780 4acb54ba Edgar E. Iglesias
781 4acb54ba Edgar E. Iglesias
static inline void eval_cc(DisasContext *dc, unsigned int cc,
782 4acb54ba Edgar E. Iglesias
                           TCGv d, TCGv a, TCGv b)
783 4acb54ba Edgar E. Iglesias
{
784 4acb54ba Edgar E. Iglesias
    int l1;
785 4acb54ba Edgar E. Iglesias
786 4acb54ba Edgar E. Iglesias
    switch (cc) {
787 4acb54ba Edgar E. Iglesias
        case CC_EQ:
788 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
789 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
790 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1);
791 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
792 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
793 4acb54ba Edgar E. Iglesias
            break;
794 4acb54ba Edgar E. Iglesias
        case CC_NE:
795 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
796 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
797 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1);
798 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
799 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
800 4acb54ba Edgar E. Iglesias
            break;
801 4acb54ba Edgar E. Iglesias
        case CC_LT:
802 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
803 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
804 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1);
805 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
806 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
807 4acb54ba Edgar E. Iglesias
            break;
808 4acb54ba Edgar E. Iglesias
        case CC_LE:
809 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
810 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
811 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1);
812 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
813 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
814 4acb54ba Edgar E. Iglesias
            break;
815 4acb54ba Edgar E. Iglesias
        case CC_GE:
816 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
817 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
818 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1);
819 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
820 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
821 4acb54ba Edgar E. Iglesias
            break;
822 4acb54ba Edgar E. Iglesias
        case CC_GT:
823 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
824 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
825 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1);
826 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
827 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
828 4acb54ba Edgar E. Iglesias
            break;
829 4acb54ba Edgar E. Iglesias
        default:
830 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
831 4acb54ba Edgar E. Iglesias
            break;
832 4acb54ba Edgar E. Iglesias
    }
833 4acb54ba Edgar E. Iglesias
}
834 4acb54ba Edgar E. Iglesias
835 4acb54ba Edgar E. Iglesias
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
836 4acb54ba Edgar E. Iglesias
{
837 4acb54ba Edgar E. Iglesias
    int l1;
838 4acb54ba Edgar E. Iglesias
839 4acb54ba Edgar E. Iglesias
    l1 = gen_new_label();
840 4acb54ba Edgar E. Iglesias
    /* Conditional jmp.  */
841 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
842 4acb54ba Edgar E. Iglesias
    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
843 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
844 4acb54ba Edgar E. Iglesias
    gen_set_label(l1);
845 4acb54ba Edgar E. Iglesias
}
846 4acb54ba Edgar E. Iglesias
847 4acb54ba Edgar E. Iglesias
static void dec_bcc(DisasContext *dc)
848 4acb54ba Edgar E. Iglesias
{
849 4acb54ba Edgar E. Iglesias
    unsigned int cc;
850 4acb54ba Edgar E. Iglesias
    unsigned int dslot;
851 4acb54ba Edgar E. Iglesias
852 4acb54ba Edgar E. Iglesias
    cc = EXTRACT_FIELD(dc->ir, 21, 23);
853 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 25);
854 4acb54ba Edgar E. Iglesias
    LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
855 4acb54ba Edgar E. Iglesias
856 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
857 4acb54ba Edgar E. Iglesias
    if (dslot) {
858 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
859 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
860 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
861 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
862 4acb54ba Edgar E. Iglesias
    }
863 4acb54ba Edgar E. Iglesias
864 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btarget, dc->pc);
865 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
866 4acb54ba Edgar E. Iglesias
    eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
867 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
868 4acb54ba Edgar E. Iglesias
}
869 4acb54ba Edgar E. Iglesias
870 4acb54ba Edgar E. Iglesias
static void dec_br(DisasContext *dc)
871 4acb54ba Edgar E. Iglesias
{
872 4acb54ba Edgar E. Iglesias
    unsigned int dslot, link, abs;
873 4acb54ba Edgar E. Iglesias
874 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 20);
875 4acb54ba Edgar E. Iglesias
    abs = dc->ir & (1 << 19);
876 4acb54ba Edgar E. Iglesias
    link = dc->ir & (1 << 18);
877 4acb54ba Edgar E. Iglesias
    LOG_DIS("br%s%s%s%s imm=%x\n",
878 4acb54ba Edgar E. Iglesias
             abs ? "a" : "", link ? "l" : "",
879 4acb54ba Edgar E. Iglesias
             dc->type_b ? "i" : "", dslot ? "d" : "",
880 4acb54ba Edgar E. Iglesias
             dc->imm);
881 4acb54ba Edgar E. Iglesias
882 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
883 4acb54ba Edgar E. Iglesias
    if (dslot) {
884 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
885 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
886 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
887 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
888 4acb54ba Edgar E. Iglesias
    }
889 4acb54ba Edgar E. Iglesias
    if (link && dc->rd)
890 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
891 4acb54ba Edgar E. Iglesias
892 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
893 4acb54ba Edgar E. Iglesias
    if (abs) {
894 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_btaken, 1);
895 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
896 4acb54ba Edgar E. Iglesias
        if (link && !(dc->tb_flags & IMM_FLAG)
897 4acb54ba Edgar E. Iglesias
            && (dc->imm == 8 || dc->imm == 0x18))
898 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_BREAK);
899 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0)
900 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_DEBUG);
901 4acb54ba Edgar E. Iglesias
    } else {
902 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & IMM_FLAG) {
903 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
904 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->pc);
905 4acb54ba Edgar E. Iglesias
            tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
906 4acb54ba Edgar E. Iglesias
        } else {
907 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_DIRECT;
908 4acb54ba Edgar E. Iglesias
            dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
909 4acb54ba Edgar E. Iglesias
        }
910 4acb54ba Edgar E. Iglesias
    }
911 4acb54ba Edgar E. Iglesias
}
912 4acb54ba Edgar E. Iglesias
913 4acb54ba Edgar E. Iglesias
static inline void do_rti(DisasContext *dc)
914 4acb54ba Edgar E. Iglesias
{
915 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
916 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
917 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
918 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
919 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
920 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
921 4acb54ba Edgar E. Iglesias
922 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
923 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
924 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
925 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
926 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
927 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTI_FLAG;
928 4acb54ba Edgar E. Iglesias
}
929 4acb54ba Edgar E. Iglesias
930 4acb54ba Edgar E. Iglesias
static inline void do_rtb(DisasContext *dc)
931 4acb54ba Edgar E. Iglesias
{
932 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
933 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
934 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
935 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
936 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
937 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
938 4acb54ba Edgar E. Iglesias
939 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
940 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
941 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
942 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
943 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
944 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTB_FLAG;
945 4acb54ba Edgar E. Iglesias
}
946 4acb54ba Edgar E. Iglesias
947 4acb54ba Edgar E. Iglesias
static inline void do_rte(DisasContext *dc)
948 4acb54ba Edgar E. Iglesias
{
949 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
950 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
951 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
952 4acb54ba Edgar E. Iglesias
953 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
954 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
955 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
956 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
957 4acb54ba Edgar E. Iglesias
958 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
959 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
960 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
961 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
962 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
963 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTE_FLAG;
964 4acb54ba Edgar E. Iglesias
}
965 4acb54ba Edgar E. Iglesias
966 4acb54ba Edgar E. Iglesias
static void dec_rts(DisasContext *dc)
967 4acb54ba Edgar E. Iglesias
{
968 4acb54ba Edgar E. Iglesias
    unsigned int b_bit, i_bit, e_bit;
969 4acb54ba Edgar E. Iglesias
970 4acb54ba Edgar E. Iglesias
    i_bit = dc->ir & (1 << 21);
971 4acb54ba Edgar E. Iglesias
    b_bit = dc->ir & (1 << 22);
972 4acb54ba Edgar E. Iglesias
    e_bit = dc->ir & (1 << 23);
973 4acb54ba Edgar E. Iglesias
974 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 2;
975 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= D_FLAG;
976 4acb54ba Edgar E. Iglesias
    tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
977 4acb54ba Edgar E. Iglesias
                  cpu_env, offsetof(CPUState, bimm));
978 4acb54ba Edgar E. Iglesias
979 4acb54ba Edgar E. Iglesias
    if (i_bit) {
980 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtid ir=%x\n", dc->ir);
981 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTI_FLAG;
982 4acb54ba Edgar E. Iglesias
    } else if (b_bit) {
983 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtbd ir=%x\n", dc->ir);
984 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTB_FLAG;
985 4acb54ba Edgar E. Iglesias
    } else if (e_bit) {
986 4acb54ba Edgar E. Iglesias
        LOG_DIS("rted ir=%x\n", dc->ir);
987 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTE_FLAG;
988 4acb54ba Edgar E. Iglesias
    } else
989 4acb54ba Edgar E. Iglesias
        LOG_DIS("rts ir=%x\n", dc->ir);
990 4acb54ba Edgar E. Iglesias
991 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btaken, 1);
992 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
993 4acb54ba Edgar E. Iglesias
}
994 4acb54ba Edgar E. Iglesias
995 4acb54ba Edgar E. Iglesias
static void dec_null(DisasContext *dc)
996 4acb54ba Edgar E. Iglesias
{
997 4acb54ba Edgar E. Iglesias
    qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
998 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
999 4acb54ba Edgar E. Iglesias
}
1000 4acb54ba Edgar E. Iglesias
1001 4acb54ba Edgar E. Iglesias
static struct decoder_info {
1002 4acb54ba Edgar E. Iglesias
    struct {
1003 4acb54ba Edgar E. Iglesias
        uint32_t bits;
1004 4acb54ba Edgar E. Iglesias
        uint32_t mask;
1005 4acb54ba Edgar E. Iglesias
    };
1006 4acb54ba Edgar E. Iglesias
    void (*dec)(DisasContext *dc);
1007 4acb54ba Edgar E. Iglesias
} decinfo[] = {
1008 4acb54ba Edgar E. Iglesias
    {DEC_ADD, dec_add},
1009 4acb54ba Edgar E. Iglesias
    {DEC_SUB, dec_sub},
1010 4acb54ba Edgar E. Iglesias
    {DEC_AND, dec_and},
1011 4acb54ba Edgar E. Iglesias
    {DEC_XOR, dec_xor},
1012 4acb54ba Edgar E. Iglesias
    {DEC_OR, dec_or},
1013 4acb54ba Edgar E. Iglesias
    {DEC_BIT, dec_bit},
1014 4acb54ba Edgar E. Iglesias
    {DEC_BARREL, dec_barrel},
1015 4acb54ba Edgar E. Iglesias
    {DEC_LD, dec_load},
1016 4acb54ba Edgar E. Iglesias
    {DEC_ST, dec_store},
1017 4acb54ba Edgar E. Iglesias
    {DEC_IMM, dec_imm},
1018 4acb54ba Edgar E. Iglesias
    {DEC_BR, dec_br},
1019 4acb54ba Edgar E. Iglesias
    {DEC_BCC, dec_bcc},
1020 4acb54ba Edgar E. Iglesias
    {DEC_RTS, dec_rts},
1021 4acb54ba Edgar E. Iglesias
    {DEC_MUL, dec_mul},
1022 4acb54ba Edgar E. Iglesias
    {DEC_DIV, dec_div},
1023 4acb54ba Edgar E. Iglesias
    {DEC_MSR, dec_msr},
1024 4acb54ba Edgar E. Iglesias
    {{0, 0}, dec_null}
1025 4acb54ba Edgar E. Iglesias
};
1026 4acb54ba Edgar E. Iglesias
1027 4acb54ba Edgar E. Iglesias
static inline void decode(DisasContext *dc)
1028 4acb54ba Edgar E. Iglesias
{
1029 4acb54ba Edgar E. Iglesias
    uint32_t ir;
1030 4acb54ba Edgar E. Iglesias
    int i;
1031 4acb54ba Edgar E. Iglesias
1032 4acb54ba Edgar E. Iglesias
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
1033 4acb54ba Edgar E. Iglesias
        tcg_gen_debug_insn_start(dc->pc);
1034 4acb54ba Edgar E. Iglesias
1035 4acb54ba Edgar E. Iglesias
    dc->ir = ir = ldl_code(dc->pc);
1036 4acb54ba Edgar E. Iglesias
    LOG_DIS("%8.8x\t", dc->ir);
1037 4acb54ba Edgar E. Iglesias
1038 4acb54ba Edgar E. Iglesias
    if (dc->ir)
1039 4acb54ba Edgar E. Iglesias
        dc->nr_nops = 0;
1040 4acb54ba Edgar E. Iglesias
    else {
1041 4acb54ba Edgar E. Iglesias
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1042 4acb54ba Edgar E. Iglesias
        dc->nr_nops++;
1043 4acb54ba Edgar E. Iglesias
        if (dc->nr_nops > 4)
1044 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "fetching nop sequence\n");
1045 4acb54ba Edgar E. Iglesias
    }
1046 4acb54ba Edgar E. Iglesias
    /* bit 2 seems to indicate insn type.  */
1047 4acb54ba Edgar E. Iglesias
    dc->type_b = ir & (1 << 29);
1048 4acb54ba Edgar E. Iglesias
1049 4acb54ba Edgar E. Iglesias
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1050 4acb54ba Edgar E. Iglesias
    dc->rd = EXTRACT_FIELD(ir, 21, 25);
1051 4acb54ba Edgar E. Iglesias
    dc->ra = EXTRACT_FIELD(ir, 16, 20);
1052 4acb54ba Edgar E. Iglesias
    dc->rb = EXTRACT_FIELD(ir, 11, 15);
1053 4acb54ba Edgar E. Iglesias
    dc->imm = EXTRACT_FIELD(ir, 0, 15);
1054 4acb54ba Edgar E. Iglesias
1055 4acb54ba Edgar E. Iglesias
    /* Large switch for all insns.  */
1056 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1057 4acb54ba Edgar E. Iglesias
        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1058 4acb54ba Edgar E. Iglesias
            decinfo[i].dec(dc);
1059 4acb54ba Edgar E. Iglesias
            break;
1060 4acb54ba Edgar E. Iglesias
        }
1061 4acb54ba Edgar E. Iglesias
    }
1062 4acb54ba Edgar E. Iglesias
}
1063 4acb54ba Edgar E. Iglesias
1064 4acb54ba Edgar E. Iglesias
1065 4acb54ba Edgar E. Iglesias
static void check_breakpoint(CPUState *env, DisasContext *dc)
1066 4acb54ba Edgar E. Iglesias
{
1067 4acb54ba Edgar E. Iglesias
    CPUBreakpoint *bp;
1068 4acb54ba Edgar E. Iglesias
1069 4acb54ba Edgar E. Iglesias
    if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
1070 4acb54ba Edgar E. Iglesias
        TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1071 4acb54ba Edgar E. Iglesias
            if (bp->pc == dc->pc) {
1072 4acb54ba Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1073 4acb54ba Edgar E. Iglesias
                dc->is_jmp = DISAS_UPDATE;
1074 4acb54ba Edgar E. Iglesias
             }
1075 4acb54ba Edgar E. Iglesias
        }
1076 4acb54ba Edgar E. Iglesias
    }
1077 4acb54ba Edgar E. Iglesias
}
1078 4acb54ba Edgar E. Iglesias
1079 4acb54ba Edgar E. Iglesias
/* generate intermediate code for basic block 'tb'.  */
1080 4acb54ba Edgar E. Iglesias
static void
1081 4acb54ba Edgar E. Iglesias
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
1082 4acb54ba Edgar E. Iglesias
                               int search_pc)
1083 4acb54ba Edgar E. Iglesias
{
1084 4acb54ba Edgar E. Iglesias
    uint16_t *gen_opc_end;
1085 4acb54ba Edgar E. Iglesias
    uint32_t pc_start;
1086 4acb54ba Edgar E. Iglesias
    int j, lj;
1087 4acb54ba Edgar E. Iglesias
    struct DisasContext ctx;
1088 4acb54ba Edgar E. Iglesias
    struct DisasContext *dc = &ctx;
1089 4acb54ba Edgar E. Iglesias
    uint32_t next_page_start, org_flags;
1090 4acb54ba Edgar E. Iglesias
    target_ulong npc;
1091 4acb54ba Edgar E. Iglesias
    int num_insns;
1092 4acb54ba Edgar E. Iglesias
    int max_insns;
1093 4acb54ba Edgar E. Iglesias
1094 4acb54ba Edgar E. Iglesias
    qemu_log_try_set_file(stderr);
1095 4acb54ba Edgar E. Iglesias
1096 4acb54ba Edgar E. Iglesias
    pc_start = tb->pc;
1097 4acb54ba Edgar E. Iglesias
    dc->env = env;
1098 4acb54ba Edgar E. Iglesias
    dc->tb = tb;
1099 4acb54ba Edgar E. Iglesias
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1100 4acb54ba Edgar E. Iglesias
1101 4acb54ba Edgar E. Iglesias
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1102 4acb54ba Edgar E. Iglesias
1103 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_NEXT;
1104 4acb54ba Edgar E. Iglesias
    dc->jmp = 0;
1105 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1106 4acb54ba Edgar E. Iglesias
    dc->ppc = pc_start;
1107 4acb54ba Edgar E. Iglesias
    dc->pc = pc_start;
1108 4acb54ba Edgar E. Iglesias
    dc->cache_pc = -1;
1109 4acb54ba Edgar E. Iglesias
    dc->singlestep_enabled = env->singlestep_enabled;
1110 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 0;
1111 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 0;
1112 4acb54ba Edgar E. Iglesias
    dc->nr_nops = 0;
1113 4acb54ba Edgar E. Iglesias
1114 4acb54ba Edgar E. Iglesias
    if (pc_start & 3)
1115 4acb54ba Edgar E. Iglesias
        cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
1116 4acb54ba Edgar E. Iglesias
1117 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1118 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1119 4acb54ba Edgar E. Iglesias
        qemu_log("--------------\n");
1120 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1121 4acb54ba Edgar E. Iglesias
#endif
1122 4acb54ba Edgar E. Iglesias
    }
1123 4acb54ba Edgar E. Iglesias
1124 4acb54ba Edgar E. Iglesias
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1125 4acb54ba Edgar E. Iglesias
    lj = -1;
1126 4acb54ba Edgar E. Iglesias
    num_insns = 0;
1127 4acb54ba Edgar E. Iglesias
    max_insns = tb->cflags & CF_COUNT_MASK;
1128 4acb54ba Edgar E. Iglesias
    if (max_insns == 0)
1129 4acb54ba Edgar E. Iglesias
        max_insns = CF_COUNT_MASK;
1130 4acb54ba Edgar E. Iglesias
1131 4acb54ba Edgar E. Iglesias
    gen_icount_start();
1132 4acb54ba Edgar E. Iglesias
    do
1133 4acb54ba Edgar E. Iglesias
    {
1134 4acb54ba Edgar E. Iglesias
#if SIM_COMPAT
1135 4acb54ba Edgar E. Iglesias
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1136 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1137 4acb54ba Edgar E. Iglesias
            gen_helper_debug();
1138 4acb54ba Edgar E. Iglesias
        }
1139 4acb54ba Edgar E. Iglesias
#endif
1140 4acb54ba Edgar E. Iglesias
        check_breakpoint(env, dc);
1141 4acb54ba Edgar E. Iglesias
1142 4acb54ba Edgar E. Iglesias
        if (search_pc) {
1143 4acb54ba Edgar E. Iglesias
            j = gen_opc_ptr - gen_opc_buf;
1144 4acb54ba Edgar E. Iglesias
            if (lj < j) {
1145 4acb54ba Edgar E. Iglesias
                lj++;
1146 4acb54ba Edgar E. Iglesias
                while (lj < j)
1147 4acb54ba Edgar E. Iglesias
                    gen_opc_instr_start[lj++] = 0;
1148 4acb54ba Edgar E. Iglesias
            }
1149 4acb54ba Edgar E. Iglesias
            gen_opc_pc[lj] = dc->pc;
1150 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj] = 1;
1151 4acb54ba Edgar E. Iglesias
                        gen_opc_icount[lj] = num_insns;
1152 4acb54ba Edgar E. Iglesias
        }
1153 4acb54ba Edgar E. Iglesias
1154 4acb54ba Edgar E. Iglesias
        /* Pretty disas.  */
1155 4acb54ba Edgar E. Iglesias
        LOG_DIS("%8.8x:\t", dc->pc);
1156 4acb54ba Edgar E. Iglesias
1157 4acb54ba Edgar E. Iglesias
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1158 4acb54ba Edgar E. Iglesias
            gen_io_start();
1159 4acb54ba Edgar E. Iglesias
1160 4acb54ba Edgar E. Iglesias
        dc->clear_imm = 1;
1161 4acb54ba Edgar E. Iglesias
        decode(dc);
1162 4acb54ba Edgar E. Iglesias
        if (dc->clear_imm)
1163 4acb54ba Edgar E. Iglesias
            dc->tb_flags &= ~IMM_FLAG;
1164 4acb54ba Edgar E. Iglesias
        dc->ppc = dc->pc;
1165 4acb54ba Edgar E. Iglesias
        dc->pc += 4;
1166 4acb54ba Edgar E. Iglesias
        num_insns++;
1167 4acb54ba Edgar E. Iglesias
1168 4acb54ba Edgar E. Iglesias
        if (dc->delayed_branch) {
1169 4acb54ba Edgar E. Iglesias
            dc->delayed_branch--;
1170 4acb54ba Edgar E. Iglesias
            if (!dc->delayed_branch) {
1171 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTI_FLAG)
1172 4acb54ba Edgar E. Iglesias
                    do_rti(dc);
1173 4acb54ba Edgar E. Iglesias
                 if (dc->tb_flags & DRTB_FLAG)
1174 4acb54ba Edgar E. Iglesias
                    do_rtb(dc);
1175 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTE_FLAG)
1176 4acb54ba Edgar E. Iglesias
                    do_rte(dc);
1177 4acb54ba Edgar E. Iglesias
                /* Clear the delay slot flag.  */
1178 4acb54ba Edgar E. Iglesias
                dc->tb_flags &= ~D_FLAG;
1179 4acb54ba Edgar E. Iglesias
                /* If it is a direct jump, try direct chaining.  */
1180 4acb54ba Edgar E. Iglesias
                if (dc->jmp != JMP_DIRECT) {
1181 4acb54ba Edgar E. Iglesias
                    eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1182 4acb54ba Edgar E. Iglesias
                    dc->is_jmp = DISAS_JUMP;
1183 4acb54ba Edgar E. Iglesias
                }
1184 4acb54ba Edgar E. Iglesias
                break;
1185 4acb54ba Edgar E. Iglesias
            }
1186 4acb54ba Edgar E. Iglesias
        }
1187 4acb54ba Edgar E. Iglesias
        if (env->singlestep_enabled)
1188 4acb54ba Edgar E. Iglesias
            break;
1189 4acb54ba Edgar E. Iglesias
    } while (!dc->is_jmp && !dc->cpustate_changed
1190 4acb54ba Edgar E. Iglesias
         && gen_opc_ptr < gen_opc_end
1191 4acb54ba Edgar E. Iglesias
                 && !singlestep
1192 4acb54ba Edgar E. Iglesias
         && (dc->pc < next_page_start)
1193 4acb54ba Edgar E. Iglesias
                 && num_insns < max_insns);
1194 4acb54ba Edgar E. Iglesias
1195 4acb54ba Edgar E. Iglesias
    npc = dc->pc;
1196 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
1197 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & D_FLAG) {
1198 4acb54ba Edgar E. Iglesias
            dc->is_jmp = DISAS_UPDATE;
1199 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1200 4acb54ba Edgar E. Iglesias
            sync_jmpstate(dc);
1201 4acb54ba Edgar E. Iglesias
        } else
1202 4acb54ba Edgar E. Iglesias
            npc = dc->jmp_pc;
1203 4acb54ba Edgar E. Iglesias
    }
1204 4acb54ba Edgar E. Iglesias
1205 4acb54ba Edgar E. Iglesias
    if (tb->cflags & CF_LAST_IO)
1206 4acb54ba Edgar E. Iglesias
        gen_io_end();
1207 4acb54ba Edgar E. Iglesias
    /* Force an update if the per-tb cpu state has changed.  */
1208 4acb54ba Edgar E. Iglesias
    if (dc->is_jmp == DISAS_NEXT
1209 4acb54ba Edgar E. Iglesias
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1210 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
1211 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1212 4acb54ba Edgar E. Iglesias
    }
1213 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1214 4acb54ba Edgar E. Iglesias
1215 4acb54ba Edgar E. Iglesias
    if (unlikely(env->singlestep_enabled)) {
1216 4acb54ba Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_DEBUG);
1217 4acb54ba Edgar E. Iglesias
        if (dc->is_jmp == DISAS_NEXT)
1218 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1219 4acb54ba Edgar E. Iglesias
    } else {
1220 4acb54ba Edgar E. Iglesias
        switch(dc->is_jmp) {
1221 4acb54ba Edgar E. Iglesias
            case DISAS_NEXT:
1222 4acb54ba Edgar E. Iglesias
                gen_goto_tb(dc, 1, npc);
1223 4acb54ba Edgar E. Iglesias
                break;
1224 4acb54ba Edgar E. Iglesias
            default:
1225 4acb54ba Edgar E. Iglesias
            case DISAS_JUMP:
1226 4acb54ba Edgar E. Iglesias
            case DISAS_UPDATE:
1227 4acb54ba Edgar E. Iglesias
                /* indicate that the hash table must be used
1228 4acb54ba Edgar E. Iglesias
                   to find the next TB */
1229 4acb54ba Edgar E. Iglesias
                tcg_gen_exit_tb(0);
1230 4acb54ba Edgar E. Iglesias
                break;
1231 4acb54ba Edgar E. Iglesias
            case DISAS_TB_JUMP:
1232 4acb54ba Edgar E. Iglesias
                /* nothing more to generate */
1233 4acb54ba Edgar E. Iglesias
                break;
1234 4acb54ba Edgar E. Iglesias
        }
1235 4acb54ba Edgar E. Iglesias
    }
1236 4acb54ba Edgar E. Iglesias
    gen_icount_end(tb, num_insns);
1237 4acb54ba Edgar E. Iglesias
    *gen_opc_ptr = INDEX_op_end;
1238 4acb54ba Edgar E. Iglesias
    if (search_pc) {
1239 4acb54ba Edgar E. Iglesias
        j = gen_opc_ptr - gen_opc_buf;
1240 4acb54ba Edgar E. Iglesias
        lj++;
1241 4acb54ba Edgar E. Iglesias
        while (lj <= j)
1242 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj++] = 0;
1243 4acb54ba Edgar E. Iglesias
    } else {
1244 4acb54ba Edgar E. Iglesias
        tb->size = dc->pc - pc_start;
1245 4acb54ba Edgar E. Iglesias
                tb->icount = num_insns;
1246 4acb54ba Edgar E. Iglesias
    }
1247 4acb54ba Edgar E. Iglesias
1248 4acb54ba Edgar E. Iglesias
#ifdef DEBUG_DISAS
1249 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1250 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1251 4acb54ba Edgar E. Iglesias
        qemu_log("\n");
1252 4acb54ba Edgar E. Iglesias
#if DISAS_GNU
1253 4acb54ba Edgar E. Iglesias
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1254 4acb54ba Edgar E. Iglesias
#endif
1255 4acb54ba Edgar E. Iglesias
        qemu_log("\nisize=%d osize=%zd\n",
1256 4acb54ba Edgar E. Iglesias
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1257 4acb54ba Edgar E. Iglesias
    }
1258 4acb54ba Edgar E. Iglesias
#endif
1259 4acb54ba Edgar E. Iglesias
#endif
1260 4acb54ba Edgar E. Iglesias
    assert(!dc->abort_at_next_insn);
1261 4acb54ba Edgar E. Iglesias
}
1262 4acb54ba Edgar E. Iglesias
1263 4acb54ba Edgar E. Iglesias
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1264 4acb54ba Edgar E. Iglesias
{
1265 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 0);
1266 4acb54ba Edgar E. Iglesias
}
1267 4acb54ba Edgar E. Iglesias
1268 4acb54ba Edgar E. Iglesias
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1269 4acb54ba Edgar E. Iglesias
{
1270 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 1);
1271 4acb54ba Edgar E. Iglesias
}
1272 4acb54ba Edgar E. Iglesias
1273 4acb54ba Edgar E. Iglesias
void cpu_dump_state (CPUState *env, FILE *f,
1274 4acb54ba Edgar E. Iglesias
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1275 4acb54ba Edgar E. Iglesias
                     int flags)
1276 4acb54ba Edgar E. Iglesias
{
1277 4acb54ba Edgar E. Iglesias
    int i;
1278 4acb54ba Edgar E. Iglesias
1279 4acb54ba Edgar E. Iglesias
    if (!env || !f)
1280 4acb54ba Edgar E. Iglesias
        return;
1281 4acb54ba Edgar E. Iglesias
1282 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "IN: PC=%x %s\n",
1283 4acb54ba Edgar E. Iglesias
                env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1284 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n",
1285 4acb54ba Edgar E. Iglesias
             env->sregs[SR_MSR], env->sregs[SR_ESR],
1286 4acb54ba Edgar E. Iglesias
             env->debug, env->imm, env->iflags);
1287 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s)\n",
1288 4acb54ba Edgar E. Iglesias
             env->btaken, env->btarget,
1289 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1290 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel");
1291 4acb54ba Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
1292 4acb54ba Edgar E. Iglesias
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1293 4acb54ba Edgar E. Iglesias
        if ((i + 1) % 4 == 0)
1294 4acb54ba Edgar E. Iglesias
            cpu_fprintf(f, "\n");
1295 4acb54ba Edgar E. Iglesias
        }
1296 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "\n\n");
1297 4acb54ba Edgar E. Iglesias
}
1298 4acb54ba Edgar E. Iglesias
1299 4acb54ba Edgar E. Iglesias
CPUState *cpu_mb_init (const char *cpu_model)
1300 4acb54ba Edgar E. Iglesias
{
1301 4acb54ba Edgar E. Iglesias
    CPUState *env;
1302 4acb54ba Edgar E. Iglesias
    static int tcg_initialized = 0;
1303 4acb54ba Edgar E. Iglesias
    int i;
1304 4acb54ba Edgar E. Iglesias
1305 4acb54ba Edgar E. Iglesias
    env = qemu_mallocz(sizeof(CPUState));
1306 4acb54ba Edgar E. Iglesias
1307 4acb54ba Edgar E. Iglesias
    cpu_exec_init(env);
1308 4acb54ba Edgar E. Iglesias
    cpu_reset(env);
1309 4acb54ba Edgar E. Iglesias
1310 4acb54ba Edgar E. Iglesias
    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
1311 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_BARREL_MASK \
1312 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DIV_MASK \
1313 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_HW_MUL_MASK \
1314 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_EXC_MASK \
1315 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_ICACHE_MASK \
1316 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DCACHE_MASK \
1317 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_MMU \
1318 4acb54ba Edgar E. Iglesias
                       | (0xb << 8);
1319 4acb54ba Edgar E. Iglesias
     env->pvr.regs[2] = PVR2_D_OPB_MASK \
1320 4acb54ba Edgar E. Iglesias
                        | PVR2_D_LMB_MASK \
1321 4acb54ba Edgar E. Iglesias
                        | PVR2_I_OPB_MASK \
1322 4acb54ba Edgar E. Iglesias
                        | PVR2_I_LMB_MASK \
1323 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MSR_INSTR \
1324 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_PCMP_INSTR \
1325 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_BARREL_MASK \
1326 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_DIV_MASK \
1327 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_HW_MUL_MASK \
1328 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MUL64_MASK \
1329 4acb54ba Edgar E. Iglesias
                        | 0;
1330 4acb54ba Edgar E. Iglesias
     env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
1331 4acb54ba Edgar E. Iglesias
     env->pvr.regs[11] = PVR11_USE_MMU;
1332 4acb54ba Edgar E. Iglesias
1333 4acb54ba Edgar E. Iglesias
    if (tcg_initialized)
1334 4acb54ba Edgar E. Iglesias
        return env;
1335 4acb54ba Edgar E. Iglesias
1336 4acb54ba Edgar E. Iglesias
    tcg_initialized = 1;
1337 4acb54ba Edgar E. Iglesias
1338 4acb54ba Edgar E. Iglesias
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1339 4acb54ba Edgar E. Iglesias
1340 4acb54ba Edgar E. Iglesias
    env_debug = tcg_global_mem_new(TCG_AREG0, 
1341 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, debug),
1342 4acb54ba Edgar E. Iglesias
                    "debug0");
1343 4acb54ba Edgar E. Iglesias
    env_iflags = tcg_global_mem_new(TCG_AREG0, 
1344 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, iflags),
1345 4acb54ba Edgar E. Iglesias
                    "iflags");
1346 4acb54ba Edgar E. Iglesias
    env_imm = tcg_global_mem_new(TCG_AREG0, 
1347 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, imm),
1348 4acb54ba Edgar E. Iglesias
                    "imm");
1349 4acb54ba Edgar E. Iglesias
    env_btarget = tcg_global_mem_new(TCG_AREG0,
1350 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btarget),
1351 4acb54ba Edgar E. Iglesias
                     "btarget");
1352 4acb54ba Edgar E. Iglesias
    env_btaken = tcg_global_mem_new(TCG_AREG0,
1353 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btaken),
1354 4acb54ba Edgar E. Iglesias
                     "btaken");
1355 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1356 4acb54ba Edgar E. Iglesias
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1357 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, regs[i]),
1358 4acb54ba Edgar E. Iglesias
                          regnames[i]);
1359 4acb54ba Edgar E. Iglesias
    }
1360 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1361 4acb54ba Edgar E. Iglesias
        cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
1362 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, sregs[i]),
1363 4acb54ba Edgar E. Iglesias
                          special_regnames[i]);
1364 4acb54ba Edgar E. Iglesias
    }
1365 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 2
1366 4acb54ba Edgar E. Iglesias
#include "helper.h"
1367 4acb54ba Edgar E. Iglesias
1368 4acb54ba Edgar E. Iglesias
    return env;
1369 4acb54ba Edgar E. Iglesias
}
1370 4acb54ba Edgar E. Iglesias
1371 4acb54ba Edgar E. Iglesias
void cpu_reset (CPUState *env)
1372 4acb54ba Edgar E. Iglesias
{
1373 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1374 4acb54ba Edgar E. Iglesias
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1375 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1376 4acb54ba Edgar E. Iglesias
    }
1377 4acb54ba Edgar E. Iglesias
1378 4acb54ba Edgar E. Iglesias
    memset(env, 0, offsetof(CPUMBState, breakpoints));
1379 4acb54ba Edgar E. Iglesias
    tlb_flush(env, 1);
1380 4acb54ba Edgar E. Iglesias
1381 4acb54ba Edgar E. Iglesias
    env->sregs[SR_MSR] = 0;
1382 4acb54ba Edgar E. Iglesias
#if defined(CONFIG_USER_ONLY)
1383 4acb54ba Edgar E. Iglesias
    /* start in user mode with interrupts enabled.  */
1384 4acb54ba Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
1385 4acb54ba Edgar E. Iglesias
#else
1386 4acb54ba Edgar E. Iglesias
    mmu_init(&env->mmu);
1387 4acb54ba Edgar E. Iglesias
#endif
1388 4acb54ba Edgar E. Iglesias
}
1389 4acb54ba Edgar E. Iglesias
1390 4acb54ba Edgar E. Iglesias
void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
1391 4acb54ba Edgar E. Iglesias
                 unsigned long searched_pc, int pc_pos, void *puc)
1392 4acb54ba Edgar E. Iglesias
{
1393 4acb54ba Edgar E. Iglesias
    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
1394 4acb54ba Edgar E. Iglesias
}