Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ a88790a1

History | View | Annotate | Download (44.6 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 38972938 Juan Quintela
static const 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 38972938 Juan Quintela
static const 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 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
235 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
236 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
237 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
238 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
239 1567a005 Edgar E. Iglesias
    }
240 1567a005 Edgar E. Iglesias
241 4acb54ba Edgar E. Iglesias
    mode = dc->opcode & 3;
242 4acb54ba Edgar E. Iglesias
    switch (mode) {
243 4acb54ba Edgar E. Iglesias
        case 0:
244 4acb54ba Edgar E. Iglesias
            /* pcmpbf.  */
245 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpbf r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
246 4acb54ba Edgar E. Iglesias
            if (dc->rd)
247 4acb54ba Edgar E. Iglesias
                gen_helper_pcmpbf(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
248 4acb54ba Edgar E. Iglesias
            break;
249 4acb54ba Edgar E. Iglesias
        case 2:
250 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
251 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
252 4acb54ba Edgar E. Iglesias
                TCGv t0 = tcg_temp_local_new();
253 4acb54ba Edgar E. Iglesias
                l1 = gen_new_label();
254 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 1);
255 4acb54ba Edgar E. Iglesias
                tcg_gen_brcond_tl(TCG_COND_EQ,
256 4acb54ba Edgar E. Iglesias
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
257 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 0);
258 4acb54ba Edgar E. Iglesias
                gen_set_label(l1);
259 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
260 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t0);
261 4acb54ba Edgar E. Iglesias
            }
262 4acb54ba Edgar E. Iglesias
            break;
263 4acb54ba Edgar E. Iglesias
        case 3:
264 4acb54ba Edgar E. Iglesias
            LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
265 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
266 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
267 4acb54ba Edgar E. Iglesias
                TCGv t0 = tcg_temp_local_new();
268 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 1);
269 4acb54ba Edgar E. Iglesias
                tcg_gen_brcond_tl(TCG_COND_NE,
270 4acb54ba Edgar E. Iglesias
                                  cpu_R[dc->ra], cpu_R[dc->rb], l1);
271 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(t0, 0);
272 4acb54ba Edgar E. Iglesias
                gen_set_label(l1);
273 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], t0);
274 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t0);
275 4acb54ba Edgar E. Iglesias
            }
276 4acb54ba Edgar E. Iglesias
            break;
277 4acb54ba Edgar E. Iglesias
        default:
278 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env,
279 4acb54ba Edgar E. Iglesias
                      "unsupported pattern insn opcode=%x\n", dc->opcode);
280 4acb54ba Edgar E. Iglesias
            break;
281 4acb54ba Edgar E. Iglesias
    }
282 4acb54ba Edgar E. Iglesias
}
283 4acb54ba Edgar E. Iglesias
284 4acb54ba Edgar E. Iglesias
static void dec_and(DisasContext *dc)
285 4acb54ba Edgar E. Iglesias
{
286 4acb54ba Edgar E. Iglesias
    unsigned int not;
287 4acb54ba Edgar E. Iglesias
288 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
289 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
290 4acb54ba Edgar E. Iglesias
        return;
291 4acb54ba Edgar E. Iglesias
    }
292 4acb54ba Edgar E. Iglesias
293 4acb54ba Edgar E. Iglesias
    not = dc->opcode & (1 << 1);
294 4acb54ba Edgar E. Iglesias
    LOG_DIS("and%s\n", not ? "n" : "");
295 4acb54ba Edgar E. Iglesias
296 4acb54ba Edgar E. Iglesias
    if (!dc->rd)
297 4acb54ba Edgar E. Iglesias
        return;
298 4acb54ba Edgar E. Iglesias
299 4acb54ba Edgar E. Iglesias
    if (not) {
300 4acb54ba Edgar E. Iglesias
        TCGv t = tcg_temp_new();
301 4acb54ba Edgar E. Iglesias
        tcg_gen_not_tl(t, *(dec_alu_op_b(dc)));
302 4acb54ba Edgar E. Iglesias
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], t);
303 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
304 4acb54ba Edgar E. Iglesias
    } else
305 4acb54ba Edgar E. Iglesias
        tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
306 4acb54ba Edgar E. Iglesias
}
307 4acb54ba Edgar E. Iglesias
308 4acb54ba Edgar E. Iglesias
static void dec_or(DisasContext *dc)
309 4acb54ba Edgar E. Iglesias
{
310 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
311 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
312 4acb54ba Edgar E. Iglesias
        return;
313 4acb54ba Edgar E. Iglesias
    }
314 4acb54ba Edgar E. Iglesias
315 4acb54ba Edgar E. Iglesias
    LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm);
316 4acb54ba Edgar E. Iglesias
    if (dc->rd)
317 4acb54ba Edgar E. Iglesias
        tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
318 4acb54ba Edgar E. Iglesias
}
319 4acb54ba Edgar E. Iglesias
320 4acb54ba Edgar E. Iglesias
static void dec_xor(DisasContext *dc)
321 4acb54ba Edgar E. Iglesias
{
322 4acb54ba Edgar E. Iglesias
    if (!dc->type_b && (dc->imm & (1 << 10))) {
323 4acb54ba Edgar E. Iglesias
        dec_pattern(dc);
324 4acb54ba Edgar E. Iglesias
        return;
325 4acb54ba Edgar E. Iglesias
    }
326 4acb54ba Edgar E. Iglesias
327 4acb54ba Edgar E. Iglesias
    LOG_DIS("xor r%d\n", dc->rd);
328 4acb54ba Edgar E. Iglesias
    if (dc->rd)
329 4acb54ba Edgar E. Iglesias
        tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
330 4acb54ba Edgar E. Iglesias
}
331 4acb54ba Edgar E. Iglesias
332 4acb54ba Edgar E. Iglesias
static void read_carry(DisasContext *dc, TCGv d)
333 4acb54ba Edgar E. Iglesias
{
334 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
335 4acb54ba Edgar E. Iglesias
}
336 4acb54ba Edgar E. Iglesias
337 4acb54ba Edgar E. Iglesias
static void write_carry(DisasContext *dc, TCGv v)
338 4acb54ba Edgar E. Iglesias
{
339 4acb54ba Edgar E. Iglesias
    TCGv t0 = tcg_temp_new();
340 4acb54ba Edgar E. Iglesias
    tcg_gen_shli_tl(t0, v, 31);
341 4acb54ba Edgar E. Iglesias
    tcg_gen_sari_tl(t0, t0, 31);
342 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(env_debug, t0);
343 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
344 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
345 4acb54ba Edgar E. Iglesias
                    ~(MSR_C | MSR_CC));
346 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
347 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
348 4acb54ba Edgar E. Iglesias
}
349 4acb54ba Edgar E. Iglesias
350 4acb54ba Edgar E. Iglesias
351 4acb54ba Edgar E. Iglesias
static inline void msr_read(DisasContext *dc, TCGv d)
352 4acb54ba Edgar E. Iglesias
{
353 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
354 4acb54ba Edgar E. Iglesias
}
355 4acb54ba Edgar E. Iglesias
356 4acb54ba Edgar E. Iglesias
static inline void msr_write(DisasContext *dc, TCGv v)
357 4acb54ba Edgar E. Iglesias
{
358 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 1;
359 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_MSR], v);
360 4acb54ba Edgar E. Iglesias
    /* PVR, we have a processor version register.  */
361 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], (1 << 10));
362 4acb54ba Edgar E. Iglesias
}
363 4acb54ba Edgar E. Iglesias
364 4acb54ba Edgar E. Iglesias
static void dec_msr(DisasContext *dc)
365 4acb54ba Edgar E. Iglesias
{
366 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
367 4acb54ba Edgar E. Iglesias
    unsigned int sr, to, rn;
368 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
369 4acb54ba Edgar E. Iglesias
370 4acb54ba Edgar E. Iglesias
    sr = dc->imm & ((1 << 14) - 1);
371 4acb54ba Edgar E. Iglesias
    to = dc->imm & (1 << 14);
372 4acb54ba Edgar E. Iglesias
    dc->type_b = 1;
373 4acb54ba Edgar E. Iglesias
    if (to)
374 4acb54ba Edgar E. Iglesias
        dc->cpustate_changed = 1;
375 4acb54ba Edgar E. Iglesias
376 4acb54ba Edgar E. Iglesias
    /* msrclr and msrset.  */
377 4acb54ba Edgar E. Iglesias
    if (!(dc->imm & (1 << 15))) {
378 4acb54ba Edgar E. Iglesias
        unsigned int clr = dc->ir & (1 << 16);
379 4acb54ba Edgar E. Iglesias
380 4acb54ba Edgar E. Iglesias
        LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
381 4acb54ba Edgar E. Iglesias
                dc->rd, dc->imm);
382 1567a005 Edgar E. Iglesias
383 1567a005 Edgar E. Iglesias
        if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
384 1567a005 Edgar E. Iglesias
            /* nop??? */
385 1567a005 Edgar E. Iglesias
            return;
386 1567a005 Edgar E. Iglesias
        }
387 1567a005 Edgar E. Iglesias
388 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
389 1567a005 Edgar E. Iglesias
            && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) {
390 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
391 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
392 1567a005 Edgar E. Iglesias
            return;
393 1567a005 Edgar E. Iglesias
        }
394 1567a005 Edgar E. Iglesias
395 4acb54ba Edgar E. Iglesias
        if (dc->rd)
396 4acb54ba Edgar E. Iglesias
            msr_read(dc, cpu_R[dc->rd]);
397 4acb54ba Edgar E. Iglesias
398 4acb54ba Edgar E. Iglesias
        t0 = tcg_temp_new();
