Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ 72cf2d4f

History | View | Annotate | Download (44.1 kB)

1 4acb54ba Edgar E. Iglesias
/*
2 4acb54ba Edgar E. Iglesias
 *  Xilinx MicroBlaze emulation for qemu: main translation routines.
3 4acb54ba Edgar E. Iglesias
 *
4 4acb54ba Edgar E. Iglesias
 *  Copyright (c) 2009 Edgar E. Iglesias.
5 4acb54ba Edgar E. Iglesias
 *
6 4acb54ba Edgar E. Iglesias
 * This library is free software; you can redistribute it and/or
7 4acb54ba Edgar E. Iglesias
 * modify it under the terms of the GNU Lesser General Public
8 4acb54ba Edgar E. Iglesias
 * License as published by the Free Software Foundation; either
9 4acb54ba Edgar E. Iglesias
 * version 2 of the License, or (at your option) any later version.
10 4acb54ba Edgar E. Iglesias
 *
11 4acb54ba Edgar E. Iglesias
 * This library is distributed in the hope that it will be useful,
12 4acb54ba Edgar E. Iglesias
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 4acb54ba Edgar E. Iglesias
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 4acb54ba Edgar E. Iglesias
 * Lesser General Public License for more details.
15 4acb54ba Edgar E. Iglesias
 *
16 4acb54ba Edgar E. Iglesias
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 4acb54ba Edgar E. Iglesias
 */
19 4acb54ba Edgar E. Iglesias
20 4acb54ba Edgar E. Iglesias
#include <stdarg.h>
21 4acb54ba Edgar E. Iglesias
#include <stdlib.h>
22 4acb54ba Edgar E. Iglesias
#include <stdio.h>
23 4acb54ba Edgar E. Iglesias
#include <string.h>
24 4acb54ba Edgar E. Iglesias
#include <inttypes.h>
25 4acb54ba Edgar E. Iglesias
#include <assert.h>
26 4acb54ba Edgar E. Iglesias
27 4acb54ba Edgar E. Iglesias
#include "cpu.h"
28 4acb54ba Edgar E. Iglesias
#include "exec-all.h"
29 4acb54ba Edgar E. Iglesias
#include "disas.h"
30 4acb54ba Edgar E. Iglesias
#include "tcg-op.h"
31 4acb54ba Edgar E. Iglesias
#include "helper.h"
32 4acb54ba Edgar E. Iglesias
#include "microblaze-decode.h"
33 4acb54ba Edgar E. Iglesias
#include "qemu-common.h"
34 4acb54ba Edgar E. Iglesias
35 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 1
36 4acb54ba Edgar E. Iglesias
#include "helper.h"
37 4acb54ba Edgar E. Iglesias
38 4acb54ba Edgar E. Iglesias
#define SIM_COMPAT 0
39 4acb54ba Edgar E. Iglesias
#define DISAS_GNU 1
40 4acb54ba Edgar E. Iglesias
#define DISAS_MB 1
41 4acb54ba Edgar E. Iglesias
#if DISAS_MB && !SIM_COMPAT
42 4acb54ba Edgar E. Iglesias
#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
43 4acb54ba Edgar E. Iglesias
#else
44 4acb54ba Edgar E. Iglesias
#  define LOG_DIS(...) do { } while (0)
45 4acb54ba Edgar E. Iglesias
#endif
46 4acb54ba Edgar E. Iglesias
47 4acb54ba Edgar E. Iglesias
#define D(x)
48 4acb54ba Edgar E. Iglesias
49 4acb54ba Edgar E. Iglesias
#define EXTRACT_FIELD(src, start, end) \
50 4acb54ba Edgar E. Iglesias
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
51 4acb54ba Edgar E. Iglesias
52 4acb54ba Edgar E. Iglesias
static TCGv env_debug;
53 4acb54ba Edgar E. Iglesias
static TCGv_ptr cpu_env;
54 4acb54ba Edgar E. Iglesias
static TCGv cpu_R[32];
55 4acb54ba Edgar E. Iglesias
static TCGv cpu_SR[18];
56 4acb54ba Edgar E. Iglesias
static TCGv env_imm;
57 4acb54ba Edgar E. Iglesias
static TCGv env_btaken;
58 4acb54ba Edgar E. Iglesias
static TCGv env_btarget;
59 4acb54ba Edgar E. Iglesias
static TCGv env_iflags;
60 4acb54ba Edgar E. Iglesias
61 4acb54ba Edgar E. Iglesias
#include "gen-icount.h"
62 4acb54ba Edgar E. Iglesias
63 4acb54ba Edgar E. Iglesias
/* This is the state at translation time.  */
64 4acb54ba Edgar E. Iglesias
typedef struct DisasContext {
65 4acb54ba Edgar E. Iglesias
    CPUState *env;
66 4acb54ba Edgar E. Iglesias
    target_ulong pc, ppc;
67 4acb54ba Edgar E. Iglesias
    target_ulong cache_pc;
68 4acb54ba Edgar E. Iglesias
69 4acb54ba Edgar E. Iglesias
    /* Decoder.  */
70 4acb54ba Edgar E. Iglesias
    int type_b;
71 4acb54ba Edgar E. Iglesias
    uint32_t ir;
72 4acb54ba Edgar E. Iglesias
    uint8_t opcode;
73 4acb54ba Edgar E. Iglesias
    uint8_t rd, ra, rb;
74 4acb54ba Edgar E. Iglesias
    uint16_t imm;
75 4acb54ba Edgar E. Iglesias
76 4acb54ba Edgar E. Iglesias
    unsigned int cpustate_changed;
77 4acb54ba Edgar E. Iglesias
    unsigned int delayed_branch;
78 4acb54ba Edgar E. Iglesias
    unsigned int tb_flags, synced_flags; /* tb dependent flags.  */
79 4acb54ba Edgar E. Iglesias
    unsigned int clear_imm;
80 4acb54ba Edgar E. Iglesias
    int is_jmp;
81 4acb54ba Edgar E. Iglesias
82 4acb54ba Edgar E. Iglesias
#define JMP_NOJMP    0
83 4acb54ba Edgar E. Iglesias
#define JMP_DIRECT   1
84 4acb54ba Edgar E. Iglesias
#define JMP_INDIRECT 2
85 4acb54ba Edgar E. Iglesias
    unsigned int jmp;
86 4acb54ba Edgar E. Iglesias
    uint32_t jmp_pc;
87 4acb54ba Edgar E. Iglesias
88 4acb54ba Edgar E. Iglesias
    int abort_at_next_insn;
89 4acb54ba Edgar E. Iglesias
    int nr_nops;
90 4acb54ba Edgar E. Iglesias
    struct TranslationBlock *tb;
91 4acb54ba Edgar E. Iglesias
    int singlestep_enabled;
92 4acb54ba Edgar E. Iglesias
} DisasContext;
93 4acb54ba Edgar E. Iglesias
94 4acb54ba Edgar E. Iglesias
const static char *regnames[] =
95 4acb54ba Edgar E. Iglesias
{
96 4acb54ba Edgar E. Iglesias
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
97 4acb54ba Edgar E. Iglesias
    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
98 4acb54ba Edgar E. Iglesias
    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
99 4acb54ba Edgar E. Iglesias
    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
100 4acb54ba Edgar E. Iglesias
};
101 4acb54ba Edgar E. Iglesias
102 4acb54ba Edgar E. Iglesias
const static char *special_regnames[] =
103 4acb54ba Edgar E. Iglesias
{
104 4acb54ba Edgar E. Iglesias
    "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7",
105 4acb54ba Edgar E. Iglesias
    "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
106 4acb54ba Edgar E. Iglesias
    "sr16", "sr17", "sr18"
107 4acb54ba Edgar E. Iglesias
};
108 4acb54ba Edgar E. Iglesias
109 4acb54ba Edgar E. Iglesias
/* Sign extend at translation time.  */
110 4acb54ba Edgar E. Iglesias
static inline int sign_extend(unsigned int val, unsigned int width)
111 4acb54ba Edgar E. Iglesias
{
112 4acb54ba Edgar E. Iglesias
        int sval;
113 4acb54ba Edgar E. Iglesias
114 4acb54ba Edgar E. Iglesias
        /* LSL.  */
115 4acb54ba Edgar E. Iglesias
        val <<= 31 - width;
116 4acb54ba Edgar E. Iglesias
        sval = val;
117 4acb54ba Edgar E. Iglesias
        /* ASR.  */
118 4acb54ba Edgar E. Iglesias
        sval >>= 31 - width;
119 4acb54ba Edgar E. Iglesias
        return sval;
120 4acb54ba Edgar E. Iglesias
}
121 4acb54ba Edgar E. Iglesias
122 4acb54ba Edgar E. Iglesias
static inline void t_sync_flags(DisasContext *dc)
123 4acb54ba Edgar E. Iglesias
{
124 4acb54ba Edgar E. Iglesias
    /* Synch the tb dependant flags between translator and runtime.  */
125 4acb54ba Edgar E. Iglesias
    if (dc->tb_flags != dc->synced_flags) {
126 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_iflags, dc->tb_flags);
127 4acb54ba Edgar E. Iglesias
        dc->synced_flags = dc->tb_flags;
128 4acb54ba Edgar E. Iglesias
    }
129 4acb54ba Edgar E. Iglesias
}
130 4acb54ba Edgar E. Iglesias
131 4acb54ba Edgar E. Iglesias
static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
132 4acb54ba Edgar E. Iglesias
{
133 4acb54ba Edgar E. Iglesias
    TCGv_i32 tmp = tcg_const_i32(index);
134 4acb54ba Edgar E. Iglesias
135 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
136 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
137 4acb54ba Edgar E. Iglesias
    gen_helper_raise_exception(tmp);
138 4acb54ba Edgar E. Iglesias
    tcg_temp_free_i32(tmp);
139 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_UPDATE;
140 4acb54ba Edgar E. Iglesias
}
141 4acb54ba Edgar E. Iglesias
142 4acb54ba Edgar E. Iglesias
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
143 4acb54ba Edgar E. Iglesias
{
144 4acb54ba Edgar E. Iglesias
    TranslationBlock *tb;
145 4acb54ba Edgar E. Iglesias
    tb = dc->tb;
146 4acb54ba Edgar E. Iglesias
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
147 4acb54ba Edgar E. Iglesias
        tcg_gen_goto_tb(n);
148 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
149 4acb54ba Edgar E. Iglesias
        tcg_gen_exit_tb((long)tb + n);
150 4acb54ba Edgar E. Iglesias
    } else {
151 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dest);
152 4acb54ba Edgar E. Iglesias
        tcg_gen_exit_tb(0);
153 4acb54ba Edgar E. Iglesias
    }
154 4acb54ba Edgar E. Iglesias
}
155 4acb54ba Edgar E. Iglesias
156 4acb54ba Edgar E. Iglesias
static inline TCGv *dec_alu_op_b(DisasContext *dc)
157 4acb54ba Edgar E. Iglesias
{
158 4acb54ba Edgar E. Iglesias
    if (dc->type_b) {
159 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & IMM_FLAG)
160 4acb54ba Edgar E. Iglesias
            tcg_gen_ori_tl(env_imm, env_imm, dc->imm);
161 4acb54ba Edgar E. Iglesias
        else
162 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm));
163 4acb54ba Edgar E. Iglesias
        return &env_imm;
164 4acb54ba Edgar E. Iglesias
    } else
165 4acb54ba Edgar E. Iglesias
        return &cpu_R[dc->rb];
166 4acb54ba Edgar E. Iglesias
}
167 4acb54ba Edgar E. Iglesias
168 4acb54ba Edgar E. Iglesias
static void dec_add(DisasContext *dc)
169 4acb54ba Edgar E. Iglesias
{
170 4acb54ba Edgar E. Iglesias
    unsigned int k, c;
171 4acb54ba Edgar E. Iglesias
172 4acb54ba Edgar E. Iglesias
    k = dc->opcode & 4;
173 4acb54ba Edgar E. Iglesias
    c = dc->opcode & 2;
174 4acb54ba Edgar E. Iglesias
175 4acb54ba Edgar E. Iglesias
    LOG_DIS("add%s%s%s r%d r%d r%d\n",
176 4acb54ba Edgar E. Iglesias
            dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
177 4acb54ba Edgar E. Iglesias
            dc->rd, dc->ra, dc->rb);
178 4acb54ba Edgar E. Iglesias
179 4acb54ba Edgar E. Iglesias
    if (k && !c && dc->rd)
180 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
181 4acb54ba Edgar E. Iglesias
    else if (dc->rd)
182 4acb54ba Edgar E. Iglesias
        gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
183 4acb54ba Edgar E. Iglesias
                         tcg_const_tl(k), tcg_const_tl(c));
184 4acb54ba Edgar E. Iglesias
    else {
185 4acb54ba Edgar E. Iglesias
        TCGv d = tcg_temp_new();
186 4acb54ba Edgar E. Iglesias
        gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
187 4acb54ba Edgar E. Iglesias
                         tcg_const_tl(k), tcg_const_tl(c));
188 4acb54ba Edgar E. Iglesias
        tcg_temp_free(d);
189 4acb54ba Edgar E. Iglesias
    }
190 4acb54ba Edgar E. Iglesias
}
191 4acb54ba Edgar E. Iglesias
192 4acb54ba Edgar E. Iglesias
static void dec_sub(DisasContext *dc)
193 4acb54ba Edgar E. Iglesias
{
194 4acb54ba Edgar E. Iglesias
    unsigned int u, cmp, k, c;
195 4acb54ba Edgar E. Iglesias
196 4acb54ba Edgar E. Iglesias
    u = dc->imm & 2;
197 4acb54ba Edgar E. Iglesias
    k = dc->opcode & 4;
198 4acb54ba Edgar E. Iglesias
    c = dc->opcode & 2;
199 4acb54ba Edgar E. Iglesias
    cmp = (dc->imm & 1) && (!dc->type_b) && k;
200 4acb54ba Edgar E. Iglesias
201 4acb54ba Edgar E. Iglesias
    if (cmp) {
202 4acb54ba Edgar E. Iglesias
        LOG_DIS("cmp%s r%d, r%d ir=%x\n", u ? "u" : "", dc->rd, dc->ra, dc->ir);
203 4acb54ba Edgar E. Iglesias
        if (dc->rd) {
204 4acb54ba Edgar E. Iglesias
            if (u)
205 4acb54ba Edgar E. Iglesias
                gen_helper_cmpu(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
206 4acb54ba Edgar E. Iglesias
            else
207 4acb54ba Edgar E. Iglesias
                gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
208 4acb54ba Edgar E. Iglesias
        }
209 4acb54ba Edgar E. Iglesias
    } else {
210 4acb54ba Edgar E. Iglesias
        LOG_DIS("sub%s%s r%d, r%d r%d\n",
211 4acb54ba Edgar E. Iglesias
                 k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
212 4acb54ba Edgar E. Iglesias
213 4acb54ba Edgar E. Iglesias
        if (!k || c) {
214 4acb54ba Edgar E. Iglesias
            TCGv t;
215 4acb54ba Edgar E. Iglesias
            t = tcg_temp_new();
216 4acb54ba Edgar E. Iglesias
            if (dc->rd)
217 4acb54ba Edgar E. Iglesias
                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
218 4acb54ba Edgar E. Iglesias
                                 tcg_const_tl(k), tcg_const_tl(c));
219 4acb54ba Edgar E. Iglesias
            else
220 4acb54ba Edgar E. Iglesias
                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
221 4acb54ba Edgar E. Iglesias
                                 tcg_const_tl(k), tcg_const_tl(c));
222 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t);
223 4acb54ba Edgar E. Iglesias
        }
224 4acb54ba Edgar E. Iglesias
        else if (dc->rd)
225 4acb54ba Edgar E. Iglesias
            tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
226 4acb54ba Edgar E. Iglesias
    }