399 4acb54ba Edgar E. Iglesias
        t1 = tcg_temp_new();
400 4acb54ba Edgar E. Iglesias
        msr_read(dc, t0);
401 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc)));
402 4acb54ba Edgar E. Iglesias
403 4acb54ba Edgar E. Iglesias
        if (clr) {
404 4acb54ba Edgar E. Iglesias
            tcg_gen_not_tl(t1, t1);
405 4acb54ba Edgar E. Iglesias
            tcg_gen_and_tl(t0, t0, t1);
406 4acb54ba Edgar E. Iglesias
        } else
407 4acb54ba Edgar E. Iglesias
            tcg_gen_or_tl(t0, t0, t1);
408 4acb54ba Edgar E. Iglesias
        msr_write(dc, t0);
409 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t0);
410 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t1);
411 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
412 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
413 4acb54ba Edgar E. Iglesias
        return;
414 4acb54ba Edgar E. Iglesias
    }
415 4acb54ba Edgar E. Iglesias
416 1567a005 Edgar E. Iglesias
    if (to) {
417 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
418 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
419 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
420 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
421 1567a005 Edgar E. Iglesias
            return;
422 1567a005 Edgar E. Iglesias
        }
423 1567a005 Edgar E. Iglesias
    }
424 1567a005 Edgar E. Iglesias
425 4acb54ba Edgar E. Iglesias
#if !defined(CONFIG_USER_ONLY)
426 4acb54ba Edgar E. Iglesias
    /* Catch read/writes to the mmu block.  */
427 4acb54ba Edgar E. Iglesias
    if ((sr & ~0xff) == 0x1000) {
428 4acb54ba Edgar E. Iglesias
        sr &= 7;
429 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
430 4acb54ba Edgar E. Iglesias
        if (to)
431 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
432 4acb54ba Edgar E. Iglesias
        else
433 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
434 4acb54ba Edgar E. Iglesias
        return;
435 4acb54ba Edgar E. Iglesias
    }
436 4acb54ba Edgar E. Iglesias
#endif
437 4acb54ba Edgar E. Iglesias
438 4acb54ba Edgar E. Iglesias
    if (to) {
439 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss sr%x r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
440 4acb54ba Edgar E. Iglesias
        switch (sr) {
441 4acb54ba Edgar E. Iglesias
            case 0:
442 4acb54ba Edgar E. Iglesias
                break;
443 4acb54ba Edgar E. Iglesias
            case 1:
444 4acb54ba Edgar E. Iglesias
                msr_write(dc, cpu_R[dc->ra]);
445 4acb54ba Edgar E. Iglesias
                break;
446 4acb54ba Edgar E. Iglesias
            case 0x3:
447 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]);
448 4acb54ba Edgar E. Iglesias
                break;
449 4acb54ba Edgar E. Iglesias
            case 0x5:
450 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]);
451 4acb54ba Edgar E. Iglesias
                break;
452 4acb54ba Edgar E. Iglesias
            case 0x7:
453 4acb54ba Edgar E. Iglesias
                /* Ignored at the moment.  */
454 4acb54ba Edgar E. Iglesias
                break;
455 4acb54ba Edgar E. Iglesias
            default:
456 4acb54ba Edgar E. Iglesias
                cpu_abort(dc->env, "unknown mts reg %x\n", sr);
457 4acb54ba Edgar E. Iglesias
                break;
458 4acb54ba Edgar E. Iglesias
        }
459 4acb54ba Edgar E. Iglesias
    } else {
460 4acb54ba Edgar E. Iglesias
        LOG_DIS("m%ss r%d sr%x imm=%x\n", to ? "t" : "f", dc->rd, sr, dc->imm);
461 4acb54ba Edgar E. Iglesias
462 4acb54ba Edgar E. Iglesias
        switch (sr) {
463 4acb54ba Edgar E. Iglesias
            case 0:
464 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
465 4acb54ba Edgar E. Iglesias
                break;
466 4acb54ba Edgar E. Iglesias
            case 1:
467 4acb54ba Edgar E. Iglesias
                msr_read(dc, cpu_R[dc->rd]);
468 4acb54ba Edgar E. Iglesias
                break;
469 4acb54ba Edgar E. Iglesias
            case 0x3:
470 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]);
471 4acb54ba Edgar E. Iglesias
                break;
472 4acb54ba Edgar E. Iglesias
            case 0x5:
473 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]);
474 4acb54ba Edgar E. Iglesias
                break;
475 4acb54ba Edgar E. Iglesias
             case 0x7:
476 4acb54ba Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_R[dc->rd], 0);
477 4acb54ba Edgar E. Iglesias
                break;
478 4acb54ba Edgar E. Iglesias
            case 0xb:
479 4acb54ba Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
480 4acb54ba Edgar E. Iglesias
                break;
481 4acb54ba Edgar E. Iglesias
            case 0x2000:
482 4acb54ba Edgar E. Iglesias
            case 0x2001:
483 4acb54ba Edgar E. Iglesias
            case 0x2002:
484 4acb54ba Edgar E. Iglesias
            case 0x2003:
485 4acb54ba Edgar E. Iglesias
            case 0x2004:
486 4acb54ba Edgar E. Iglesias
            case 0x2005:
487 4acb54ba Edgar E. Iglesias
            case 0x2006:
488 4acb54ba Edgar E. Iglesias
            case 0x2007:
489 4acb54ba Edgar E. Iglesias
            case 0x2008:
490 4acb54ba Edgar E. Iglesias
            case 0x2009:
491 4acb54ba Edgar E. Iglesias
            case 0x200a:
492 4acb54ba Edgar E. Iglesias
            case 0x200b:
493 4acb54ba Edgar E. Iglesias
            case 0x200c:
494 4acb54ba Edgar E. Iglesias
                rn = sr & 0xf;
495 4acb54ba Edgar E. Iglesias
                tcg_gen_ld_tl(cpu_R[dc->rd],
496 4acb54ba Edgar E. Iglesias
                              cpu_env, offsetof(CPUState, pvr.regs[rn]));
497 4acb54ba Edgar E. Iglesias
                break;
498 4acb54ba Edgar E. Iglesias
            default:
499 4acb54ba Edgar E. Iglesias
                cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
500 4acb54ba Edgar E. Iglesias
                break;
501 4acb54ba Edgar E. Iglesias
        }
502 4acb54ba Edgar E. Iglesias
    }
503 ee7dbcf8 Edgar E. Iglesias
504 ee7dbcf8 Edgar E. Iglesias
    if (dc->rd == 0) {
505 ee7dbcf8 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[0], 0);
506 ee7dbcf8 Edgar E. Iglesias
    }
507 4acb54ba Edgar E. Iglesias
}
508 4acb54ba Edgar E. Iglesias
509 4acb54ba Edgar E. Iglesias
/* 64-bit signed mul, lower result in d and upper in d2.  */
510 4acb54ba Edgar E. Iglesias
static void t_gen_muls(TCGv d, TCGv d2, TCGv a, TCGv b)
511 4acb54ba Edgar E. Iglesias
{
512 4acb54ba Edgar E. Iglesias
    TCGv_i64 t0, t1;
513 4acb54ba Edgar E. Iglesias
514 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new_i64();
515 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new_i64();
516 4acb54ba Edgar E. Iglesias
517 4acb54ba Edgar E. Iglesias
    tcg_gen_ext_i32_i64(t0, a);
518 4acb54ba Edgar E. Iglesias
    tcg_gen_ext_i32_i64(t1, b);
519 4acb54ba Edgar E. Iglesias
    tcg_gen_mul_i64(t0, t0, t1);
520 4acb54ba Edgar E. Iglesias
521 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d, t0);
522 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_i64(t0, t0, 32);
523 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d2, t0);
524 4acb54ba Edgar E. Iglesias
525 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t0);
526 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t1);
527 4acb54ba Edgar E. Iglesias
}
528 4acb54ba Edgar E. Iglesias
529 4acb54ba Edgar E. Iglesias
/* 64-bit unsigned muls, lower result in d and upper in d2.  */
530 4acb54ba Edgar E. Iglesias
static void t_gen_mulu(TCGv d, TCGv d2, TCGv a, TCGv b)
531 4acb54ba Edgar E. Iglesias
{
532 4acb54ba Edgar E. Iglesias
    TCGv_i64 t0, t1;
533 4acb54ba Edgar E. Iglesias
534 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new_i64();
535 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new_i64();
536 4acb54ba Edgar E. Iglesias
537 4acb54ba Edgar E. Iglesias
    tcg_gen_extu_i32_i64(t0, a);
538 4acb54ba Edgar E. Iglesias
    tcg_gen_extu_i32_i64(t1, b);
539 4acb54ba Edgar E. Iglesias
    tcg_gen_mul_i64(t0, t0, t1);
540 4acb54ba Edgar E. Iglesias
541 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d, t0);
542 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_i64(t0, t0, 32);
543 4acb54ba Edgar E. Iglesias
    tcg_gen_trunc_i64_i32(d2, t0);
544 4acb54ba Edgar E. Iglesias
545 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t0);
546 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i64(t1);
547 4acb54ba Edgar E. Iglesias
}
548 4acb54ba Edgar E. Iglesias
549 4acb54ba Edgar E. Iglesias
/* Multiplier unit.  */
550 4acb54ba Edgar E. Iglesias
static void dec_mul(DisasContext *dc)
551 4acb54ba Edgar E. Iglesias
{
552 4acb54ba Edgar E. Iglesias
    TCGv d[2];
553 4acb54ba Edgar E. Iglesias
    unsigned int subcode;
554 4acb54ba Edgar E. Iglesias
555 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
556 97f90cbf Edgar E. Iglesias
         && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
557 1567a005 Edgar E. Iglesias
         && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
558 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
559 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
560 1567a005 Edgar E. Iglesias
        return;
561 1567a005 Edgar E. Iglesias
    }