227 4acb54ba Edgar E. Iglesias
}
228 4acb54ba Edgar E. Iglesias
229 4acb54ba Edgar E. Iglesias
static void dec_pattern(DisasContext *dc)
230 4acb54ba Edgar E. Iglesias
{
231 4acb54ba Edgar E. Iglesias
    unsigned int mode;
232 4acb54ba Edgar E. Iglesias
    int l1;
233 4acb54ba Edgar E. Iglesias
234 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 4acb54ba Edgar E. Iglesias
            /* wdc.  */
717 4acb54ba Edgar E. Iglesias
            LOG_DIS("wdc r%d\n", dc->ra);
718 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
719 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
720 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
721 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
722 1567a005 Edgar E. Iglesias
                return;
723 1567a005 Edgar E. Iglesias
            }
724 4acb54ba Edgar E. Iglesias
            break;
725 4acb54ba Edgar E. Iglesias
        case 0x68:
726 4acb54ba Edgar E. Iglesias
            /* wic.  */
727 4acb54ba Edgar E. Iglesias
            LOG_DIS("wic r%d\n", dc->ra);
728 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
729 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
730 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
731 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
732 1567a005 Edgar E. Iglesias
                return;
733 1567a005 Edgar E. Iglesias
            }
734 4acb54ba Edgar E. Iglesias
            break;
735 4acb54ba Edgar E. Iglesias
        default:
736 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
737 4acb54ba Edgar E. Iglesias
                     dc->pc, op, dc->rd, dc->ra, dc->rb);
738 4acb54ba Edgar E. Iglesias
            break;
739 4acb54ba Edgar E. Iglesias
    }
740 4acb54ba Edgar E. Iglesias
}
741 4acb54ba Edgar E. Iglesias
742 4acb54ba Edgar E. Iglesias
static inline void sync_jmpstate(DisasContext *dc)
743 4acb54ba Edgar E. Iglesias
{
744 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
745 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_INDIRECT;
746 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
747 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
748 4acb54ba Edgar E. Iglesias
    }
749 4acb54ba Edgar E. Iglesias
}
750 4acb54ba Edgar E. Iglesias
751 4acb54ba Edgar E. Iglesias
static void dec_imm(DisasContext *dc)
752 4acb54ba Edgar E. Iglesias
{
753 4acb54ba Edgar E. Iglesias
    LOG_DIS("imm %x\n", dc->imm << 16);
754 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_imm, (dc->imm << 16));
755 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= IMM_FLAG;
756 4acb54ba Edgar E. Iglesias
    dc->clear_imm = 0;
757 4acb54ba Edgar E. Iglesias
}
758 4acb54ba Edgar E. Iglesias
759 4acb54ba Edgar E. Iglesias
static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
760 4acb54ba Edgar E. Iglesias
                            unsigned int size)
761 4acb54ba Edgar E. Iglesias
{
762 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
763 4acb54ba Edgar E. Iglesias
764 4acb54ba Edgar E. Iglesias
    if (size == 1) {
765 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld8u(dst, addr, mem_index);
766 4acb54ba Edgar E. Iglesias
    } else if (size == 2) {
767 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld16u(dst, addr, mem_index);
768 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
769 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld32u(dst, addr, mem_index);
770 4acb54ba Edgar E. Iglesias
    } else
771 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect load size %d\n", size);
772 4acb54ba Edgar E. Iglesias
}
773 4acb54ba Edgar E. Iglesias
774 4acb54ba Edgar E. Iglesias
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
775 4acb54ba Edgar E. Iglesias
{
776 4acb54ba Edgar E. Iglesias
    unsigned int extimm = dc->tb_flags & IMM_FLAG;
777 4acb54ba Edgar E. Iglesias
778 4acb54ba Edgar E. Iglesias
    /* Treat the fast cases first.  */
779 4acb54ba Edgar E. Iglesias
    if (!dc->type_b) {
780 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
781 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
782 4acb54ba Edgar E. Iglesias
        return t;
783 4acb54ba Edgar E. Iglesias
    }
784 4acb54ba Edgar E. Iglesias
    /* Immediate.  */
785 4acb54ba Edgar E. Iglesias
    if (!extimm) {
786 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0) {
787 4acb54ba Edgar E. Iglesias
            return &cpu_R[dc->ra];
788 4acb54ba Edgar E. Iglesias
        }
789 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
790 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
791 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
792 4acb54ba Edgar E. Iglesias
    } else {
793 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
794 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
795 4acb54ba Edgar E. Iglesias
    }
796 4acb54ba Edgar E. Iglesias
797 4acb54ba Edgar E. Iglesias
    return t;
798 4acb54ba Edgar E. Iglesias
}
799 4acb54ba Edgar E. Iglesias
800 4acb54ba Edgar E. Iglesias
static void dec_load(DisasContext *dc)
801 4acb54ba Edgar E. Iglesias
{
802 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
803 4acb54ba Edgar E. Iglesias
    unsigned int size;
804 4acb54ba Edgar E. Iglesias
805 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
806 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
807 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
808 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
809 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
810 0187688f Edgar E. Iglesias
        return;
811 0187688f Edgar E. Iglesias
    }
812 4acb54ba Edgar E. Iglesias
813 4acb54ba Edgar E. Iglesias
    LOG_DIS("l %x %d\n", dc->opcode, size);
814 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
815 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
816 4acb54ba Edgar E. Iglesias
817 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
818 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
819 968a40f6 Edgar E. Iglesias
820 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
821 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
822 a12f6507 Edgar E. Iglesias
        TCGv v = tcg_temp_new();
823 a12f6507 Edgar E. Iglesias
824 a12f6507 Edgar E. Iglesias
        /*
825 a12f6507 Edgar E. Iglesias
         * Microblaze gives MMU faults priority over faults due to
826 a12f6507 Edgar E. Iglesias
         * unaligned addresses. That's why we speculatively do the load
827 a12f6507 Edgar E. Iglesias
         * into v. If the load succeeds, we verify alignment of the
828 a12f6507 Edgar E. Iglesias
         * address and if that succeeds we write into the destination reg.
829 a12f6507 Edgar E. Iglesias
         */
830 a12f6507 Edgar E. Iglesias
        gen_load(dc, v, *addr, size);
831 a12f6507 Edgar E. Iglesias
832 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
833 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
834 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(0), tcg_const_tl(size - 1));
835 a12f6507 Edgar E. Iglesias
        if (dc->rd)
836 a12f6507 Edgar E. Iglesias
            tcg_gen_mov_tl(cpu_R[dc->rd], v);
837 a12f6507 Edgar E. Iglesias
        tcg_temp_free(v);
838 968a40f6 Edgar E. Iglesias
    } else {
839 a12f6507 Edgar E. Iglesias
        if (dc->rd) {
840 a12f6507 Edgar E. Iglesias
            gen_load(dc, cpu_R[dc->rd], *addr, size);
841 a12f6507 Edgar E. Iglesias
        } else {
842 a12f6507 Edgar E. Iglesias
            gen_load(dc, env_imm, *addr, size);
843 a12f6507 Edgar E. Iglesias
        }
844 4acb54ba Edgar E. Iglesias
    }
845 4acb54ba Edgar E. Iglesias
846 4acb54ba Edgar E. Iglesias
    if (addr == &t)
847 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
848 4acb54ba Edgar E. Iglesias
}
849 4acb54ba Edgar E. Iglesias
850 4acb54ba Edgar E. Iglesias
static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
851 4acb54ba Edgar E. Iglesias
                      unsigned int size)