562 1567a005 Edgar E. Iglesias
563 4acb54ba Edgar E. Iglesias
    subcode = dc->imm & 3;
564 4acb54ba Edgar E. Iglesias
    d[0] = tcg_temp_new();
565 4acb54ba Edgar E. Iglesias
    d[1] = tcg_temp_new();
566 4acb54ba Edgar E. Iglesias
567 4acb54ba Edgar E. Iglesias
    if (dc->type_b) {
568 4acb54ba Edgar E. Iglesias
        LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm);
569 4acb54ba Edgar E. Iglesias
        t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
570 4acb54ba Edgar E. Iglesias
        goto done;
571 4acb54ba Edgar E. Iglesias
    }
572 4acb54ba Edgar E. Iglesias
573 1567a005 Edgar E. Iglesias
    /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2.  */
574 1567a005 Edgar E. Iglesias
    if (subcode >= 1 && subcode <= 3
575 1567a005 Edgar E. Iglesias
        && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
576 1567a005 Edgar E. Iglesias
        /* nop??? */
577 1567a005 Edgar E. Iglesias
    }
578 1567a005 Edgar E. Iglesias
579 4acb54ba Edgar E. Iglesias
    switch (subcode) {
580 4acb54ba Edgar E. Iglesias
        case 0:
581 4acb54ba Edgar E. Iglesias
            LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
582 4acb54ba Edgar E. Iglesias
            t_gen_mulu(cpu_R[dc->rd], d[1], cpu_R[dc->ra], cpu_R[dc->rb]);
583 4acb54ba Edgar E. Iglesias
            break;
584 4acb54ba Edgar E. Iglesias
        case 1:
585 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
586 4acb54ba Edgar E. Iglesias
            t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
587 4acb54ba Edgar E. Iglesias
            break;
588 4acb54ba Edgar E. Iglesias
        case 2:
589 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
590 4acb54ba Edgar E. Iglesias
            t_gen_muls(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
591 4acb54ba Edgar E. Iglesias
            break;
592 4acb54ba Edgar E. Iglesias
        case 3:
593 4acb54ba Edgar E. Iglesias
            LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
594 4acb54ba Edgar E. Iglesias
            t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
595 4acb54ba Edgar E. Iglesias
            break;
596 4acb54ba Edgar E. Iglesias
        default:
597 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
598 4acb54ba Edgar E. Iglesias
            break;
599 4acb54ba Edgar E. Iglesias
    }
600 4acb54ba Edgar E. Iglesias
done:
601 4acb54ba Edgar E. Iglesias
    tcg_temp_free(d[0]);
602 4acb54ba Edgar E. Iglesias
    tcg_temp_free(d[1]);
603 4acb54ba Edgar E. Iglesias
}
604 4acb54ba Edgar E. Iglesias
605 4acb54ba Edgar E. Iglesias
/* Div unit.  */
606 4acb54ba Edgar E. Iglesias
static void dec_div(DisasContext *dc)
607 4acb54ba Edgar E. Iglesias
{
608 4acb54ba Edgar E. Iglesias
    unsigned int u;
609 4acb54ba Edgar E. Iglesias
610 4acb54ba Edgar E. Iglesias
    u = dc->imm & 2; 
611 4acb54ba Edgar E. Iglesias
    LOG_DIS("div\n");
612 4acb54ba Edgar E. Iglesias
613 97f90cbf Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
614 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
615 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
616 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
617 1567a005 Edgar E. Iglesias
    }
618 1567a005 Edgar E. Iglesias
619 4acb54ba Edgar E. Iglesias
    if (u)
620 4acb54ba Edgar E. Iglesias
        gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
621 4acb54ba Edgar E. Iglesias
    else
622 4acb54ba Edgar E. Iglesias
        gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
623 4acb54ba Edgar E. Iglesias
    if (!dc->rd)
624 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], 0);
625 4acb54ba Edgar E. Iglesias
}
626 4acb54ba Edgar E. Iglesias
627 4acb54ba Edgar E. Iglesias
static void dec_barrel(DisasContext *dc)
628 4acb54ba Edgar E. Iglesias
{
629 4acb54ba Edgar E. Iglesias
    TCGv t0;
630 4acb54ba Edgar E. Iglesias
    unsigned int s, t;
631 4acb54ba Edgar E. Iglesias
632 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
633 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
634 1567a005 Edgar E. Iglesias
          && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
635 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
636 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
637 1567a005 Edgar E. Iglesias
        return;
638 1567a005 Edgar E. Iglesias
    }
639 1567a005 Edgar E. Iglesias
640 4acb54ba Edgar E. Iglesias
    s = dc->imm & (1 << 10);
641 4acb54ba Edgar E. Iglesias
    t = dc->imm & (1 << 9);
642 4acb54ba Edgar E. Iglesias
643 4acb54ba Edgar E. Iglesias
    LOG_DIS("bs%s%s r%d r%d r%d\n",
644 4acb54ba Edgar E. Iglesias
            s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
645 4acb54ba Edgar E. Iglesias
646 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
647 4acb54ba Edgar E. Iglesias
648 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
649 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, 31);
650 4acb54ba Edgar E. Iglesias
651 4acb54ba Edgar E. Iglesias
    if (s)
652 4acb54ba Edgar E. Iglesias
        tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
653 4acb54ba Edgar E. Iglesias
    else {
654 4acb54ba Edgar E. Iglesias
        if (t)
655 4acb54ba Edgar E. Iglesias
            tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
656 4acb54ba Edgar E. Iglesias
        else
657 4acb54ba Edgar E. Iglesias
            tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
658 4acb54ba Edgar E. Iglesias
    }
659 4acb54ba Edgar E. Iglesias
}
660 4acb54ba Edgar E. Iglesias
661 4acb54ba Edgar E. Iglesias
static void dec_bit(DisasContext *dc)
662 4acb54ba Edgar E. Iglesias
{
663 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
664 4acb54ba Edgar E. Iglesias
    unsigned int op;
665 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
666 4acb54ba Edgar E. Iglesias
667 4acb54ba Edgar E. Iglesias
    op = dc->ir & ((1 << 8) - 1);
668 4acb54ba Edgar E. Iglesias
    switch (op) {
669 4acb54ba Edgar E. Iglesias
        case 0x21:
670 4acb54ba Edgar E. Iglesias
            /* src.  */
671 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
672 4acb54ba Edgar E. Iglesias
673 4acb54ba Edgar E. Iglesias
            LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
674 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
675 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
676 4acb54ba Edgar E. Iglesias
                t1 = tcg_temp_new();
677 4acb54ba Edgar E. Iglesias
                read_carry(dc, t1);
678 4acb54ba Edgar E. Iglesias
                tcg_gen_shli_tl(t1, t1, 31);
679 4acb54ba Edgar E. Iglesias
680 4acb54ba Edgar E. Iglesias
                tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
681 4acb54ba Edgar E. Iglesias
                tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
682 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t1);
683 4acb54ba Edgar E. Iglesias
            }
684 4acb54ba Edgar E. Iglesias
685 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
686 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
687 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
688 4acb54ba Edgar E. Iglesias
            break;
689 4acb54ba Edgar E. Iglesias
690 4acb54ba Edgar E. Iglesias
        case 0x1:
691 4acb54ba Edgar E. Iglesias
        case 0x41:
692 4acb54ba Edgar E. Iglesias
            /* srl.  */
693 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
694 4acb54ba Edgar E. Iglesias
            LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
695 4acb54ba Edgar E. Iglesias
696 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
697 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
698 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
699 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
700 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
701 4acb54ba Edgar E. Iglesias
                if (op == 0x41)
702 4acb54ba Edgar E. Iglesias
                    tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
703 4acb54ba Edgar E. Iglesias
                else
704 4acb54ba Edgar E. Iglesias
                    tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
705 4acb54ba Edgar E. Iglesias
            }
706 4acb54ba Edgar E. Iglesias
            break;
707 4acb54ba Edgar E. Iglesias
        case 0x60:
708 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
709 4acb54ba Edgar E. Iglesias
            tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
710 4acb54ba Edgar E. Iglesias
            break;
711 4acb54ba Edgar E. Iglesias
        case 0x61:
712 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
713 4acb54ba Edgar E. Iglesias
            tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
714 4acb54ba Edgar E. Iglesias
            break;
715 4acb54ba Edgar E. Iglesias
        case 0x64:
716 f062a3c7 Edgar E. Iglesias
        case 0x66:
717 f062a3c7 Edgar E. Iglesias
        case 0x74:
718 f062a3c7 Edgar E. Iglesias
        case 0x76:
719 4acb54ba Edgar E. Iglesias
            /* wdc.  */
720 4acb54ba Edgar E. Iglesias
            LOG_DIS("wdc r%d\n", dc->ra);
721 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
722 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
723 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
724 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
725 1567a005 Edgar E. Iglesias
                return;
726 1567a005 Edgar E. Iglesias
            }
727 4acb54ba Edgar E. Iglesias
            break;
728 4acb54ba Edgar E. Iglesias
        case 0x68:
729 4acb54ba Edgar E. Iglesias
            /* wic.  */
730 4acb54ba Edgar E. Iglesias
            LOG_DIS("wic r%d\n", dc->ra);
731 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
732 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
733 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
734 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
735 1567a005 Edgar E. Iglesias
                return;
736 1567a005 Edgar E. Iglesias
            }
737 4acb54ba Edgar E. Iglesias
            break;
738 4acb54ba Edgar E. Iglesias
        default:
739 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
740 4acb54ba Edgar E. Iglesias
                     dc->pc, op, dc->rd, dc->ra, dc->rb);
741 4acb54ba Edgar E. Iglesias
            break;
742 4acb54ba Edgar E. Iglesias
    }
743 4acb54ba Edgar E. Iglesias
}
744 4acb54ba Edgar E. Iglesias
745 4acb54ba Edgar E. Iglesias
static inline void sync_jmpstate(DisasContext *dc)
746 4acb54ba Edgar E. Iglesias
{
747 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
748 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_INDIRECT;
749 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
750 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
751 4acb54ba Edgar E. Iglesias
    }
752 4acb54ba Edgar E. Iglesias
}
753 4acb54ba Edgar E. Iglesias
754 4acb54ba Edgar E. Iglesias
static void dec_imm(DisasContext *dc)
755 4acb54ba Edgar E. Iglesias
{
756 4acb54ba Edgar E. Iglesias
    LOG_DIS("imm %x\n", dc->imm << 16);
757 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_imm, (dc->imm << 16));
758 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= IMM_FLAG;
759 4acb54ba Edgar E. Iglesias
    dc->clear_imm = 0;
760 4acb54ba Edgar E. Iglesias
}
761 4acb54ba Edgar E. Iglesias
762 4acb54ba Edgar E. Iglesias
static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
763 4acb54ba Edgar E. Iglesias
                            unsigned int size)
764 4acb54ba Edgar E. Iglesias
{
765 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
766 4acb54ba Edgar E. Iglesias
767 4acb54ba Edgar E. Iglesias
    if (size == 1) {
768 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld8u(dst, addr, mem_index);
769 4acb54ba Edgar E. Iglesias
    } else if (size == 2) {
770 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld16u(dst, addr, mem_index);
771 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
772 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld32u(dst, addr, mem_index);
773 4acb54ba Edgar E. Iglesias
    } else
774 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect load size %d\n", size);
775 4acb54ba Edgar E. Iglesias
}
776 4acb54ba Edgar E. Iglesias
777 4acb54ba Edgar E. Iglesias
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
778 4acb54ba Edgar E. Iglesias
{
779 4acb54ba Edgar E. Iglesias
    unsigned int extimm = dc->tb_flags & IMM_FLAG;
780 4acb54ba Edgar E. Iglesias
781 4acb54ba Edgar E. Iglesias
    /* Treat the fast cases first.  */
782 4acb54ba Edgar E. Iglesias
    if (!dc->type_b) {
783 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
784 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
785 4acb54ba Edgar E. Iglesias
        return t;
786 4acb54ba Edgar E. Iglesias
    }
787 4acb54ba Edgar E. Iglesias
    /* Immediate.  */
788 4acb54ba Edgar E. Iglesias
    if (!extimm) {
789 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0) {
790 4acb54ba Edgar E. Iglesias
            return &cpu_R[dc->ra];
791 4acb54ba Edgar E. Iglesias
        }
792 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
793 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
794 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
795 4acb54ba Edgar E. Iglesias
    } else {
796 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
797 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
798 4acb54ba Edgar E. Iglesias
    }
799 4acb54ba Edgar E. Iglesias
800 4acb54ba Edgar E. Iglesias
    return t;
801 4acb54ba Edgar E. Iglesias
}
802 4acb54ba Edgar E. Iglesias
803 4acb54ba Edgar E. Iglesias
static void dec_load(DisasContext *dc)
804 4acb54ba Edgar E. Iglesias
{
805 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
806 4acb54ba Edgar E. Iglesias
    unsigned int size;
807 4acb54ba Edgar E. Iglesias
808 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
809 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
810 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
811 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
812 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
813 0187688f Edgar E. Iglesias
        return;
814 0187688f Edgar E. Iglesias
    }
815 4acb54ba Edgar E. Iglesias
816 4acb54ba Edgar E. Iglesias
    LOG_DIS("l %x %d\n", dc->opcode, size);
817 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
818 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
819 4acb54ba Edgar E. Iglesias
820 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
821 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
822 968a40f6 Edgar E. Iglesias
823 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
824 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
825 a12f6507 Edgar E. Iglesias
        TCGv v = tcg_temp_new();
826 a12f6507 Edgar E. Iglesias
827 a12f6507 Edgar E. Iglesias
        /*
828 a12f6507 Edgar E. Iglesias
         * Microblaze gives MMU faults priority over faults due to
829 a12f6507 Edgar E. Iglesias
         * unaligned addresses. That's why we speculatively do the load
830 a12f6507 Edgar E. Iglesias
         * into v. If the load succeeds, we verify alignment of the
831 a12f6507 Edgar E. Iglesias
         * address and if that succeeds we write into the destination reg.
832 a12f6507 Edgar E. Iglesias
         */
833 a12f6507 Edgar E. Iglesias
        gen_load(dc, v, *addr, size);
834 a12f6507 Edgar E. Iglesias
835 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
836 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
837 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(0), tcg_const_tl(size - 1));
838 a12f6507 Edgar E. Iglesias
        if (dc->rd)
839 a12f6507 Edgar E. Iglesias
            tcg_gen_mov_tl(cpu_R[dc->rd], v);
840 a12f6507 Edgar E. Iglesias
        tcg_temp_free(v);
841 968a40f6 Edgar E. Iglesias
    } else {
842 a12f6507 Edgar E. Iglesias
        if (dc->rd) {
843 a12f6507 Edgar E. Iglesias
            gen_load(dc, cpu_R[dc->rd], *addr, size);
844 a12f6507 Edgar E. Iglesias
        } else {
845 a12f6507 Edgar E. Iglesias
            gen_load(dc, env_imm, *addr, size);
846 a12f6507 Edgar E. Iglesias
        }
847 4acb54ba Edgar E. Iglesias
    }
848 4acb54ba Edgar E. Iglesias
849 4acb54ba Edgar E. Iglesias
    if (addr == &t)
850 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
851 4acb54ba Edgar E. Iglesias
}
852 4acb54ba Edgar E. Iglesias
853 4acb54ba Edgar E. Iglesias
static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
854 4acb54ba Edgar E. Iglesias
                      unsigned int size)
855 4acb54ba Edgar E. Iglesias
{
856 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
857 4acb54ba Edgar E. Iglesias
858 4acb54ba Edgar E. Iglesias
    if (size == 1)
859 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st8(val, addr, mem_index);
860 4acb54ba Edgar E. Iglesias
    else if (size == 2) {
861 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st16(val, addr, mem_index);
862 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
863 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st32(val, addr, mem_index);
864 4acb54ba Edgar E. Iglesias
    } else
865 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect store size %d\n", size);
866 4acb54ba Edgar E. Iglesias
}
867 4acb54ba Edgar E. Iglesias
868 4acb54ba Edgar E. Iglesias
static void dec_store(DisasContext *dc)
869 4acb54ba Edgar E. Iglesias
{
870 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
871 4acb54ba Edgar E. Iglesias
    unsigned int size;
872 4acb54ba Edgar E. Iglesias
873 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
874 4acb54ba Edgar E. Iglesias
875 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
876 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
877 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
878 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
879 0187688f Edgar E. Iglesias
        return;
880 0187688f Edgar E. Iglesias
    }
881 0187688f Edgar E. Iglesias
882 4acb54ba Edgar E. Iglesias
    LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
883 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
884 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
885 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
886 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
887 968a40f6 Edgar E. Iglesias
888 a12f6507 Edgar E. Iglesias
    gen_store(dc, *addr, cpu_R[dc->rd], size);
889 a12f6507 Edgar E. Iglesias
890 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
891 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
892 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
893 a12f6507 Edgar E. Iglesias
        /* FIXME: if the alignment is wrong, we should restore the value
894 a12f6507 Edgar E. Iglesias
         *        in memory.
895 a12f6507 Edgar E. Iglesias
         */
896 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
897 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(1), tcg_const_tl(size - 1));
898 968a40f6 Edgar E. Iglesias
    }
899 968a40f6 Edgar E. Iglesias
900 4acb54ba Edgar E. Iglesias
    if (addr == &t)
901 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
902 4acb54ba Edgar E. Iglesias
}
903 4acb54ba Edgar E. Iglesias
904 4acb54ba Edgar E. Iglesias
static inline void eval_cc(DisasContext *dc, unsigned int cc,
905 4acb54ba Edgar E. Iglesias
                           TCGv d, TCGv a, TCGv b)
906 4acb54ba Edgar E. Iglesias
{
907 4acb54ba Edgar E. Iglesias
    int l1;
908 4acb54ba Edgar E. Iglesias
909 4acb54ba Edgar E. Iglesias
    switch (cc) {
910 4acb54ba Edgar E. Iglesias
        case CC_EQ:
911 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
912 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
913 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1);
914 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
915 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
916 4acb54ba Edgar E. Iglesias
            break;
917 4acb54ba Edgar E. Iglesias
        case CC_NE:
918 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
919 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
920 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1);
921 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
922 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
923 4acb54ba Edgar E. Iglesias
            break;
924 4acb54ba Edgar E. Iglesias
        case CC_LT:
925 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
926 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
927 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1);
928 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
929 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
930 4acb54ba Edgar E. Iglesias
            break;
931 4acb54ba Edgar E. Iglesias
        case CC_LE:
932 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
933 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
934 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1);
935 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
936 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
937 4acb54ba Edgar E. Iglesias
            break;