852 4acb54ba Edgar E. Iglesias
{
853 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
854 4acb54ba Edgar E. Iglesias
855 4acb54ba Edgar E. Iglesias
    if (size == 1)
856 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st8(val, addr, mem_index);
857 4acb54ba Edgar E. Iglesias
    else if (size == 2) {
858 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st16(val, addr, mem_index);
859 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
860 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st32(val, addr, mem_index);
861 4acb54ba Edgar E. Iglesias
    } else
862 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect store size %d\n", size);
863 4acb54ba Edgar E. Iglesias
}
864 4acb54ba Edgar E. Iglesias
865 4acb54ba Edgar E. Iglesias
static void dec_store(DisasContext *dc)
866 4acb54ba Edgar E. Iglesias
{
867 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
868 4acb54ba Edgar E. Iglesias
    unsigned int size;
869 4acb54ba Edgar E. Iglesias
870 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
871 4acb54ba Edgar E. Iglesias
872 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
873 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
874 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
875 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
876 0187688f Edgar E. Iglesias
        return;
877 0187688f Edgar E. Iglesias
    }
878 0187688f Edgar E. Iglesias
879 4acb54ba Edgar E. Iglesias
    LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
880 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
881 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
882 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
883 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
884 968a40f6 Edgar E. Iglesias
885 a12f6507 Edgar E. Iglesias
    gen_store(dc, *addr, cpu_R[dc->rd], size);
886 a12f6507 Edgar E. Iglesias
887 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
888 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
889 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
890 a12f6507 Edgar E. Iglesias
        /* FIXME: if the alignment is wrong, we should restore the value
891 a12f6507 Edgar E. Iglesias
         *        in memory.
892 a12f6507 Edgar E. Iglesias
         */
893 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
894 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(1), tcg_const_tl(size - 1));
895 968a40f6 Edgar E. Iglesias
    }
896 968a40f6 Edgar E. Iglesias
897 4acb54ba Edgar E. Iglesias
    if (addr == &t)
898 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
899 4acb54ba Edgar E. Iglesias
}
900 4acb54ba Edgar E. Iglesias
901 4acb54ba Edgar E. Iglesias
static inline void eval_cc(DisasContext *dc, unsigned int cc,
902 4acb54ba Edgar E. Iglesias
                           TCGv d, TCGv a, TCGv b)
903 4acb54ba Edgar E. Iglesias
{
904 4acb54ba Edgar E. Iglesias
    int l1;
905 4acb54ba Edgar E. Iglesias
906 4acb54ba Edgar E. Iglesias
    switch (cc) {
907 4acb54ba Edgar E. Iglesias
        case CC_EQ:
908 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
909 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
910 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1);
911 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
912 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
913 4acb54ba Edgar E. Iglesias
            break;
914 4acb54ba Edgar E. Iglesias
        case CC_NE:
915 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
916 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
917 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1);
918 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
919 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
920 4acb54ba Edgar E. Iglesias
            break;
921 4acb54ba Edgar E. Iglesias
        case CC_LT:
922 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
923 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
924 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1);
925 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
926 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
927 4acb54ba Edgar E. Iglesias
            break;
928 4acb54ba Edgar E. Iglesias
        case CC_LE:
929 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
930 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
931 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1);
932 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
933 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
934 4acb54ba Edgar E. Iglesias
            break;
935 4acb54ba Edgar E. Iglesias
        case CC_GE:
936 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
937 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
938 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1);
939 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
940 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
941 4acb54ba Edgar E. Iglesias
            break;
942 4acb54ba Edgar E. Iglesias
        case CC_GT:
943 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
944 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
945 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1);
946 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
947 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
948 4acb54ba Edgar E. Iglesias
            break;
949 4acb54ba Edgar E. Iglesias
        default:
950 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
951 4acb54ba Edgar E. Iglesias
            break;
952 4acb54ba Edgar E. Iglesias
    }
953 4acb54ba Edgar E. Iglesias
}
954 4acb54ba Edgar E. Iglesias
955 4acb54ba Edgar E. Iglesias
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
956 4acb54ba Edgar E. Iglesias
{
957 4acb54ba Edgar E. Iglesias
    int l1;
958 4acb54ba Edgar E. Iglesias
959 4acb54ba Edgar E. Iglesias
    l1 = gen_new_label();
960 4acb54ba Edgar E. Iglesias
    /* Conditional jmp.  */
961 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
962 4acb54ba Edgar E. Iglesias
    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
963 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
964 4acb54ba Edgar E. Iglesias
    gen_set_label(l1);
965 4acb54ba Edgar E. Iglesias
}
966 4acb54ba Edgar E. Iglesias
967 4acb54ba Edgar E. Iglesias
static void dec_bcc(DisasContext *dc)
968 4acb54ba Edgar E. Iglesias
{
969 4acb54ba Edgar E. Iglesias
    unsigned int cc;
970 4acb54ba Edgar E. Iglesias
    unsigned int dslot;
971 4acb54ba Edgar E. Iglesias
972 4acb54ba Edgar E. Iglesias
    cc = EXTRACT_FIELD(dc->ir, 21, 23);
973 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 25);
974 4acb54ba Edgar E. Iglesias
    LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
975 4acb54ba Edgar E. Iglesias
976 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
977 4acb54ba Edgar E. Iglesias
    if (dslot) {
978 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
979 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
980 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
981 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
982 4acb54ba Edgar E. Iglesias
    }
983 4acb54ba Edgar E. Iglesias
984 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btarget, dc->pc);
985 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
986 4acb54ba Edgar E. Iglesias
    eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
987 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
988 4acb54ba Edgar E. Iglesias
}
989 4acb54ba Edgar E. Iglesias
990 4acb54ba Edgar E. Iglesias
static void dec_br(DisasContext *dc)
991 4acb54ba Edgar E. Iglesias
{
992 4acb54ba Edgar E. Iglesias
    unsigned int dslot, link, abs;
993 4acb54ba Edgar E. Iglesias
994 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 20);
995 4acb54ba Edgar E. Iglesias
    abs = dc->ir & (1 << 19);
996 4acb54ba Edgar E. Iglesias
    link = dc->ir & (1 << 18);
997 4acb54ba Edgar E. Iglesias
    LOG_DIS("br%s%s%s%s imm=%x\n",
998 4acb54ba Edgar E. Iglesias
             abs ? "a" : "", link ? "l" : "",
999 4acb54ba Edgar E. Iglesias
             dc->type_b ? "i" : "", dslot ? "d" : "",
1000 4acb54ba Edgar E. Iglesias
             dc->imm);
1001 4acb54ba Edgar E. Iglesias
1002 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
1003 4acb54ba Edgar E. Iglesias
    if (dslot) {
1004 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
1005 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
1006 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1007 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
1008 4acb54ba Edgar E. Iglesias
    }
1009 4acb54ba Edgar E. Iglesias
    if (link && dc->rd)
1010 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
1011 4acb54ba Edgar E. Iglesias
1012 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
1013 4acb54ba Edgar E. Iglesias
    if (abs) {
1014 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_btaken, 1);
1015 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
1016 4acb54ba Edgar E. Iglesias
        if (link && !(dc->tb_flags & IMM_FLAG)
1017 4acb54ba Edgar E. Iglesias
            && (dc->imm == 8 || dc->imm == 0x18))
1018 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_BREAK);
1019 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0)
1020 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_DEBUG);
1021 4acb54ba Edgar E. Iglesias
    } else {
1022 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & IMM_FLAG) {
1023 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
1024 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->pc);
1025 4acb54ba Edgar E. Iglesias
            tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1026 4acb54ba Edgar E. Iglesias
        } else {
1027 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_DIRECT;
1028 4acb54ba Edgar E. Iglesias
            dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
1029 4acb54ba Edgar E. Iglesias
        }
1030 4acb54ba Edgar E. Iglesias
    }
1031 4acb54ba Edgar E. Iglesias
}
1032 4acb54ba Edgar E. Iglesias
1033 4acb54ba Edgar E. Iglesias
static inline void do_rti(DisasContext *dc)
1034 4acb54ba Edgar E. Iglesias
{
1035 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1036 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1037 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1038 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
1039 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
1040 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1041 4acb54ba Edgar E. Iglesias
1042 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1043 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1044 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1045 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1046 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1047 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTI_FLAG;
1048 4acb54ba Edgar E. Iglesias
}
1049 4acb54ba Edgar E. Iglesias
1050 4acb54ba Edgar E. Iglesias
static inline void do_rtb(DisasContext *dc)
1051 4acb54ba Edgar E. Iglesias
{
1052 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1053 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1054 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1055 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
1056 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1057 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1058 4acb54ba Edgar E. Iglesias
1059 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1060 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1061 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1062 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1063 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1064 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTB_FLAG;
1065 4acb54ba Edgar E. Iglesias
}
1066 4acb54ba Edgar E. Iglesias
1067 4acb54ba Edgar E. Iglesias
static inline void do_rte(DisasContext *dc)
1068 4acb54ba Edgar E. Iglesias
{
1069 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1070 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1071 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1072 4acb54ba Edgar E. Iglesias
1073 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
1074 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
1075 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1076 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1077 4acb54ba Edgar E. Iglesias
1078 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1079 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1080 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1081 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1082 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1083 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTE_FLAG;
1084 4acb54ba Edgar E. Iglesias
}
1085 4acb54ba Edgar E. Iglesias
1086 4acb54ba Edgar E. Iglesias
static void dec_rts(DisasContext *dc)
1087 4acb54ba Edgar E. Iglesias
{
1088 4acb54ba Edgar E. Iglesias
    unsigned int b_bit, i_bit, e_bit;
1089 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1090 4acb54ba Edgar E. Iglesias
1091 4acb54ba Edgar E. Iglesias
    i_bit = dc->ir & (1 << 21);
1092 4acb54ba Edgar E. Iglesias
    b_bit = dc->ir & (1 << 22);
1093 4acb54ba Edgar E. Iglesias
    e_bit = dc->ir & (1 << 23);
1094 4acb54ba Edgar E. Iglesias
1095 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 2;
1096 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= D_FLAG;
1097 4acb54ba Edgar E. Iglesias
    tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1098 4acb54ba Edgar E. Iglesias
                  cpu_env, offsetof(CPUState, bimm));
1099 4acb54ba Edgar E. Iglesias
1100 4acb54ba Edgar E. Iglesias
    if (i_bit) {
1101 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtid ir=%x\n", dc->ir);
1102 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1103 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1104 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1105 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1106 1567a005 Edgar E. Iglesias
        }
1107 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTI_FLAG;
1108 4acb54ba Edgar E. Iglesias
    } else if (b_bit) {
1109 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtbd ir=%x\n", dc->ir);
1110 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1111 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1112 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1113 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1114 1567a005 Edgar E. Iglesias
        }
1115 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTB_FLAG;
1116 4acb54ba Edgar E. Iglesias
    } else if (e_bit) {
1117 4acb54ba Edgar E. Iglesias
        LOG_DIS("rted ir=%x\n", dc->ir);
1118 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1119 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1120 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1121 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1122 1567a005 Edgar E. Iglesias
        }
1123 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTE_FLAG;
1124 4acb54ba Edgar E. Iglesias
    } else
1125 4acb54ba Edgar E. Iglesias
        LOG_DIS("rts ir=%x\n", dc->ir);
1126 4acb54ba Edgar E. Iglesias
1127 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btaken, 1);
1128 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1129 4acb54ba Edgar E. Iglesias
}
1130 4acb54ba Edgar E. Iglesias
1131 1567a005 Edgar E. Iglesias
static void dec_fpu(DisasContext *dc)
1132 1567a005 Edgar E. Iglesias
{
1133 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1134 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1135 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1136 97f90cbf Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
1137 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1138 1567a005 Edgar E. Iglesias
        return;
1139 1567a005 Edgar E. Iglesias
    }
1140 1567a005 Edgar E. Iglesias
1141 1567a005 Edgar E. Iglesias
    qemu_log ("unimplemented FPU insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1142 1567a005 Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1143 1567a005 Edgar E. Iglesias
}
1144 1567a005 Edgar E. Iglesias
1145 4acb54ba Edgar E. Iglesias
static void dec_null(DisasContext *dc)
1146 4acb54ba Edgar E. Iglesias
{
1147 02b33596 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1148 02b33596 Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1149 02b33596 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1150 02b33596 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1151 02b33596 Edgar E. Iglesias
        return;
1152 02b33596 Edgar E. Iglesias
    }
1153 4acb54ba Edgar E. Iglesias
    qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1154 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1155 4acb54ba Edgar E. Iglesias
}
1156 4acb54ba Edgar E. Iglesias
1157 4acb54ba Edgar E. Iglesias
static struct decoder_info {
1158 4acb54ba Edgar E. Iglesias
    struct {
1159 4acb54ba Edgar E. Iglesias
        uint32_t bits;
1160 4acb54ba Edgar E. Iglesias
        uint32_t mask;
1161 4acb54ba Edgar E. Iglesias
    };
1162 4acb54ba Edgar E. Iglesias
    void (*dec)(DisasContext *dc);
1163 4acb54ba Edgar E. Iglesias
} decinfo[] = {
1164 4acb54ba Edgar E. Iglesias
    {DEC_ADD, dec_add},
1165 4acb54ba Edgar E. Iglesias
    {DEC_SUB, dec_sub},
1166 4acb54ba Edgar E. Iglesias
    {DEC_AND, dec_and},
1167 4acb54ba Edgar E. Iglesias
    {DEC_XOR, dec_xor},
1168 4acb54ba Edgar E. Iglesias
    {DEC_OR, dec_or},
1169 4acb54ba Edgar E. Iglesias
    {DEC_BIT, dec_bit},
1170 4acb54ba Edgar E. Iglesias
    {DEC_BARREL, dec_barrel},
1171 4acb54ba Edgar E. Iglesias
    {DEC_LD, dec_load},
1172 4acb54ba Edgar E. Iglesias
    {DEC_ST, dec_store},
1173 4acb54ba Edgar E. Iglesias
    {DEC_IMM, dec_imm},
1174 4acb54ba Edgar E. Iglesias
    {DEC_BR, dec_br},
1175 4acb54ba Edgar E. Iglesias
    {DEC_BCC, dec_bcc},
1176 4acb54ba Edgar E. Iglesias
    {DEC_RTS, dec_rts},
1177 1567a005 Edgar E. Iglesias
    {DEC_FPU, dec_fpu},
1178 4acb54ba Edgar E. Iglesias
    {DEC_MUL, dec_mul},
1179 4acb54ba Edgar E. Iglesias
    {DEC_DIV, dec_div},
1180 4acb54ba Edgar E. Iglesias
    {DEC_MSR, dec_msr},
1181 4acb54ba Edgar E. Iglesias
    {{0, 0}, dec_null}
1182 4acb54ba Edgar E. Iglesias
};
1183 4acb54ba Edgar E. Iglesias
1184 4acb54ba Edgar E. Iglesias
static inline void decode(DisasContext *dc)
1185 4acb54ba Edgar E. Iglesias
{
1186 4acb54ba Edgar E. Iglesias
    uint32_t ir;
1187 4acb54ba Edgar E. Iglesias
    int i;
1188 4acb54ba Edgar E. Iglesias
1189 4acb54ba Edgar E. Iglesias
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
1190 4acb54ba Edgar E. Iglesias
        tcg_gen_debug_insn_start(dc->pc);
1191 4acb54ba Edgar E. Iglesias
1192 4acb54ba Edgar E. Iglesias
    dc->ir = ir = ldl_code(dc->pc);
1193 4acb54ba Edgar E. Iglesias
    LOG_DIS("%8.8x\t", dc->ir);
1194 4acb54ba Edgar E. Iglesias
1195 4acb54ba Edgar E. Iglesias
    if (dc->ir)
1196 4acb54ba Edgar E. Iglesias
        dc->nr_nops = 0;
1197 4acb54ba Edgar E. Iglesias
    else {
1198 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1199 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1200 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
1201 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1202 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1203 1567a005 Edgar E. Iglesias
            return;
1204 1567a005 Edgar E. Iglesias
        }
1205 1567a005 Edgar E. Iglesias
1206 4acb54ba Edgar E. Iglesias
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1207 4acb54ba Edgar E. Iglesias
        dc->nr_nops++;
1208 4acb54ba Edgar E. Iglesias
        if (dc->nr_nops > 4)
1209 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "fetching nop sequence\n");
1210 4acb54ba Edgar E. Iglesias
    }