938 4acb54ba Edgar E. Iglesias
        case CC_GE:
939 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
940 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
941 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1);
942 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
943 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
944 4acb54ba Edgar E. Iglesias
            break;
945 4acb54ba Edgar E. Iglesias
        case CC_GT:
946 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
947 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
948 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1);
949 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
950 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
951 4acb54ba Edgar E. Iglesias
            break;
952 4acb54ba Edgar E. Iglesias
        default:
953 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
954 4acb54ba Edgar E. Iglesias
            break;
955 4acb54ba Edgar E. Iglesias
    }
956 4acb54ba Edgar E. Iglesias
}
957 4acb54ba Edgar E. Iglesias
958 4acb54ba Edgar E. Iglesias
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
959 4acb54ba Edgar E. Iglesias
{
960 4acb54ba Edgar E. Iglesias
    int l1;
961 4acb54ba Edgar E. Iglesias
962 4acb54ba Edgar E. Iglesias
    l1 = gen_new_label();
963 4acb54ba Edgar E. Iglesias
    /* Conditional jmp.  */
964 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
965 4acb54ba Edgar E. Iglesias
    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
966 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
967 4acb54ba Edgar E. Iglesias
    gen_set_label(l1);
968 4acb54ba Edgar E. Iglesias
}
969 4acb54ba Edgar E. Iglesias
970 4acb54ba Edgar E. Iglesias
static void dec_bcc(DisasContext *dc)
971 4acb54ba Edgar E. Iglesias
{
972 4acb54ba Edgar E. Iglesias
    unsigned int cc;
973 4acb54ba Edgar E. Iglesias
    unsigned int dslot;
974 4acb54ba Edgar E. Iglesias
975 4acb54ba Edgar E. Iglesias
    cc = EXTRACT_FIELD(dc->ir, 21, 23);
976 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 25);
977 4acb54ba Edgar E. Iglesias
    LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
978 4acb54ba Edgar E. Iglesias
979 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
980 4acb54ba Edgar E. Iglesias
    if (dslot) {
981 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
982 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
983 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
984 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
985 4acb54ba Edgar E. Iglesias
    }
986 4acb54ba Edgar E. Iglesias
987 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btarget, dc->pc);
988 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
989 4acb54ba Edgar E. Iglesias
    eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
990 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
991 4acb54ba Edgar E. Iglesias
}
992 4acb54ba Edgar E. Iglesias
993 4acb54ba Edgar E. Iglesias
static void dec_br(DisasContext *dc)
994 4acb54ba Edgar E. Iglesias
{
995 4acb54ba Edgar E. Iglesias
    unsigned int dslot, link, abs;
996 ff21f70a Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
997 4acb54ba Edgar E. Iglesias
998 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 20);
999 4acb54ba Edgar E. Iglesias
    abs = dc->ir & (1 << 19);
1000 4acb54ba Edgar E. Iglesias
    link = dc->ir & (1 << 18);
1001 4acb54ba Edgar E. Iglesias
    LOG_DIS("br%s%s%s%s imm=%x\n",
1002 4acb54ba Edgar E. Iglesias
             abs ? "a" : "", link ? "l" : "",
1003 4acb54ba Edgar E. Iglesias
             dc->type_b ? "i" : "", dslot ? "d" : "",
1004 4acb54ba Edgar E. Iglesias
             dc->imm);
1005 4acb54ba Edgar E. Iglesias
1006 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
1007 4acb54ba Edgar E. Iglesias
    if (dslot) {
1008 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
1009 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
1010 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1011 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
1012 4acb54ba Edgar E. Iglesias
    }
1013 4acb54ba Edgar E. Iglesias
    if (link && dc->rd)
1014 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
1015 4acb54ba Edgar E. Iglesias
1016 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
1017 4acb54ba Edgar E. Iglesias
    if (abs) {
1018 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_btaken, 1);
1019 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
1020 ff21f70a Edgar E. Iglesias
        if (link && !dslot) {
1021 ff21f70a Edgar E. Iglesias
            if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18))
1022 ff21f70a Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_BREAK);
1023 ff21f70a Edgar E. Iglesias
            if (dc->imm == 0) {
1024 ff21f70a Edgar E. Iglesias
                if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
1025 ff21f70a Edgar E. Iglesias
                    tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1026 ff21f70a Edgar E. Iglesias
                    t_gen_raise_exception(dc, EXCP_HW_EXCP);
1027 ff21f70a Edgar E. Iglesias
                    return;
1028 ff21f70a Edgar E. Iglesias
                }
1029 ff21f70a Edgar E. Iglesias
1030 ff21f70a Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1031 ff21f70a Edgar E. Iglesias
            }
1032 ff21f70a Edgar E. Iglesias
        }
1033 4acb54ba Edgar E. Iglesias
    } else {
1034 9d2dcce9 Paul Hartke
        if (!dc->type_b || (dc->tb_flags & IMM_FLAG)) {
1035 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
1036 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->pc);
1037 4acb54ba Edgar E. Iglesias
            tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1038 4acb54ba Edgar E. Iglesias
        } else {
1039 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_DIRECT;
1040 4acb54ba Edgar E. Iglesias
            dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
1041 4acb54ba Edgar E. Iglesias
        }
1042 4acb54ba Edgar E. Iglesias
    }
1043 4acb54ba Edgar E. Iglesias
}
1044 4acb54ba Edgar E. Iglesias
1045 4acb54ba Edgar E. Iglesias
static inline void do_rti(DisasContext *dc)
1046 4acb54ba Edgar E. Iglesias
{
1047 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1048 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1049 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1050 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
1051 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
1052 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1053 4acb54ba Edgar E. Iglesias
1054 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1055 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1056 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1057 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1058 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1059 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTI_FLAG;
1060 4acb54ba Edgar E. Iglesias
}
1061 4acb54ba Edgar E. Iglesias
1062 4acb54ba Edgar E. Iglesias
static inline void do_rtb(DisasContext *dc)
1063 4acb54ba Edgar E. Iglesias
{
1064 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1065 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1066 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1067 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
1068 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1069 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1070 4acb54ba Edgar E. Iglesias
1071 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1072 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1073 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1074 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1075 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1076 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTB_FLAG;
1077 4acb54ba Edgar E. Iglesias
}
1078 4acb54ba Edgar E. Iglesias
1079 4acb54ba Edgar E. Iglesias
static inline void do_rte(DisasContext *dc)
1080 4acb54ba Edgar E. Iglesias
{
1081 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1082 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1083 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1084 4acb54ba Edgar E. Iglesias
1085 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
1086 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
1087 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1088 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1089 4acb54ba Edgar E. Iglesias
1090 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1091 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1092 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1093 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1094 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1095 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTE_FLAG;
1096 4acb54ba Edgar E. Iglesias
}
1097 4acb54ba Edgar E. Iglesias
1098 4acb54ba Edgar E. Iglesias
static void dec_rts(DisasContext *dc)
1099 4acb54ba Edgar E. Iglesias
{
1100 4acb54ba Edgar E. Iglesias
    unsigned int b_bit, i_bit, e_bit;
1101 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1102 4acb54ba Edgar E. Iglesias
1103 4acb54ba Edgar E. Iglesias
    i_bit = dc->ir & (1 << 21);
1104 4acb54ba Edgar E. Iglesias
    b_bit = dc->ir & (1 << 22);
1105 4acb54ba Edgar E. Iglesias
    e_bit = dc->ir & (1 << 23);
1106 4acb54ba Edgar E. Iglesias
1107 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 2;
1108 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= D_FLAG;
1109 4acb54ba Edgar E. Iglesias
    tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1110 4acb54ba Edgar E. Iglesias
                  cpu_env, offsetof(CPUState, bimm));
1111 4acb54ba Edgar E. Iglesias
1112 4acb54ba Edgar E. Iglesias
    if (i_bit) {
1113 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtid ir=%x\n", dc->ir);
1114 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1115 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1116 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1117 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1118 1567a005 Edgar E. Iglesias
        }
1119 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTI_FLAG;
1120 4acb54ba Edgar E. Iglesias
    } else if (b_bit) {
1121 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtbd ir=%x\n", dc->ir);
1122 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1123 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1124 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1125 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1126 1567a005 Edgar E. Iglesias
        }
1127 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTB_FLAG;
1128 4acb54ba Edgar E. Iglesias
    } else if (e_bit) {
1129 4acb54ba Edgar E. Iglesias
        LOG_DIS("rted ir=%x\n", dc->ir);
1130 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1131 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1132 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1133 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1134 1567a005 Edgar E. Iglesias
        }
1135 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTE_FLAG;
1136 4acb54ba Edgar E. Iglesias
    } else
1137 4acb54ba Edgar E. Iglesias
        LOG_DIS("rts ir=%x\n", dc->ir);
1138 4acb54ba Edgar E. Iglesias
1139 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btaken, 1);
1140 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1141 4acb54ba Edgar E. Iglesias
}
1142 4acb54ba Edgar E. Iglesias
1143 1567a005 Edgar E. Iglesias
static void dec_fpu(DisasContext *dc)
1144 1567a005 Edgar E. Iglesias
{
1145 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1146 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1147 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1148 97f90cbf Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
1149 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1150 1567a005 Edgar E. Iglesias
        return;
1151 1567a005 Edgar E. Iglesias
    }