1211 4acb54ba Edgar E. Iglesias
    /* bit 2 seems to indicate insn type.  */
1212 4acb54ba Edgar E. Iglesias
    dc->type_b = ir & (1 << 29);
1213 4acb54ba Edgar E. Iglesias
1214 4acb54ba Edgar E. Iglesias
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1215 4acb54ba Edgar E. Iglesias
    dc->rd = EXTRACT_FIELD(ir, 21, 25);
1216 4acb54ba Edgar E. Iglesias
    dc->ra = EXTRACT_FIELD(ir, 16, 20);
1217 4acb54ba Edgar E. Iglesias
    dc->rb = EXTRACT_FIELD(ir, 11, 15);
1218 4acb54ba Edgar E. Iglesias
    dc->imm = EXTRACT_FIELD(ir, 0, 15);
1219 4acb54ba Edgar E. Iglesias
1220 4acb54ba Edgar E. Iglesias
    /* Large switch for all insns.  */
1221 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1222 4acb54ba Edgar E. Iglesias
        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1223 4acb54ba Edgar E. Iglesias
            decinfo[i].dec(dc);
1224 4acb54ba Edgar E. Iglesias
            break;
1225 4acb54ba Edgar E. Iglesias
        }
1226 4acb54ba Edgar E. Iglesias
    }
1227 4acb54ba Edgar E. Iglesias
}
1228 4acb54ba Edgar E. Iglesias
1229 4acb54ba Edgar E. Iglesias
static void check_breakpoint(CPUState *env, DisasContext *dc)
1230 4acb54ba Edgar E. Iglesias
{
1231 4acb54ba Edgar E. Iglesias
    CPUBreakpoint *bp;
1232 4acb54ba Edgar E. Iglesias
1233 72cf2d4f Blue Swirl
    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1234 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1235 4acb54ba Edgar E. Iglesias
            if (bp->pc == dc->pc) {
1236 4acb54ba Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1237 4acb54ba Edgar E. Iglesias
                dc->is_jmp = DISAS_UPDATE;
1238 4acb54ba Edgar E. Iglesias
             }
1239 4acb54ba Edgar E. Iglesias
        }
1240 4acb54ba Edgar E. Iglesias
    }
1241 4acb54ba Edgar E. Iglesias
}
1242 4acb54ba Edgar E. Iglesias
1243 4acb54ba Edgar E. Iglesias
/* generate intermediate code for basic block 'tb'.  */
1244 4acb54ba Edgar E. Iglesias
static void
1245 4acb54ba Edgar E. Iglesias
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
1246 4acb54ba Edgar E. Iglesias
                               int search_pc)
1247 4acb54ba Edgar E. Iglesias
{
1248 4acb54ba Edgar E. Iglesias
    uint16_t *gen_opc_end;
1249 4acb54ba Edgar E. Iglesias
    uint32_t pc_start;
1250 4acb54ba Edgar E. Iglesias
    int j, lj;
1251 4acb54ba Edgar E. Iglesias
    struct DisasContext ctx;
1252 4acb54ba Edgar E. Iglesias
    struct DisasContext *dc = &ctx;
1253 4acb54ba Edgar E. Iglesias
    uint32_t next_page_start, org_flags;
1254 4acb54ba Edgar E. Iglesias
    target_ulong npc;
1255 4acb54ba Edgar E. Iglesias
    int num_insns;
1256 4acb54ba Edgar E. Iglesias
    int max_insns;
1257 4acb54ba Edgar E. Iglesias
1258 4acb54ba Edgar E. Iglesias
    qemu_log_try_set_file(stderr);
1259 4acb54ba Edgar E. Iglesias
1260 4acb54ba Edgar E. Iglesias
    pc_start = tb->pc;
1261 4acb54ba Edgar E. Iglesias
    dc->env = env;
1262 4acb54ba Edgar E. Iglesias
    dc->tb = tb;
1263 4acb54ba Edgar E. Iglesias
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1264 4acb54ba Edgar E. Iglesias
1265 4acb54ba Edgar E. Iglesias
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1266 4acb54ba Edgar E. Iglesias
1267 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_NEXT;
1268 4acb54ba Edgar E. Iglesias
    dc->jmp = 0;
1269 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1270 4acb54ba Edgar E. Iglesias
    dc->ppc = pc_start;
1271 4acb54ba Edgar E. Iglesias
    dc->pc = pc_start;
1272 4acb54ba Edgar E. Iglesias
    dc->cache_pc = -1;
1273 4acb54ba Edgar E. Iglesias
    dc->singlestep_enabled = env->singlestep_enabled;
1274 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 0;
1275 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 0;
1276 4acb54ba Edgar E. Iglesias
    dc->nr_nops = 0;
1277 4acb54ba Edgar E. Iglesias
1278 4acb54ba Edgar E. Iglesias
    if (pc_start & 3)
1279 4acb54ba Edgar E. Iglesias
        cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
1280 4acb54ba Edgar E. Iglesias
1281 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1282 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1283 4acb54ba Edgar E. Iglesias
        qemu_log("--------------\n");
1284 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1285 4acb54ba Edgar E. Iglesias
#endif
1286 4acb54ba Edgar E. Iglesias
    }
1287 4acb54ba Edgar E. Iglesias
1288 4acb54ba Edgar E. Iglesias
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1289 4acb54ba Edgar E. Iglesias
    lj = -1;
1290 4acb54ba Edgar E. Iglesias
    num_insns = 0;
1291 4acb54ba Edgar E. Iglesias
    max_insns = tb->cflags & CF_COUNT_MASK;
1292 4acb54ba Edgar E. Iglesias
    if (max_insns == 0)
1293 4acb54ba Edgar E. Iglesias
        max_insns = CF_COUNT_MASK;
1294 4acb54ba Edgar E. Iglesias
1295 4acb54ba Edgar E. Iglesias
    gen_icount_start();
1296 4acb54ba Edgar E. Iglesias
    do
1297 4acb54ba Edgar E. Iglesias
    {
1298 4acb54ba Edgar E. Iglesias
#if SIM_COMPAT
1299 4acb54ba Edgar E. Iglesias
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1300 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1301 4acb54ba Edgar E. Iglesias
            gen_helper_debug();
1302 4acb54ba Edgar E. Iglesias
        }
1303 4acb54ba Edgar E. Iglesias
#endif
1304 4acb54ba Edgar E. Iglesias
        check_breakpoint(env, dc);
1305 4acb54ba Edgar E. Iglesias
1306 4acb54ba Edgar E. Iglesias
        if (search_pc) {
1307 4acb54ba Edgar E. Iglesias
            j = gen_opc_ptr - gen_opc_buf;
1308 4acb54ba Edgar E. Iglesias
            if (lj < j) {
1309 4acb54ba Edgar E. Iglesias
                lj++;
1310 4acb54ba Edgar E. Iglesias
                while (lj < j)
1311 4acb54ba Edgar E. Iglesias
                    gen_opc_instr_start[lj++] = 0;
1312 4acb54ba Edgar E. Iglesias
            }
1313 4acb54ba Edgar E. Iglesias
            gen_opc_pc[lj] = dc->pc;
1314 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj] = 1;
1315 4acb54ba Edgar E. Iglesias
                        gen_opc_icount[lj] = num_insns;
1316 4acb54ba Edgar E. Iglesias
        }
1317 4acb54ba Edgar E. Iglesias
1318 4acb54ba Edgar E. Iglesias
        /* Pretty disas.  */
1319 4acb54ba Edgar E. Iglesias
        LOG_DIS("%8.8x:\t", dc->pc);
1320 4acb54ba Edgar E. Iglesias
1321 4acb54ba Edgar E. Iglesias
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1322 4acb54ba Edgar E. Iglesias
            gen_io_start();
1323 4acb54ba Edgar E. Iglesias
1324 4acb54ba Edgar E. Iglesias
        dc->clear_imm = 1;
1325 4acb54ba Edgar E. Iglesias
        decode(dc);
1326 4acb54ba Edgar E. Iglesias
        if (dc->clear_imm)
1327 4acb54ba Edgar E. Iglesias
            dc->tb_flags &= ~IMM_FLAG;
1328 4acb54ba Edgar E. Iglesias
        dc->ppc = dc->pc;
1329 4acb54ba Edgar E. Iglesias
        dc->pc += 4;
1330 4acb54ba Edgar E. Iglesias
        num_insns++;
1331 4acb54ba Edgar E. Iglesias
1332 4acb54ba Edgar E. Iglesias
        if (dc->delayed_branch) {
1333 4acb54ba Edgar E. Iglesias
            dc->delayed_branch--;
1334 4acb54ba Edgar E. Iglesias
            if (!dc->delayed_branch) {
1335 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTI_FLAG)
1336 4acb54ba Edgar E. Iglesias
                    do_rti(dc);
1337 4acb54ba Edgar E. Iglesias
                 if (dc->tb_flags & DRTB_FLAG)
1338 4acb54ba Edgar E. Iglesias
                    do_rtb(dc);
1339 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTE_FLAG)
1340 4acb54ba Edgar E. Iglesias
                    do_rte(dc);
1341 4acb54ba Edgar E. Iglesias
                /* Clear the delay slot flag.  */
1342 4acb54ba Edgar E. Iglesias
                dc->tb_flags &= ~D_FLAG;
1343 4acb54ba Edgar E. Iglesias
                /* If it is a direct jump, try direct chaining.  */
1344 4acb54ba Edgar E. Iglesias
                if (dc->jmp != JMP_DIRECT) {
1345 4acb54ba Edgar E. Iglesias
                    eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1346 4acb54ba Edgar E. Iglesias
                    dc->is_jmp = DISAS_JUMP;
1347 4acb54ba Edgar E. Iglesias
                }
1348 4acb54ba Edgar E. Iglesias
                break;
1349 4acb54ba Edgar E. Iglesias
            }
1350 4acb54ba Edgar E. Iglesias
        }
1351 4acb54ba Edgar E. Iglesias
        if (env->singlestep_enabled)
1352 4acb54ba Edgar E. Iglesias
            break;
1353 4acb54ba Edgar E. Iglesias
    } while (!dc->is_jmp && !dc->cpustate_changed
1354 4acb54ba Edgar E. Iglesias
         && gen_opc_ptr < gen_opc_end
1355 4acb54ba Edgar E. Iglesias
                 && !singlestep
1356 4acb54ba Edgar E. Iglesias
         && (dc->pc < next_page_start)
1357 4acb54ba Edgar E. Iglesias
                 && num_insns < max_insns);
1358 4acb54ba Edgar E. Iglesias
1359 4acb54ba Edgar E. Iglesias
    npc = dc->pc;
1360 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
1361 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & D_FLAG) {
1362 4acb54ba Edgar E. Iglesias
            dc->is_jmp = DISAS_UPDATE;
1363 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1364 4acb54ba Edgar E. Iglesias
            sync_jmpstate(dc);
1365 4acb54ba Edgar E. Iglesias
        } else
1366 4acb54ba Edgar E. Iglesias
            npc = dc->jmp_pc;
1367 4acb54ba Edgar E. Iglesias
    }
1368 4acb54ba Edgar E. Iglesias
1369 4acb54ba Edgar E. Iglesias
    if (tb->cflags & CF_LAST_IO)
1370 4acb54ba Edgar E. Iglesias
        gen_io_end();
1371 4acb54ba Edgar E. Iglesias
    /* Force an update if the per-tb cpu state has changed.  */
1372 4acb54ba Edgar E. Iglesias
    if (dc->is_jmp == DISAS_NEXT
1373 4acb54ba Edgar E. Iglesias
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
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
    }
1377 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1378 4acb54ba Edgar E. Iglesias
1379 4acb54ba Edgar E. Iglesias
    if (unlikely(env->singlestep_enabled)) {
1380 4acb54ba Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_DEBUG);
1381 4acb54ba Edgar E. Iglesias
        if (dc->is_jmp == DISAS_NEXT)
1382 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1383 4acb54ba Edgar E. Iglesias
    } else {
1384 4acb54ba Edgar E. Iglesias
        switch(dc->is_jmp) {
1385 4acb54ba Edgar E. Iglesias
            case DISAS_NEXT:
1386 4acb54ba Edgar E. Iglesias
                gen_goto_tb(dc, 1, npc);
1387 4acb54ba Edgar E. Iglesias
                break;
1388 4acb54ba Edgar E. Iglesias
            default:
1389 4acb54ba Edgar E. Iglesias
            case DISAS_JUMP:
1390 4acb54ba Edgar E. Iglesias
            case DISAS_UPDATE:
1391 4acb54ba Edgar E. Iglesias
                /* indicate that the hash table must be used
1392 4acb54ba Edgar E. Iglesias
                   to find the next TB */
1393 4acb54ba Edgar E. Iglesias
                tcg_gen_exit_tb(0);
1394 4acb54ba Edgar E. Iglesias
                break;
1395 4acb54ba Edgar E. Iglesias
            case DISAS_TB_JUMP:
1396 4acb54ba Edgar E. Iglesias
                /* nothing more to generate */
1397 4acb54ba Edgar E. Iglesias
                break;
1398 4acb54ba Edgar E. Iglesias
        }
1399 4acb54ba Edgar E. Iglesias
    }
1400 4acb54ba Edgar E. Iglesias
    gen_icount_end(tb, num_insns);
1401 4acb54ba Edgar E. Iglesias
    *gen_opc_ptr = INDEX_op_end;
1402 4acb54ba Edgar E. Iglesias
    if (search_pc) {
1403 4acb54ba Edgar E. Iglesias
        j = gen_opc_ptr - gen_opc_buf;
1404 4acb54ba Edgar E. Iglesias
        lj++;
1405 4acb54ba Edgar E. Iglesias
        while (lj <= j)
1406 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj++] = 0;
1407 4acb54ba Edgar E. Iglesias
    } else {
1408 4acb54ba Edgar E. Iglesias
        tb->size = dc->pc - pc_start;
1409 4acb54ba Edgar E. Iglesias
                tb->icount = num_insns;
1410 4acb54ba Edgar E. Iglesias
    }
1411 4acb54ba Edgar E. Iglesias
1412 4acb54ba Edgar E. Iglesias
#ifdef DEBUG_DISAS
1413 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1414 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1415 4acb54ba Edgar E. Iglesias
        qemu_log("\n");
1416 4acb54ba Edgar E. Iglesias
#if DISAS_GNU
1417 4acb54ba Edgar E. Iglesias
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1418 4acb54ba Edgar E. Iglesias
#endif
1419 4acb54ba Edgar E. Iglesias
        qemu_log("\nisize=%d osize=%zd\n",
1420 4acb54ba Edgar E. Iglesias
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1421 4acb54ba Edgar E. Iglesias
    }
1422 4acb54ba Edgar E. Iglesias
#endif
1423 4acb54ba Edgar E. Iglesias
#endif
1424 4acb54ba Edgar E. Iglesias
    assert(!dc->abort_at_next_insn);
1425 4acb54ba Edgar E. Iglesias
}
1426 4acb54ba Edgar E. Iglesias
1427 4acb54ba Edgar E. Iglesias
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1428 4acb54ba Edgar E. Iglesias
{
1429 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 0);
1430 4acb54ba Edgar E. Iglesias
}
1431 4acb54ba Edgar E. Iglesias
1432 4acb54ba Edgar E. Iglesias
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1433 4acb54ba Edgar E. Iglesias
{
1434 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 1);
1435 4acb54ba Edgar E. Iglesias
}
1436 4acb54ba Edgar E. Iglesias
1437 4acb54ba Edgar E. Iglesias
void cpu_dump_state (CPUState *env, FILE *f,
1438 4acb54ba Edgar E. Iglesias
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1439 4acb54ba Edgar E. Iglesias
                     int flags)