1152 1567a005 Edgar E. Iglesias
1153 1567a005 Edgar E. Iglesias
    qemu_log ("unimplemented FPU insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1154 1567a005 Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1155 1567a005 Edgar E. Iglesias
}
1156 1567a005 Edgar E. Iglesias
1157 4acb54ba Edgar E. Iglesias
static void dec_null(DisasContext *dc)
1158 4acb54ba Edgar E. Iglesias
{
1159 02b33596 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1160 02b33596 Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1161 02b33596 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1162 02b33596 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1163 02b33596 Edgar E. Iglesias
        return;
1164 02b33596 Edgar E. Iglesias
    }
1165 4acb54ba Edgar E. Iglesias
    qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1166 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1167 4acb54ba Edgar E. Iglesias
}
1168 4acb54ba Edgar E. Iglesias
1169 4acb54ba Edgar E. Iglesias
static struct decoder_info {
1170 4acb54ba Edgar E. Iglesias
    struct {
1171 4acb54ba Edgar E. Iglesias
        uint32_t bits;
1172 4acb54ba Edgar E. Iglesias
        uint32_t mask;
1173 4acb54ba Edgar E. Iglesias
    };
1174 4acb54ba Edgar E. Iglesias
    void (*dec)(DisasContext *dc);
1175 4acb54ba Edgar E. Iglesias
} decinfo[] = {
1176 4acb54ba Edgar E. Iglesias
    {DEC_ADD, dec_add},
1177 4acb54ba Edgar E. Iglesias
    {DEC_SUB, dec_sub},
1178 4acb54ba Edgar E. Iglesias
    {DEC_AND, dec_and},
1179 4acb54ba Edgar E. Iglesias
    {DEC_XOR, dec_xor},
1180 4acb54ba Edgar E. Iglesias
    {DEC_OR, dec_or},
1181 4acb54ba Edgar E. Iglesias
    {DEC_BIT, dec_bit},
1182 4acb54ba Edgar E. Iglesias
    {DEC_BARREL, dec_barrel},
1183 4acb54ba Edgar E. Iglesias
    {DEC_LD, dec_load},
1184 4acb54ba Edgar E. Iglesias
    {DEC_ST, dec_store},
1185 4acb54ba Edgar E. Iglesias
    {DEC_IMM, dec_imm},
1186 4acb54ba Edgar E. Iglesias
    {DEC_BR, dec_br},
1187 4acb54ba Edgar E. Iglesias
    {DEC_BCC, dec_bcc},
1188 4acb54ba Edgar E. Iglesias
    {DEC_RTS, dec_rts},
1189 1567a005 Edgar E. Iglesias
    {DEC_FPU, dec_fpu},
1190 4acb54ba Edgar E. Iglesias
    {DEC_MUL, dec_mul},
1191 4acb54ba Edgar E. Iglesias
    {DEC_DIV, dec_div},
1192 4acb54ba Edgar E. Iglesias
    {DEC_MSR, dec_msr},
1193 4acb54ba Edgar E. Iglesias
    {{0, 0}, dec_null}
1194 4acb54ba Edgar E. Iglesias
};
1195 4acb54ba Edgar E. Iglesias
1196 4acb54ba Edgar E. Iglesias
static inline void decode(DisasContext *dc)
1197 4acb54ba Edgar E. Iglesias
{
1198 4acb54ba Edgar E. Iglesias
    uint32_t ir;
1199 4acb54ba Edgar E. Iglesias
    int i;
1200 4acb54ba Edgar E. Iglesias
1201 4acb54ba Edgar E. Iglesias
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
1202 4acb54ba Edgar E. Iglesias
        tcg_gen_debug_insn_start(dc->pc);
1203 4acb54ba Edgar E. Iglesias
1204 4acb54ba Edgar E. Iglesias
    dc->ir = ir = ldl_code(dc->pc);
1205 4acb54ba Edgar E. Iglesias
    LOG_DIS("%8.8x\t", dc->ir);
1206 4acb54ba Edgar E. Iglesias
1207 4acb54ba Edgar E. Iglesias
    if (dc->ir)
1208 4acb54ba Edgar E. Iglesias
        dc->nr_nops = 0;
1209 4acb54ba Edgar E. Iglesias
    else {
1210 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1211 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1212 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
1213 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1214 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1215 1567a005 Edgar E. Iglesias
            return;
1216 1567a005 Edgar E. Iglesias
        }
1217 1567a005 Edgar E. Iglesias
1218 4acb54ba Edgar E. Iglesias
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1219 4acb54ba Edgar E. Iglesias
        dc->nr_nops++;
1220 4acb54ba Edgar E. Iglesias
        if (dc->nr_nops > 4)
1221 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "fetching nop sequence\n");
1222 4acb54ba Edgar E. Iglesias
    }
1223 4acb54ba Edgar E. Iglesias
    /* bit 2 seems to indicate insn type.  */
1224 4acb54ba Edgar E. Iglesias
    dc->type_b = ir & (1 << 29);
1225 4acb54ba Edgar E. Iglesias
1226 4acb54ba Edgar E. Iglesias
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1227 4acb54ba Edgar E. Iglesias
    dc->rd = EXTRACT_FIELD(ir, 21, 25);
1228 4acb54ba Edgar E. Iglesias
    dc->ra = EXTRACT_FIELD(ir, 16, 20);
1229 4acb54ba Edgar E. Iglesias
    dc->rb = EXTRACT_FIELD(ir, 11, 15);
1230 4acb54ba Edgar E. Iglesias
    dc->imm = EXTRACT_FIELD(ir, 0, 15);
1231 4acb54ba Edgar E. Iglesias
1232 4acb54ba Edgar E. Iglesias
    /* Large switch for all insns.  */
1233 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1234 4acb54ba Edgar E. Iglesias
        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1235 4acb54ba Edgar E. Iglesias
            decinfo[i].dec(dc);
1236 4acb54ba Edgar E. Iglesias
            break;
1237 4acb54ba Edgar E. Iglesias
        }
1238 4acb54ba Edgar E. Iglesias
    }
1239 4acb54ba Edgar E. Iglesias
}
1240 4acb54ba Edgar E. Iglesias
1241 4acb54ba Edgar E. Iglesias
static void check_breakpoint(CPUState *env, DisasContext *dc)
1242 4acb54ba Edgar E. Iglesias
{
1243 4acb54ba Edgar E. Iglesias
    CPUBreakpoint *bp;
1244 4acb54ba Edgar E. Iglesias
1245 72cf2d4f Blue Swirl
    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1246 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1247 4acb54ba Edgar E. Iglesias
            if (bp->pc == dc->pc) {
1248 4acb54ba Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1249 4acb54ba Edgar E. Iglesias
                dc->is_jmp = DISAS_UPDATE;
1250 4acb54ba Edgar E. Iglesias
             }
1251 4acb54ba Edgar E. Iglesias
        }
1252 4acb54ba Edgar E. Iglesias
    }
1253 4acb54ba Edgar E. Iglesias
}
1254 4acb54ba Edgar E. Iglesias
1255 4acb54ba Edgar E. Iglesias
/* generate intermediate code for basic block 'tb'.  */
1256 4acb54ba Edgar E. Iglesias
static void
1257 4acb54ba Edgar E. Iglesias
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
1258 4acb54ba Edgar E. Iglesias
                               int search_pc)
1259 4acb54ba Edgar E. Iglesias
{
1260 4acb54ba Edgar E. Iglesias
    uint16_t *gen_opc_end;
1261 4acb54ba Edgar E. Iglesias
    uint32_t pc_start;
1262 4acb54ba Edgar E. Iglesias
    int j, lj;
1263 4acb54ba Edgar E. Iglesias
    struct DisasContext ctx;
1264 4acb54ba Edgar E. Iglesias
    struct DisasContext *dc = &ctx;
1265 4acb54ba Edgar E. Iglesias
    uint32_t next_page_start, org_flags;
1266 4acb54ba Edgar E. Iglesias
    target_ulong npc;
1267 4acb54ba Edgar E. Iglesias
    int num_insns;
1268 4acb54ba Edgar E. Iglesias
    int max_insns;
1269 4acb54ba Edgar E. Iglesias
1270 4acb54ba Edgar E. Iglesias
    qemu_log_try_set_file(stderr);
1271 4acb54ba Edgar E. Iglesias
1272 4acb54ba Edgar E. Iglesias
    pc_start = tb->pc;
1273 4acb54ba Edgar E. Iglesias
    dc->env = env;
1274 4acb54ba Edgar E. Iglesias
    dc->tb = tb;
1275 4acb54ba Edgar E. Iglesias
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1276 4acb54ba Edgar E. Iglesias
1277 4acb54ba Edgar E. Iglesias
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1278 4acb54ba Edgar E. Iglesias
1279 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_NEXT;
1280 4acb54ba Edgar E. Iglesias
    dc->jmp = 0;
1281 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1282 4acb54ba Edgar E. Iglesias
    dc->ppc = pc_start;
1283 4acb54ba Edgar E. Iglesias
    dc->pc = pc_start;
1284 4acb54ba Edgar E. Iglesias
    dc->cache_pc = -1;
1285 4acb54ba Edgar E. Iglesias
    dc->singlestep_enabled = env->singlestep_enabled;
1286 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 0;
1287 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 0;
1288 4acb54ba Edgar E. Iglesias
    dc->nr_nops = 0;
1289 4acb54ba Edgar E. Iglesias
1290 4acb54ba Edgar E. Iglesias
    if (pc_start & 3)
1291 4acb54ba Edgar E. Iglesias
        cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
1292 4acb54ba Edgar E. Iglesias
1293 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1294 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1295 4acb54ba Edgar E. Iglesias
        qemu_log("--------------\n");
1296 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1297 4acb54ba Edgar E. Iglesias
#endif
1298 4acb54ba Edgar E. Iglesias
    }