1440 4acb54ba Edgar E. Iglesias
{
1441 4acb54ba Edgar E. Iglesias
    int i;
1442 4acb54ba Edgar E. Iglesias
1443 4acb54ba Edgar E. Iglesias
    if (!env || !f)
1444 4acb54ba Edgar E. Iglesias
        return;
1445 4acb54ba Edgar E. Iglesias
1446 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "IN: PC=%x %s\n",
1447 4acb54ba Edgar E. Iglesias
                env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1448 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n",
1449 4acb54ba Edgar E. Iglesias
             env->sregs[SR_MSR], env->sregs[SR_ESR],
1450 4acb54ba Edgar E. Iglesias
             env->debug, env->imm, env->iflags);
1451 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s)\n",
1452 4acb54ba Edgar E. Iglesias
             env->btaken, env->btarget,
1453 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1454 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel");
1455 4acb54ba Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
1456 4acb54ba Edgar E. Iglesias
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1457 4acb54ba Edgar E. Iglesias
        if ((i + 1) % 4 == 0)
1458 4acb54ba Edgar E. Iglesias
            cpu_fprintf(f, "\n");
1459 4acb54ba Edgar E. Iglesias
        }
1460 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "\n\n");
1461 4acb54ba Edgar E. Iglesias
}
1462 4acb54ba Edgar E. Iglesias
1463 4acb54ba Edgar E. Iglesias
CPUState *cpu_mb_init (const char *cpu_model)
1464 4acb54ba Edgar E. Iglesias
{
1465 4acb54ba Edgar E. Iglesias
    CPUState *env;
1466 4acb54ba Edgar E. Iglesias
    static int tcg_initialized = 0;
1467 4acb54ba Edgar E. Iglesias
    int i;
1468 4acb54ba Edgar E. Iglesias
1469 4acb54ba Edgar E. Iglesias
    env = qemu_mallocz(sizeof(CPUState));
1470 4acb54ba Edgar E. Iglesias
1471 4acb54ba Edgar E. Iglesias
    cpu_exec_init(env);
1472 4acb54ba Edgar E. Iglesias
    cpu_reset(env);
1473 4acb54ba Edgar E. Iglesias
1474 4acb54ba Edgar E. Iglesias
    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
1475 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_BARREL_MASK \
1476 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DIV_MASK \
1477 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_HW_MUL_MASK \
1478 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_EXC_MASK \
1479 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_ICACHE_MASK \
1480 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DCACHE_MASK \
1481 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_MMU \
1482 4acb54ba Edgar E. Iglesias
                       | (0xb << 8);
1483 3c50a71f Edgar E. Iglesias
    env->pvr.regs[2] = PVR2_D_OPB_MASK \
1484 4acb54ba Edgar E. Iglesias
                        | PVR2_D_LMB_MASK \
1485 4acb54ba Edgar E. Iglesias
                        | PVR2_I_OPB_MASK \
1486 4acb54ba Edgar E. Iglesias
                        | PVR2_I_LMB_MASK \
1487 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MSR_INSTR \
1488 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_PCMP_INSTR \
1489 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_BARREL_MASK \
1490 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_DIV_MASK \
1491 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_HW_MUL_MASK \
1492 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MUL64_MASK \
1493 4acb54ba Edgar E. Iglesias
                        | 0;
1494 3c50a71f Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
1495 3c50a71f Edgar E. Iglesias
    env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
1496 3c50a71f Edgar E. Iglesias
#if !defined(CONFIG_USER_ONLY)
1497 3c50a71f Edgar E. Iglesias
    env->mmu.c_mmu = 3;
1498 3c50a71f Edgar E. Iglesias
    env->mmu.c_mmu_tlb_access = 3;
1499 3c50a71f Edgar E. Iglesias
    env->mmu.c_mmu_zones = 16;
1500 3c50a71f Edgar E. Iglesias
#endif
1501 4acb54ba Edgar E. Iglesias
1502 4acb54ba Edgar E. Iglesias
    if (tcg_initialized)
1503 4acb54ba Edgar E. Iglesias
        return env;
1504 4acb54ba Edgar E. Iglesias
1505 4acb54ba Edgar E. Iglesias
    tcg_initialized = 1;
1506 4acb54ba Edgar E. Iglesias
1507 4acb54ba Edgar E. Iglesias
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1508 4acb54ba Edgar E. Iglesias
1509 4acb54ba Edgar E. Iglesias
    env_debug = tcg_global_mem_new(TCG_AREG0, 
1510 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, debug),
1511 4acb54ba Edgar E. Iglesias
                    "debug0");
1512 4acb54ba Edgar E. Iglesias
    env_iflags = tcg_global_mem_new(TCG_AREG0, 
1513 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, iflags),
1514 4acb54ba Edgar E. Iglesias
                    "iflags");
1515 4acb54ba Edgar E. Iglesias
    env_imm = tcg_global_mem_new(TCG_AREG0, 
1516 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, imm),
1517 4acb54ba Edgar E. Iglesias
                    "imm");
1518 4acb54ba Edgar E. Iglesias
    env_btarget = tcg_global_mem_new(TCG_AREG0,
1519 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btarget),
1520 4acb54ba Edgar E. Iglesias
                     "btarget");
1521 4acb54ba Edgar E. Iglesias
    env_btaken = tcg_global_mem_new(TCG_AREG0,
1522 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btaken),
1523 4acb54ba Edgar E. Iglesias
                     "btaken");
1524 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1525 4acb54ba Edgar E. Iglesias
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1526 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, regs[i]),
1527 4acb54ba Edgar E. Iglesias
                          regnames[i]);
1528 4acb54ba Edgar E. Iglesias
    }
1529 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1530 4acb54ba Edgar E. Iglesias
        cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
1531 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, sregs[i]),
1532 4acb54ba Edgar E. Iglesias
                          special_regnames[i]);
1533 4acb54ba Edgar E. Iglesias
    }
1534 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 2
1535 4acb54ba Edgar E. Iglesias
#include "helper.h"
1536 4acb54ba Edgar E. Iglesias
1537 4acb54ba Edgar E. Iglesias
    return env;
1538 4acb54ba Edgar E. Iglesias
}
1539 4acb54ba Edgar E. Iglesias
1540 4acb54ba Edgar E. Iglesias
void cpu_reset (CPUState *env)
1541 4acb54ba Edgar E. Iglesias
{
1542 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1543 4acb54ba Edgar E. Iglesias
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1544 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1545 4acb54ba Edgar E. Iglesias
    }
1546 4acb54ba Edgar E. Iglesias
1547 4acb54ba Edgar E. Iglesias
    memset(env, 0, offsetof(CPUMBState, breakpoints));
1548 4acb54ba Edgar E. Iglesias
    tlb_flush(env, 1);
1549 4acb54ba Edgar E. Iglesias
1550 4acb54ba Edgar E. Iglesias
    env->sregs[SR_MSR] = 0;
1551 4acb54ba Edgar E. Iglesias
#if defined(CONFIG_USER_ONLY)
1552 4acb54ba Edgar E. Iglesias
    /* start in user mode with interrupts enabled.  */
1553 4acb54ba Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
1554 4acb54ba Edgar E. Iglesias
#else
1555 4acb54ba Edgar E. Iglesias
    mmu_init(&env->mmu);
1556 4acb54ba Edgar E. Iglesias
#endif
1557 4acb54ba Edgar E. Iglesias
}
1558 4acb54ba Edgar E. Iglesias
1559 4acb54ba Edgar E. Iglesias
void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
1560 4acb54ba Edgar E. Iglesias
                 unsigned long searched_pc, int pc_pos, void *puc)
1561 4acb54ba Edgar E. Iglesias
{
1562 4acb54ba Edgar E. Iglesias
    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
1563 4acb54ba Edgar E. Iglesias
}