1299 4acb54ba Edgar E. Iglesias
1300 4acb54ba Edgar E. Iglesias
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1301 4acb54ba Edgar E. Iglesias
    lj = -1;
1302 4acb54ba Edgar E. Iglesias
    num_insns = 0;
1303 4acb54ba Edgar E. Iglesias
    max_insns = tb->cflags & CF_COUNT_MASK;
1304 4acb54ba Edgar E. Iglesias
    if (max_insns == 0)
1305 4acb54ba Edgar E. Iglesias
        max_insns = CF_COUNT_MASK;
1306 4acb54ba Edgar E. Iglesias
1307 4acb54ba Edgar E. Iglesias
    gen_icount_start();
1308 4acb54ba Edgar E. Iglesias
    do
1309 4acb54ba Edgar E. Iglesias
    {
1310 4acb54ba Edgar E. Iglesias
#if SIM_COMPAT
1311 4acb54ba Edgar E. Iglesias
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1312 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1313 4acb54ba Edgar E. Iglesias
            gen_helper_debug();
1314 4acb54ba Edgar E. Iglesias
        }
1315 4acb54ba Edgar E. Iglesias
#endif
1316 4acb54ba Edgar E. Iglesias
        check_breakpoint(env, dc);
1317 4acb54ba Edgar E. Iglesias
1318 4acb54ba Edgar E. Iglesias
        if (search_pc) {
1319 4acb54ba Edgar E. Iglesias
            j = gen_opc_ptr - gen_opc_buf;
1320 4acb54ba Edgar E. Iglesias
            if (lj < j) {
1321 4acb54ba Edgar E. Iglesias
                lj++;
1322 4acb54ba Edgar E. Iglesias
                while (lj < j)
1323 4acb54ba Edgar E. Iglesias
                    gen_opc_instr_start[lj++] = 0;
1324 4acb54ba Edgar E. Iglesias
            }
1325 4acb54ba Edgar E. Iglesias
            gen_opc_pc[lj] = dc->pc;
1326 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj] = 1;
1327 4acb54ba Edgar E. Iglesias
                        gen_opc_icount[lj] = num_insns;
1328 4acb54ba Edgar E. Iglesias
        }
1329 4acb54ba Edgar E. Iglesias
1330 4acb54ba Edgar E. Iglesias
        /* Pretty disas.  */
1331 4acb54ba Edgar E. Iglesias
        LOG_DIS("%8.8x:\t", dc->pc);
1332 4acb54ba Edgar E. Iglesias
1333 4acb54ba Edgar E. Iglesias
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1334 4acb54ba Edgar E. Iglesias
            gen_io_start();
1335 4acb54ba Edgar E. Iglesias
1336 4acb54ba Edgar E. Iglesias
        dc->clear_imm = 1;
1337 4acb54ba Edgar E. Iglesias
        decode(dc);
1338 4acb54ba Edgar E. Iglesias
        if (dc->clear_imm)
1339 4acb54ba Edgar E. Iglesias
            dc->tb_flags &= ~IMM_FLAG;
1340 4acb54ba Edgar E. Iglesias
        dc->ppc = dc->pc;
1341 4acb54ba Edgar E. Iglesias
        dc->pc += 4;
1342 4acb54ba Edgar E. Iglesias
        num_insns++;
1343 4acb54ba Edgar E. Iglesias
1344 4acb54ba Edgar E. Iglesias
        if (dc->delayed_branch) {
1345 4acb54ba Edgar E. Iglesias
            dc->delayed_branch--;
1346 4acb54ba Edgar E. Iglesias
            if (!dc->delayed_branch) {
1347 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTI_FLAG)
1348 4acb54ba Edgar E. Iglesias
                    do_rti(dc);
1349 4acb54ba Edgar E. Iglesias
                 if (dc->tb_flags & DRTB_FLAG)
1350 4acb54ba Edgar E. Iglesias
                    do_rtb(dc);
1351 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTE_FLAG)
1352 4acb54ba Edgar E. Iglesias
                    do_rte(dc);
1353 4acb54ba Edgar E. Iglesias
                /* Clear the delay slot flag.  */
1354 4acb54ba Edgar E. Iglesias
                dc->tb_flags &= ~D_FLAG;
1355 4acb54ba Edgar E. Iglesias
                /* If it is a direct jump, try direct chaining.  */
1356 4acb54ba Edgar E. Iglesias
                if (dc->jmp != JMP_DIRECT) {
1357 4acb54ba Edgar E. Iglesias
                    eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1358 4acb54ba Edgar E. Iglesias
                    dc->is_jmp = DISAS_JUMP;
1359 4acb54ba Edgar E. Iglesias
                }
1360 4acb54ba Edgar E. Iglesias
                break;
1361 4acb54ba Edgar E. Iglesias
            }
1362 4acb54ba Edgar E. Iglesias
        }
1363 4acb54ba Edgar E. Iglesias
        if (env->singlestep_enabled)
1364 4acb54ba Edgar E. Iglesias
            break;
1365 4acb54ba Edgar E. Iglesias
    } while (!dc->is_jmp && !dc->cpustate_changed
1366 4acb54ba Edgar E. Iglesias
         && gen_opc_ptr < gen_opc_end
1367 4acb54ba Edgar E. Iglesias
                 && !singlestep
1368 4acb54ba Edgar E. Iglesias
         && (dc->pc < next_page_start)
1369 4acb54ba Edgar E. Iglesias
                 && num_insns < max_insns);
1370 4acb54ba Edgar E. Iglesias
1371 4acb54ba Edgar E. Iglesias
    npc = dc->pc;
1372 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
1373 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & D_FLAG) {
1374 4acb54ba Edgar E. Iglesias
            dc->is_jmp = DISAS_UPDATE;
1375 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1376 4acb54ba Edgar E. Iglesias
            sync_jmpstate(dc);
1377 4acb54ba Edgar E. Iglesias
        } else
1378 4acb54ba Edgar E. Iglesias
            npc = dc->jmp_pc;
1379 4acb54ba Edgar E. Iglesias
    }
1380 4acb54ba Edgar E. Iglesias
1381 4acb54ba Edgar E. Iglesias
    if (tb->cflags & CF_LAST_IO)
1382 4acb54ba Edgar E. Iglesias
        gen_io_end();
1383 4acb54ba Edgar E. Iglesias
    /* Force an update if the per-tb cpu state has changed.  */
1384 4acb54ba Edgar E. Iglesias
    if (dc->is_jmp == DISAS_NEXT
1385 4acb54ba Edgar E. Iglesias
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1386 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
1387 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1388 4acb54ba Edgar E. Iglesias
    }
1389 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1390 4acb54ba Edgar E. Iglesias
1391 4acb54ba Edgar E. Iglesias
    if (unlikely(env->singlestep_enabled)) {
1392 4acb54ba Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_DEBUG);
1393 4acb54ba Edgar E. Iglesias
        if (dc->is_jmp == DISAS_NEXT)
1394 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1395 4acb54ba Edgar E. Iglesias
    } else {
1396 4acb54ba Edgar E. Iglesias
        switch(dc->is_jmp) {
1397 4acb54ba Edgar E. Iglesias
            case DISAS_NEXT:
1398 4acb54ba Edgar E. Iglesias
                gen_goto_tb(dc, 1, npc);
1399 4acb54ba Edgar E. Iglesias
                break;
1400 4acb54ba Edgar E. Iglesias
            default:
1401 4acb54ba Edgar E. Iglesias
            case DISAS_JUMP:
1402 4acb54ba Edgar E. Iglesias
            case DISAS_UPDATE:
1403 4acb54ba Edgar E. Iglesias
                /* indicate that the hash table must be used
1404 4acb54ba Edgar E. Iglesias
                   to find the next TB */
1405 4acb54ba Edgar E. Iglesias
                tcg_gen_exit_tb(0);
1406 4acb54ba Edgar E. Iglesias
                break;
1407 4acb54ba Edgar E. Iglesias
            case DISAS_TB_JUMP:
1408 4acb54ba Edgar E. Iglesias
                /* nothing more to generate */
1409 4acb54ba Edgar E. Iglesias
                break;
1410 4acb54ba Edgar E. Iglesias
        }
1411 4acb54ba Edgar E. Iglesias
    }
1412 4acb54ba Edgar E. Iglesias
    gen_icount_end(tb, num_insns);
1413 4acb54ba Edgar E. Iglesias
    *gen_opc_ptr = INDEX_op_end;
1414 4acb54ba Edgar E. Iglesias
    if (search_pc) {
1415 4acb54ba Edgar E. Iglesias
        j = gen_opc_ptr - gen_opc_buf;
1416 4acb54ba Edgar E. Iglesias
        lj++;
1417 4acb54ba Edgar E. Iglesias
        while (lj <= j)
1418 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj++] = 0;
1419 4acb54ba Edgar E. Iglesias
    } else {
1420 4acb54ba Edgar E. Iglesias
        tb->size = dc->pc - pc_start;
1421 4acb54ba Edgar E. Iglesias
                tb->icount = num_insns;
1422 4acb54ba Edgar E. Iglesias
    }
1423 4acb54ba Edgar E. Iglesias
1424 4acb54ba Edgar E. Iglesias
#ifdef DEBUG_DISAS
1425 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1426 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1427 4acb54ba Edgar E. Iglesias
        qemu_log("\n");
1428 4acb54ba Edgar E. Iglesias
#if DISAS_GNU
1429 4acb54ba Edgar E. Iglesias
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1430 4acb54ba Edgar E. Iglesias
#endif
1431 4acb54ba Edgar E. Iglesias
        qemu_log("\nisize=%d osize=%zd\n",
1432 4acb54ba Edgar E. Iglesias
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1433 4acb54ba Edgar E. Iglesias
    }
1434 4acb54ba Edgar E. Iglesias
#endif
1435 4acb54ba Edgar E. Iglesias
#endif
1436 4acb54ba Edgar E. Iglesias
    assert(!dc->abort_at_next_insn);
1437 4acb54ba Edgar E. Iglesias
}
1438 4acb54ba Edgar E. Iglesias
1439 4acb54ba Edgar E. Iglesias
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1440 4acb54ba Edgar E. Iglesias
{
1441 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 0);
1442 4acb54ba Edgar E. Iglesias
}
1443 4acb54ba Edgar E. Iglesias
1444 4acb54ba Edgar E. Iglesias
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1445 4acb54ba Edgar E. Iglesias
{
1446 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 1);
1447 4acb54ba Edgar E. Iglesias
}
1448 4acb54ba Edgar E. Iglesias
1449 4acb54ba Edgar E. Iglesias
void cpu_dump_state (CPUState *env, FILE *f,
1450 4acb54ba Edgar E. Iglesias
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1451 4acb54ba Edgar E. Iglesias
                     int flags)
1452 4acb54ba Edgar E. Iglesias
{
1453 4acb54ba Edgar E. Iglesias
    int i;
1454 4acb54ba Edgar E. Iglesias
1455 4acb54ba Edgar E. Iglesias
    if (!env || !f)
1456 4acb54ba Edgar E. Iglesias
        return;
1457 4acb54ba Edgar E. Iglesias
1458 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "IN: PC=%x %s\n",
1459 4acb54ba Edgar E. Iglesias
                env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1460 4c24aa0a Michal Simek
    cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n",
1461 4c24aa0a Michal Simek
             env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1462 4acb54ba Edgar E. Iglesias
             env->debug, env->imm, env->iflags);
1463 17c52a43 Edgar E. Iglesias
    cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1464 4acb54ba Edgar E. Iglesias
             env->btaken, env->btarget,
1465 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1466 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
1467 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_EIP),
1468 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_IE));
1469 17c52a43 Edgar E. Iglesias
1470 4acb54ba Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
1471 4acb54ba Edgar E. Iglesias
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1472 4acb54ba Edgar E. Iglesias
        if ((i + 1) % 4 == 0)
1473 4acb54ba Edgar E. Iglesias
            cpu_fprintf(f, "\n");
1474 4acb54ba Edgar E. Iglesias
        }
1475 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "\n\n");
1476 4acb54ba Edgar E. Iglesias
}
1477 4acb54ba Edgar E. Iglesias
1478 4acb54ba Edgar E. Iglesias
CPUState *cpu_mb_init (const char *cpu_model)
1479 4acb54ba Edgar E. Iglesias
{
1480 4acb54ba Edgar E. Iglesias
    CPUState *env;
1481 4acb54ba Edgar E. Iglesias
    static int tcg_initialized = 0;
1482 4acb54ba Edgar E. Iglesias
    int i;
1483 4acb54ba Edgar E. Iglesias
1484 4acb54ba Edgar E. Iglesias
    env = qemu_mallocz(sizeof(CPUState));
1485 4acb54ba Edgar E. Iglesias
1486 4acb54ba Edgar E. Iglesias
    cpu_exec_init(env);
1487 4acb54ba Edgar E. Iglesias
    cpu_reset(env);
1488 4acb54ba Edgar E. Iglesias
1489 4acb54ba Edgar E. Iglesias
1490 4acb54ba Edgar E. Iglesias
    if (tcg_initialized)
1491 4acb54ba Edgar E. Iglesias
        return env;
1492 4acb54ba Edgar E. Iglesias
1493 4acb54ba Edgar E. Iglesias
    tcg_initialized = 1;
1494 4acb54ba Edgar E. Iglesias
1495 4acb54ba Edgar E. Iglesias
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1496 4acb54ba Edgar E. Iglesias
1497 4acb54ba Edgar E. Iglesias
    env_debug = tcg_global_mem_new(TCG_AREG0, 
1498 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, debug),
1499 4acb54ba Edgar E. Iglesias
                    "debug0");
1500 4acb54ba Edgar E. Iglesias
    env_iflags = tcg_global_mem_new(TCG_AREG0, 
1501 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, iflags),
1502 4acb54ba Edgar E. Iglesias
                    "iflags");
1503 4acb54ba Edgar E. Iglesias
    env_imm = tcg_global_mem_new(TCG_AREG0, 
1504 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, imm),
1505 4acb54ba Edgar E. Iglesias
                    "imm");
1506 4acb54ba Edgar E. Iglesias
    env_btarget = tcg_global_mem_new(TCG_AREG0,
1507 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btarget),
1508 4acb54ba Edgar E. Iglesias
                     "btarget");
1509 4acb54ba Edgar E. Iglesias
    env_btaken = tcg_global_mem_new(TCG_AREG0,
1510 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btaken),
1511 4acb54ba Edgar E. Iglesias
                     "btaken");
1512 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1513 4acb54ba Edgar E. Iglesias
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1514 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, regs[i]),
1515 4acb54ba Edgar E. Iglesias
                          regnames[i]);
1516 4acb54ba Edgar E. Iglesias
    }
1517 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1518 4acb54ba Edgar E. Iglesias
        cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
1519 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, sregs[i]),
1520 4acb54ba Edgar E. Iglesias
                          special_regnames[i]);
1521 4acb54ba Edgar E. Iglesias
    }
1522 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 2
1523 4acb54ba Edgar E. Iglesias
#include "helper.h"
1524 4acb54ba Edgar E. Iglesias
1525 4acb54ba Edgar E. Iglesias
    return env;
1526 4acb54ba Edgar E. Iglesias
}
1527 4acb54ba Edgar E. Iglesias
1528 4acb54ba Edgar E. Iglesias
void cpu_reset (CPUState *env)
1529 4acb54ba Edgar E. Iglesias
{
1530 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1531 4acb54ba Edgar E. Iglesias
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1532 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1533 4acb54ba Edgar E. Iglesias
    }
1534 4acb54ba Edgar E. Iglesias
1535 4acb54ba Edgar E. Iglesias
    memset(env, 0, offsetof(CPUMBState, breakpoints));
1536 4acb54ba Edgar E. Iglesias
    tlb_flush(env, 1);
1537 4acb54ba Edgar E. Iglesias
1538 4898427e Edgar E. Iglesias
    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
1539 4898427e Edgar E. Iglesias
                       | PVR0_USE_BARREL_MASK \
1540 4898427e Edgar E. Iglesias
                       | PVR0_USE_DIV_MASK \
1541 4898427e Edgar E. Iglesias
                       | PVR0_USE_HW_MUL_MASK \
1542 4898427e Edgar E. Iglesias
                       | PVR0_USE_EXC_MASK \
1543 4898427e Edgar E. Iglesias
                       | PVR0_USE_ICACHE_MASK \
1544 4898427e Edgar E. Iglesias
                       | PVR0_USE_DCACHE_MASK \
1545 4898427e Edgar E. Iglesias
                       | PVR0_USE_MMU \
1546 4898427e Edgar E. Iglesias
                       | (0xb << 8);
1547 4898427e Edgar E. Iglesias
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
1548 4898427e Edgar E. Iglesias
                        | PVR2_D_LMB_MASK \
1549 4898427e Edgar E. Iglesias
                        | PVR2_I_OPB_MASK \
1550 4898427e Edgar E. Iglesias
                        | PVR2_I_LMB_MASK \
1551 4898427e Edgar E. Iglesias
                        | PVR2_USE_MSR_INSTR \
1552 4898427e Edgar E. Iglesias
                        | PVR2_USE_PCMP_INSTR \
1553 4898427e Edgar E. Iglesias
                        | PVR2_USE_BARREL_MASK \
1554 4898427e Edgar E. Iglesias
                        | PVR2_USE_DIV_MASK \
1555 4898427e Edgar E. Iglesias
                        | PVR2_USE_HW_MUL_MASK \
1556 4898427e Edgar E. Iglesias
                        | PVR2_USE_MUL64_MASK \
1557 4898427e Edgar E. Iglesias
                        | 0;
1558 4898427e Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
1559 4898427e Edgar E. Iglesias
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
1560 4898427e Edgar E. Iglesias
1561 4acb54ba Edgar E. Iglesias
    env->sregs[SR_MSR] = 0;
1562 4acb54ba Edgar E. Iglesias
#if defined(CONFIG_USER_ONLY)
1563 4acb54ba Edgar E. Iglesias
    /* start in user mode with interrupts enabled.  */
1564 4acb54ba Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
1565 4acb54ba Edgar E. Iglesias
#else
1566 4acb54ba Edgar E. Iglesias
    mmu_init(&env->mmu);
1567 4898427e Edgar E. Iglesias
    env->mmu.c_mmu = 3;
1568 4898427e Edgar E. Iglesias
    env->mmu.c_mmu_tlb_access = 3;
1569 4898427e Edgar E. Iglesias
    env->mmu.c_mmu_zones = 16;
1570 4acb54ba Edgar E. Iglesias
#endif
1571 4acb54ba Edgar E. Iglesias
}
1572 4acb54ba Edgar E. Iglesias
1573 4acb54ba Edgar E. Iglesias
void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
1574 4acb54ba Edgar E. Iglesias
                 unsigned long searched_pc, int pc_pos, void *puc)
1575 4acb54ba Edgar E. Iglesias
{
1576 4acb54ba Edgar E. Iglesias
    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
1577 4acb54ba Edgar E. Iglesias
}