Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ 968a40f6

History | View | Annotate | Download (42.5 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 1567a005 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 1567a005 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 1567a005 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 1567a005 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 4acb54ba Edgar E. Iglesias
807 4acb54ba Edgar E. Iglesias
    LOG_DIS("l %x %d\n", dc->opcode, size);
808 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
809 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
810 4acb54ba Edgar E. Iglesias
811 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
812 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
813 968a40f6 Edgar E. Iglesias
814 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
815 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
816 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
817 968a40f6 Edgar E. Iglesias
                            tcg_const_tl(0), tcg_const_tl(size));
818 968a40f6 Edgar E. Iglesias
    }
819 968a40f6 Edgar E. Iglesias
820 968a40f6 Edgar E. Iglesias
    if (dc->rd) {
821 4acb54ba Edgar E. Iglesias
        gen_load(dc, cpu_R[dc->rd], *addr, size);
822 968a40f6 Edgar E. Iglesias
    } else {
823 4acb54ba Edgar E. Iglesias
        gen_load(dc, env_imm, *addr, size);
824 4acb54ba Edgar E. Iglesias
    }
825 4acb54ba Edgar E. Iglesias
826 4acb54ba Edgar E. Iglesias
    if (addr == &t)
827 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
828 4acb54ba Edgar E. Iglesias
}
829 4acb54ba Edgar E. Iglesias
830 4acb54ba Edgar E. Iglesias
static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
831 4acb54ba Edgar E. Iglesias
                      unsigned int size)
832 4acb54ba Edgar E. Iglesias
{
833 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
834 4acb54ba Edgar E. Iglesias
835 4acb54ba Edgar E. Iglesias
    if (size == 1)
836 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st8(val, addr, mem_index);
837 4acb54ba Edgar E. Iglesias
    else if (size == 2) {
838 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st16(val, addr, mem_index);
839 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
840 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st32(val, addr, mem_index);
841 4acb54ba Edgar E. Iglesias
    } else
842 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect store size %d\n", size);
843 4acb54ba Edgar E. Iglesias
}
844 4acb54ba Edgar E. Iglesias
845 4acb54ba Edgar E. Iglesias
static void dec_store(DisasContext *dc)
846 4acb54ba Edgar E. Iglesias
{
847 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
848 4acb54ba Edgar E. Iglesias
    unsigned int size;
849 4acb54ba Edgar E. Iglesias
850 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
851 4acb54ba Edgar E. Iglesias
852 4acb54ba Edgar E. Iglesias
    LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
853 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
854 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
855 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
856 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
857 968a40f6 Edgar E. Iglesias
858 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
859 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
860 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
861 968a40f6 Edgar E. Iglesias
                            tcg_const_tl(1), tcg_const_tl(size));
862 968a40f6 Edgar E. Iglesias
    }
863 968a40f6 Edgar E. Iglesias
864 4acb54ba Edgar E. Iglesias
    gen_store(dc, *addr, cpu_R[dc->rd], size);
865 4acb54ba Edgar E. Iglesias
    if (addr == &t)
866 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
867 4acb54ba Edgar E. Iglesias
}
868 4acb54ba Edgar E. Iglesias
869 4acb54ba Edgar E. Iglesias
static inline void eval_cc(DisasContext *dc, unsigned int cc,
870 4acb54ba Edgar E. Iglesias
                           TCGv d, TCGv a, TCGv b)
871 4acb54ba Edgar E. Iglesias
{
872 4acb54ba Edgar E. Iglesias
    int l1;
873 4acb54ba Edgar E. Iglesias
874 4acb54ba Edgar E. Iglesias
    switch (cc) {
875 4acb54ba Edgar E. Iglesias
        case CC_EQ:
876 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
877 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
878 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_EQ, a, b, l1);
879 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
880 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
881 4acb54ba Edgar E. Iglesias
            break;
882 4acb54ba Edgar E. Iglesias
        case CC_NE:
883 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
884 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
885 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_NE, a, b, l1);
886 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
887 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
888 4acb54ba Edgar E. Iglesias
            break;
889 4acb54ba Edgar E. Iglesias
        case CC_LT:
890 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
891 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
892 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LT, a, b, l1);
893 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
894 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
895 4acb54ba Edgar E. Iglesias
            break;
896 4acb54ba Edgar E. Iglesias
        case CC_LE:
897 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
898 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
899 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_LE, a, b, l1);
900 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
901 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
902 4acb54ba Edgar E. Iglesias
            break;
903 4acb54ba Edgar E. Iglesias
        case CC_GE:
904 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
905 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
906 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GE, a, b, l1);
907 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
908 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
909 4acb54ba Edgar E. Iglesias
            break;
910 4acb54ba Edgar E. Iglesias
        case CC_GT:
911 4acb54ba Edgar E. Iglesias
            l1 = gen_new_label();
912 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
913 4acb54ba Edgar E. Iglesias
            tcg_gen_brcond_tl(TCG_COND_GT, a, b, l1);
914 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 0);
915 4acb54ba Edgar E. Iglesias
            gen_set_label(l1);
916 4acb54ba Edgar E. Iglesias
            break;
917 4acb54ba Edgar E. Iglesias
        default:
918 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
919 4acb54ba Edgar E. Iglesias
            break;
920 4acb54ba Edgar E. Iglesias
    }
921 4acb54ba Edgar E. Iglesias
}
922 4acb54ba Edgar E. Iglesias
923 4acb54ba Edgar E. Iglesias
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
924 4acb54ba Edgar E. Iglesias
{
925 4acb54ba Edgar E. Iglesias
    int l1;
926 4acb54ba Edgar E. Iglesias
927 4acb54ba Edgar E. Iglesias
    l1 = gen_new_label();
928 4acb54ba Edgar E. Iglesias
    /* Conditional jmp.  */
929 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
930 4acb54ba Edgar E. Iglesias
    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
931 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
932 4acb54ba Edgar E. Iglesias
    gen_set_label(l1);
933 4acb54ba Edgar E. Iglesias
}
934 4acb54ba Edgar E. Iglesias
935 4acb54ba Edgar E. Iglesias
static void dec_bcc(DisasContext *dc)
936 4acb54ba Edgar E. Iglesias
{
937 4acb54ba Edgar E. Iglesias
    unsigned int cc;
938 4acb54ba Edgar E. Iglesias
    unsigned int dslot;
939 4acb54ba Edgar E. Iglesias
940 4acb54ba Edgar E. Iglesias
    cc = EXTRACT_FIELD(dc->ir, 21, 23);
941 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 25);
942 4acb54ba Edgar E. Iglesias
    LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
943 4acb54ba Edgar E. Iglesias
944 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
945 4acb54ba Edgar E. Iglesias
    if (dslot) {
946 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
947 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
948 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
949 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
950 4acb54ba Edgar E. Iglesias
    }
951 4acb54ba Edgar E. Iglesias
952 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btarget, dc->pc);
953 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
954 4acb54ba Edgar E. Iglesias
    eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
955 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
956 4acb54ba Edgar E. Iglesias
}
957 4acb54ba Edgar E. Iglesias
958 4acb54ba Edgar E. Iglesias
static void dec_br(DisasContext *dc)
959 4acb54ba Edgar E. Iglesias
{
960 4acb54ba Edgar E. Iglesias
    unsigned int dslot, link, abs;
961 4acb54ba Edgar E. Iglesias
962 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 20);
963 4acb54ba Edgar E. Iglesias
    abs = dc->ir & (1 << 19);
964 4acb54ba Edgar E. Iglesias
    link = dc->ir & (1 << 18);
965 4acb54ba Edgar E. Iglesias
    LOG_DIS("br%s%s%s%s imm=%x\n",
966 4acb54ba Edgar E. Iglesias
             abs ? "a" : "", link ? "l" : "",
967 4acb54ba Edgar E. Iglesias
             dc->type_b ? "i" : "", dslot ? "d" : "",
968 4acb54ba Edgar E. Iglesias
             dc->imm);
969 4acb54ba Edgar E. Iglesias
970 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
971 4acb54ba Edgar E. Iglesias
    if (dslot) {
972 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
973 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
974 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
975 4acb54ba Edgar E. Iglesias
                      cpu_env, offsetof(CPUState, bimm));
976 4acb54ba Edgar E. Iglesias
    }
977 4acb54ba Edgar E. Iglesias
    if (link && dc->rd)
978 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
979 4acb54ba Edgar E. Iglesias
980 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
981 4acb54ba Edgar E. Iglesias
    if (abs) {
982 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_btaken, 1);
983 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
984 4acb54ba Edgar E. Iglesias
        if (link && !(dc->tb_flags & IMM_FLAG)
985 4acb54ba Edgar E. Iglesias
            && (dc->imm == 8 || dc->imm == 0x18))
986 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_BREAK);
987 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0)
988 4acb54ba Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_DEBUG);
989 4acb54ba Edgar E. Iglesias
    } else {
990 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & IMM_FLAG) {
991 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
992 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->pc);
993 4acb54ba Edgar E. Iglesias
            tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
994 4acb54ba Edgar E. Iglesias
        } else {
995 4acb54ba Edgar E. Iglesias
            dc->jmp = JMP_DIRECT;
996 4acb54ba Edgar E. Iglesias
            dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
997 4acb54ba Edgar E. Iglesias
        }
998 4acb54ba Edgar E. Iglesias
    }
999 4acb54ba Edgar E. Iglesias
}
1000 4acb54ba Edgar E. Iglesias
1001 4acb54ba Edgar E. Iglesias
static inline void do_rti(DisasContext *dc)
1002 4acb54ba Edgar E. Iglesias
{
1003 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1004 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1005 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1006 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
1007 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
1008 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1009 4acb54ba Edgar E. Iglesias
1010 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1011 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1012 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1013 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1014 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1015 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTI_FLAG;
1016 4acb54ba Edgar E. Iglesias
}
1017 4acb54ba Edgar E. Iglesias
1018 4acb54ba Edgar E. Iglesias
static inline void do_rtb(DisasContext *dc)
1019 4acb54ba Edgar E. Iglesias
{
1020 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1021 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1022 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1023 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
1024 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1025 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1026 4acb54ba Edgar E. Iglesias
1027 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1028 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1029 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1030 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1031 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1032 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTB_FLAG;
1033 4acb54ba Edgar E. Iglesias
}
1034 4acb54ba Edgar E. Iglesias
1035 4acb54ba Edgar E. Iglesias
static inline void do_rte(DisasContext *dc)
1036 4acb54ba Edgar E. Iglesias
{
1037 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1038 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1039 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1040 4acb54ba Edgar E. Iglesias
1041 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
1042 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
1043 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1044 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1045 4acb54ba Edgar E. Iglesias
1046 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1047 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1048 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1049 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1050 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1051 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTE_FLAG;
1052 4acb54ba Edgar E. Iglesias
}
1053 4acb54ba Edgar E. Iglesias
1054 4acb54ba Edgar E. Iglesias
static void dec_rts(DisasContext *dc)
1055 4acb54ba Edgar E. Iglesias
{
1056 4acb54ba Edgar E. Iglesias
    unsigned int b_bit, i_bit, e_bit;
1057 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1058 4acb54ba Edgar E. Iglesias
1059 4acb54ba Edgar E. Iglesias
    i_bit = dc->ir & (1 << 21);
1060 4acb54ba Edgar E. Iglesias
    b_bit = dc->ir & (1 << 22);
1061 4acb54ba Edgar E. Iglesias
    e_bit = dc->ir & (1 << 23);
1062 4acb54ba Edgar E. Iglesias
1063 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 2;
1064 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= D_FLAG;
1065 4acb54ba Edgar E. Iglesias
    tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1066 4acb54ba Edgar E. Iglesias
                  cpu_env, offsetof(CPUState, bimm));
1067 4acb54ba Edgar E. Iglesias
1068 4acb54ba Edgar E. Iglesias
    if (i_bit) {
1069 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtid ir=%x\n", dc->ir);
1070 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1071 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1072 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1073 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1074 1567a005 Edgar E. Iglesias
        }
1075 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTI_FLAG;
1076 4acb54ba Edgar E. Iglesias
    } else if (b_bit) {
1077 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtbd ir=%x\n", dc->ir);
1078 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1079 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1080 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1081 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1082 1567a005 Edgar E. Iglesias
        }
1083 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTB_FLAG;
1084 4acb54ba Edgar E. Iglesias
    } else if (e_bit) {
1085 4acb54ba Edgar E. Iglesias
        LOG_DIS("rted ir=%x\n", dc->ir);
1086 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1087 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1088 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1089 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1090 1567a005 Edgar E. Iglesias
        }
1091 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTE_FLAG;
1092 4acb54ba Edgar E. Iglesias
    } else
1093 4acb54ba Edgar E. Iglesias
        LOG_DIS("rts ir=%x\n", dc->ir);
1094 4acb54ba Edgar E. Iglesias
1095 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btaken, 1);
1096 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1097 4acb54ba Edgar E. Iglesias
}
1098 4acb54ba Edgar E. Iglesias
1099 1567a005 Edgar E. Iglesias
static void dec_fpu(DisasContext *dc)
1100 1567a005 Edgar E. Iglesias
{
1101 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1102 1567a005 Edgar E. Iglesias
          && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1103 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1104 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1105 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1106 1567a005 Edgar E. Iglesias
        return;
1107 1567a005 Edgar E. Iglesias
    }
1108 1567a005 Edgar E. Iglesias
1109 1567a005 Edgar E. Iglesias
    qemu_log ("unimplemented FPU insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1110 1567a005 Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1111 1567a005 Edgar E. Iglesias
}
1112 1567a005 Edgar E. Iglesias
1113 4acb54ba Edgar E. Iglesias
static void dec_null(DisasContext *dc)
1114 4acb54ba Edgar E. Iglesias
{
1115 4acb54ba Edgar E. Iglesias
    qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1116 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1117 4acb54ba Edgar E. Iglesias
}
1118 4acb54ba Edgar E. Iglesias
1119 4acb54ba Edgar E. Iglesias
static struct decoder_info {
1120 4acb54ba Edgar E. Iglesias
    struct {
1121 4acb54ba Edgar E. Iglesias
        uint32_t bits;
1122 4acb54ba Edgar E. Iglesias
        uint32_t mask;
1123 4acb54ba Edgar E. Iglesias
    };
1124 4acb54ba Edgar E. Iglesias
    void (*dec)(DisasContext *dc);
1125 4acb54ba Edgar E. Iglesias
} decinfo[] = {
1126 4acb54ba Edgar E. Iglesias
    {DEC_ADD, dec_add},
1127 4acb54ba Edgar E. Iglesias
    {DEC_SUB, dec_sub},
1128 4acb54ba Edgar E. Iglesias
    {DEC_AND, dec_and},
1129 4acb54ba Edgar E. Iglesias
    {DEC_XOR, dec_xor},
1130 4acb54ba Edgar E. Iglesias
    {DEC_OR, dec_or},
1131 4acb54ba Edgar E. Iglesias
    {DEC_BIT, dec_bit},
1132 4acb54ba Edgar E. Iglesias
    {DEC_BARREL, dec_barrel},
1133 4acb54ba Edgar E. Iglesias
    {DEC_LD, dec_load},
1134 4acb54ba Edgar E. Iglesias
    {DEC_ST, dec_store},
1135 4acb54ba Edgar E. Iglesias
    {DEC_IMM, dec_imm},
1136 4acb54ba Edgar E. Iglesias
    {DEC_BR, dec_br},
1137 4acb54ba Edgar E. Iglesias
    {DEC_BCC, dec_bcc},
1138 4acb54ba Edgar E. Iglesias
    {DEC_RTS, dec_rts},
1139 1567a005 Edgar E. Iglesias
    {DEC_FPU, dec_fpu},
1140 4acb54ba Edgar E. Iglesias
    {DEC_MUL, dec_mul},
1141 4acb54ba Edgar E. Iglesias
    {DEC_DIV, dec_div},
1142 4acb54ba Edgar E. Iglesias
    {DEC_MSR, dec_msr},
1143 4acb54ba Edgar E. Iglesias
    {{0, 0}, dec_null}
1144 4acb54ba Edgar E. Iglesias
};
1145 4acb54ba Edgar E. Iglesias
1146 4acb54ba Edgar E. Iglesias
static inline void decode(DisasContext *dc)
1147 4acb54ba Edgar E. Iglesias
{
1148 4acb54ba Edgar E. Iglesias
    uint32_t ir;
1149 4acb54ba Edgar E. Iglesias
    int i;
1150 4acb54ba Edgar E. Iglesias
1151 4acb54ba Edgar E. Iglesias
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
1152 4acb54ba Edgar E. Iglesias
        tcg_gen_debug_insn_start(dc->pc);
1153 4acb54ba Edgar E. Iglesias
1154 4acb54ba Edgar E. Iglesias
    dc->ir = ir = ldl_code(dc->pc);
1155 4acb54ba Edgar E. Iglesias
    LOG_DIS("%8.8x\t", dc->ir);
1156 4acb54ba Edgar E. Iglesias
1157 4acb54ba Edgar E. Iglesias
    if (dc->ir)
1158 4acb54ba Edgar E. Iglesias
        dc->nr_nops = 0;
1159 4acb54ba Edgar E. Iglesias
    else {
1160 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1161 1567a005 Edgar E. Iglesias
              && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1162 1567a005 Edgar E. Iglesias
              && !(dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
1163 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1164 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1165 1567a005 Edgar E. Iglesias
            return;
1166 1567a005 Edgar E. Iglesias
        }
1167 1567a005 Edgar E. Iglesias
1168 4acb54ba Edgar E. Iglesias
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1169 4acb54ba Edgar E. Iglesias
        dc->nr_nops++;
1170 4acb54ba Edgar E. Iglesias
        if (dc->nr_nops > 4)
1171 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "fetching nop sequence\n");
1172 4acb54ba Edgar E. Iglesias
    }
1173 4acb54ba Edgar E. Iglesias
    /* bit 2 seems to indicate insn type.  */
1174 4acb54ba Edgar E. Iglesias
    dc->type_b = ir & (1 << 29);
1175 4acb54ba Edgar E. Iglesias
1176 4acb54ba Edgar E. Iglesias
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1177 4acb54ba Edgar E. Iglesias
    dc->rd = EXTRACT_FIELD(ir, 21, 25);
1178 4acb54ba Edgar E. Iglesias
    dc->ra = EXTRACT_FIELD(ir, 16, 20);
1179 4acb54ba Edgar E. Iglesias
    dc->rb = EXTRACT_FIELD(ir, 11, 15);
1180 4acb54ba Edgar E. Iglesias
    dc->imm = EXTRACT_FIELD(ir, 0, 15);
1181 4acb54ba Edgar E. Iglesias
1182 4acb54ba Edgar E. Iglesias
    /* Large switch for all insns.  */
1183 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1184 4acb54ba Edgar E. Iglesias
        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1185 4acb54ba Edgar E. Iglesias
            decinfo[i].dec(dc);
1186 4acb54ba Edgar E. Iglesias
            break;
1187 4acb54ba Edgar E. Iglesias
        }
1188 4acb54ba Edgar E. Iglesias
    }
1189 4acb54ba Edgar E. Iglesias
}
1190 4acb54ba Edgar E. Iglesias
1191 4acb54ba Edgar E. Iglesias
static void check_breakpoint(CPUState *env, DisasContext *dc)
1192 4acb54ba Edgar E. Iglesias
{
1193 4acb54ba Edgar E. Iglesias
    CPUBreakpoint *bp;
1194 4acb54ba Edgar E. Iglesias
1195 4acb54ba Edgar E. Iglesias
    if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
1196 4acb54ba Edgar E. Iglesias
        TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1197 4acb54ba Edgar E. Iglesias
            if (bp->pc == dc->pc) {
1198 4acb54ba Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1199 4acb54ba Edgar E. Iglesias
                dc->is_jmp = DISAS_UPDATE;
1200 4acb54ba Edgar E. Iglesias
             }
1201 4acb54ba Edgar E. Iglesias
        }
1202 4acb54ba Edgar E. Iglesias
    }
1203 4acb54ba Edgar E. Iglesias
}
1204 4acb54ba Edgar E. Iglesias
1205 4acb54ba Edgar E. Iglesias
/* generate intermediate code for basic block 'tb'.  */
1206 4acb54ba Edgar E. Iglesias
static void
1207 4acb54ba Edgar E. Iglesias
gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
1208 4acb54ba Edgar E. Iglesias
                               int search_pc)
1209 4acb54ba Edgar E. Iglesias
{
1210 4acb54ba Edgar E. Iglesias
    uint16_t *gen_opc_end;
1211 4acb54ba Edgar E. Iglesias
    uint32_t pc_start;
1212 4acb54ba Edgar E. Iglesias
    int j, lj;
1213 4acb54ba Edgar E. Iglesias
    struct DisasContext ctx;
1214 4acb54ba Edgar E. Iglesias
    struct DisasContext *dc = &ctx;
1215 4acb54ba Edgar E. Iglesias
    uint32_t next_page_start, org_flags;
1216 4acb54ba Edgar E. Iglesias
    target_ulong npc;
1217 4acb54ba Edgar E. Iglesias
    int num_insns;
1218 4acb54ba Edgar E. Iglesias
    int max_insns;
1219 4acb54ba Edgar E. Iglesias
1220 4acb54ba Edgar E. Iglesias
    qemu_log_try_set_file(stderr);
1221 4acb54ba Edgar E. Iglesias
1222 4acb54ba Edgar E. Iglesias
    pc_start = tb->pc;
1223 4acb54ba Edgar E. Iglesias
    dc->env = env;
1224 4acb54ba Edgar E. Iglesias
    dc->tb = tb;
1225 4acb54ba Edgar E. Iglesias
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1226 4acb54ba Edgar E. Iglesias
1227 4acb54ba Edgar E. Iglesias
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1228 4acb54ba Edgar E. Iglesias
1229 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_NEXT;
1230 4acb54ba Edgar E. Iglesias
    dc->jmp = 0;
1231 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1232 4acb54ba Edgar E. Iglesias
    dc->ppc = pc_start;
1233 4acb54ba Edgar E. Iglesias
    dc->pc = pc_start;
1234 4acb54ba Edgar E. Iglesias
    dc->cache_pc = -1;
1235 4acb54ba Edgar E. Iglesias
    dc->singlestep_enabled = env->singlestep_enabled;
1236 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 0;
1237 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 0;
1238 4acb54ba Edgar E. Iglesias
    dc->nr_nops = 0;
1239 4acb54ba Edgar E. Iglesias
1240 4acb54ba Edgar E. Iglesias
    if (pc_start & 3)
1241 4acb54ba Edgar E. Iglesias
        cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
1242 4acb54ba Edgar E. Iglesias
1243 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1244 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1245 4acb54ba Edgar E. Iglesias
        qemu_log("--------------\n");
1246 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1247 4acb54ba Edgar E. Iglesias
#endif
1248 4acb54ba Edgar E. Iglesias
    }
1249 4acb54ba Edgar E. Iglesias
1250 4acb54ba Edgar E. Iglesias
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1251 4acb54ba Edgar E. Iglesias
    lj = -1;
1252 4acb54ba Edgar E. Iglesias
    num_insns = 0;
1253 4acb54ba Edgar E. Iglesias
    max_insns = tb->cflags & CF_COUNT_MASK;
1254 4acb54ba Edgar E. Iglesias
    if (max_insns == 0)
1255 4acb54ba Edgar E. Iglesias
        max_insns = CF_COUNT_MASK;
1256 4acb54ba Edgar E. Iglesias
1257 4acb54ba Edgar E. Iglesias
    gen_icount_start();
1258 4acb54ba Edgar E. Iglesias
    do
1259 4acb54ba Edgar E. Iglesias
    {
1260 4acb54ba Edgar E. Iglesias
#if SIM_COMPAT
1261 4acb54ba Edgar E. Iglesias
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1262 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1263 4acb54ba Edgar E. Iglesias
            gen_helper_debug();
1264 4acb54ba Edgar E. Iglesias
        }
1265 4acb54ba Edgar E. Iglesias
#endif
1266 4acb54ba Edgar E. Iglesias
        check_breakpoint(env, dc);
1267 4acb54ba Edgar E. Iglesias
1268 4acb54ba Edgar E. Iglesias
        if (search_pc) {
1269 4acb54ba Edgar E. Iglesias
            j = gen_opc_ptr - gen_opc_buf;
1270 4acb54ba Edgar E. Iglesias
            if (lj < j) {
1271 4acb54ba Edgar E. Iglesias
                lj++;
1272 4acb54ba Edgar E. Iglesias
                while (lj < j)
1273 4acb54ba Edgar E. Iglesias
                    gen_opc_instr_start[lj++] = 0;
1274 4acb54ba Edgar E. Iglesias
            }
1275 4acb54ba Edgar E. Iglesias
            gen_opc_pc[lj] = dc->pc;
1276 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj] = 1;
1277 4acb54ba Edgar E. Iglesias
                        gen_opc_icount[lj] = num_insns;
1278 4acb54ba Edgar E. Iglesias
        }
1279 4acb54ba Edgar E. Iglesias
1280 4acb54ba Edgar E. Iglesias
        /* Pretty disas.  */
1281 4acb54ba Edgar E. Iglesias
        LOG_DIS("%8.8x:\t", dc->pc);
1282 4acb54ba Edgar E. Iglesias
1283 4acb54ba Edgar E. Iglesias
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1284 4acb54ba Edgar E. Iglesias
            gen_io_start();
1285 4acb54ba Edgar E. Iglesias
1286 4acb54ba Edgar E. Iglesias
        dc->clear_imm = 1;
1287 4acb54ba Edgar E. Iglesias
        decode(dc);
1288 4acb54ba Edgar E. Iglesias
        if (dc->clear_imm)
1289 4acb54ba Edgar E. Iglesias
            dc->tb_flags &= ~IMM_FLAG;
1290 4acb54ba Edgar E. Iglesias
        dc->ppc = dc->pc;
1291 4acb54ba Edgar E. Iglesias
        dc->pc += 4;
1292 4acb54ba Edgar E. Iglesias
        num_insns++;
1293 4acb54ba Edgar E. Iglesias
1294 4acb54ba Edgar E. Iglesias
        if (dc->delayed_branch) {
1295 4acb54ba Edgar E. Iglesias
            dc->delayed_branch--;
1296 4acb54ba Edgar E. Iglesias
            if (!dc->delayed_branch) {
1297 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTI_FLAG)
1298 4acb54ba Edgar E. Iglesias
                    do_rti(dc);
1299 4acb54ba Edgar E. Iglesias
                 if (dc->tb_flags & DRTB_FLAG)
1300 4acb54ba Edgar E. Iglesias
                    do_rtb(dc);
1301 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTE_FLAG)
1302 4acb54ba Edgar E. Iglesias
                    do_rte(dc);
1303 4acb54ba Edgar E. Iglesias
                /* Clear the delay slot flag.  */
1304 4acb54ba Edgar E. Iglesias
                dc->tb_flags &= ~D_FLAG;
1305 4acb54ba Edgar E. Iglesias
                /* If it is a direct jump, try direct chaining.  */
1306 4acb54ba Edgar E. Iglesias
                if (dc->jmp != JMP_DIRECT) {
1307 4acb54ba Edgar E. Iglesias
                    eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1308 4acb54ba Edgar E. Iglesias
                    dc->is_jmp = DISAS_JUMP;
1309 4acb54ba Edgar E. Iglesias
                }
1310 4acb54ba Edgar E. Iglesias
                break;
1311 4acb54ba Edgar E. Iglesias
            }
1312 4acb54ba Edgar E. Iglesias
        }
1313 4acb54ba Edgar E. Iglesias
        if (env->singlestep_enabled)
1314 4acb54ba Edgar E. Iglesias
            break;
1315 4acb54ba Edgar E. Iglesias
    } while (!dc->is_jmp && !dc->cpustate_changed
1316 4acb54ba Edgar E. Iglesias
         && gen_opc_ptr < gen_opc_end
1317 4acb54ba Edgar E. Iglesias
                 && !singlestep
1318 4acb54ba Edgar E. Iglesias
         && (dc->pc < next_page_start)
1319 4acb54ba Edgar E. Iglesias
                 && num_insns < max_insns);
1320 4acb54ba Edgar E. Iglesias
1321 4acb54ba Edgar E. Iglesias
    npc = dc->pc;
1322 4acb54ba Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT) {
1323 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & D_FLAG) {
1324 4acb54ba Edgar E. Iglesias
            dc->is_jmp = DISAS_UPDATE;
1325 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1326 4acb54ba Edgar E. Iglesias
            sync_jmpstate(dc);
1327 4acb54ba Edgar E. Iglesias
        } else
1328 4acb54ba Edgar E. Iglesias
            npc = dc->jmp_pc;
1329 4acb54ba Edgar E. Iglesias
    }
1330 4acb54ba Edgar E. Iglesias
1331 4acb54ba Edgar E. Iglesias
    if (tb->cflags & CF_LAST_IO)
1332 4acb54ba Edgar E. Iglesias
        gen_io_end();
1333 4acb54ba Edgar E. Iglesias
    /* Force an update if the per-tb cpu state has changed.  */
1334 4acb54ba Edgar E. Iglesias
    if (dc->is_jmp == DISAS_NEXT
1335 4acb54ba Edgar E. Iglesias
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1336 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
1337 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1338 4acb54ba Edgar E. Iglesias
    }
1339 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1340 4acb54ba Edgar E. Iglesias
1341 4acb54ba Edgar E. Iglesias
    if (unlikely(env->singlestep_enabled)) {
1342 4acb54ba Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_DEBUG);
1343 4acb54ba Edgar E. Iglesias
        if (dc->is_jmp == DISAS_NEXT)
1344 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1345 4acb54ba Edgar E. Iglesias
    } else {
1346 4acb54ba Edgar E. Iglesias
        switch(dc->is_jmp) {
1347 4acb54ba Edgar E. Iglesias
            case DISAS_NEXT:
1348 4acb54ba Edgar E. Iglesias
                gen_goto_tb(dc, 1, npc);
1349 4acb54ba Edgar E. Iglesias
                break;
1350 4acb54ba Edgar E. Iglesias
            default:
1351 4acb54ba Edgar E. Iglesias
            case DISAS_JUMP:
1352 4acb54ba Edgar E. Iglesias
            case DISAS_UPDATE:
1353 4acb54ba Edgar E. Iglesias
                /* indicate that the hash table must be used
1354 4acb54ba Edgar E. Iglesias
                   to find the next TB */
1355 4acb54ba Edgar E. Iglesias
                tcg_gen_exit_tb(0);
1356 4acb54ba Edgar E. Iglesias
                break;
1357 4acb54ba Edgar E. Iglesias
            case DISAS_TB_JUMP:
1358 4acb54ba Edgar E. Iglesias
                /* nothing more to generate */
1359 4acb54ba Edgar E. Iglesias
                break;
1360 4acb54ba Edgar E. Iglesias
        }
1361 4acb54ba Edgar E. Iglesias
    }
1362 4acb54ba Edgar E. Iglesias
    gen_icount_end(tb, num_insns);
1363 4acb54ba Edgar E. Iglesias
    *gen_opc_ptr = INDEX_op_end;
1364 4acb54ba Edgar E. Iglesias
    if (search_pc) {
1365 4acb54ba Edgar E. Iglesias
        j = gen_opc_ptr - gen_opc_buf;
1366 4acb54ba Edgar E. Iglesias
        lj++;
1367 4acb54ba Edgar E. Iglesias
        while (lj <= j)
1368 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj++] = 0;
1369 4acb54ba Edgar E. Iglesias
    } else {
1370 4acb54ba Edgar E. Iglesias
        tb->size = dc->pc - pc_start;
1371 4acb54ba Edgar E. Iglesias
                tb->icount = num_insns;
1372 4acb54ba Edgar E. Iglesias
    }
1373 4acb54ba Edgar E. Iglesias
1374 4acb54ba Edgar E. Iglesias
#ifdef DEBUG_DISAS
1375 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1376 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1377 4acb54ba Edgar E. Iglesias
        qemu_log("\n");
1378 4acb54ba Edgar E. Iglesias
#if DISAS_GNU
1379 4acb54ba Edgar E. Iglesias
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1380 4acb54ba Edgar E. Iglesias
#endif
1381 4acb54ba Edgar E. Iglesias
        qemu_log("\nisize=%d osize=%zd\n",
1382 4acb54ba Edgar E. Iglesias
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1383 4acb54ba Edgar E. Iglesias
    }
1384 4acb54ba Edgar E. Iglesias
#endif
1385 4acb54ba Edgar E. Iglesias
#endif
1386 4acb54ba Edgar E. Iglesias
    assert(!dc->abort_at_next_insn);
1387 4acb54ba Edgar E. Iglesias
}
1388 4acb54ba Edgar E. Iglesias
1389 4acb54ba Edgar E. Iglesias
void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
1390 4acb54ba Edgar E. Iglesias
{
1391 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 0);
1392 4acb54ba Edgar E. Iglesias
}
1393 4acb54ba Edgar E. Iglesias
1394 4acb54ba Edgar E. Iglesias
void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
1395 4acb54ba Edgar E. Iglesias
{
1396 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 1);
1397 4acb54ba Edgar E. Iglesias
}
1398 4acb54ba Edgar E. Iglesias
1399 4acb54ba Edgar E. Iglesias
void cpu_dump_state (CPUState *env, FILE *f,
1400 4acb54ba Edgar E. Iglesias
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1401 4acb54ba Edgar E. Iglesias
                     int flags)
1402 4acb54ba Edgar E. Iglesias
{
1403 4acb54ba Edgar E. Iglesias
    int i;
1404 4acb54ba Edgar E. Iglesias
1405 4acb54ba Edgar E. Iglesias
    if (!env || !f)
1406 4acb54ba Edgar E. Iglesias
        return;
1407 4acb54ba Edgar E. Iglesias
1408 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "IN: PC=%x %s\n",
1409 4acb54ba Edgar E. Iglesias
                env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1410 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "rmsr=%x resr=%x debug[%x] imm=%x iflags=%x\n",
1411 4acb54ba Edgar E. Iglesias
             env->sregs[SR_MSR], env->sregs[SR_ESR],
1412 4acb54ba Edgar E. Iglesias
             env->debug, env->imm, env->iflags);
1413 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s)\n",
1414 4acb54ba Edgar E. Iglesias
             env->btaken, env->btarget,
1415 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1416 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel");
1417 4acb54ba Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
1418 4acb54ba Edgar E. Iglesias
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1419 4acb54ba Edgar E. Iglesias
        if ((i + 1) % 4 == 0)
1420 4acb54ba Edgar E. Iglesias
            cpu_fprintf(f, "\n");
1421 4acb54ba Edgar E. Iglesias
        }
1422 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "\n\n");
1423 4acb54ba Edgar E. Iglesias
}
1424 4acb54ba Edgar E. Iglesias
1425 4acb54ba Edgar E. Iglesias
CPUState *cpu_mb_init (const char *cpu_model)
1426 4acb54ba Edgar E. Iglesias
{
1427 4acb54ba Edgar E. Iglesias
    CPUState *env;
1428 4acb54ba Edgar E. Iglesias
    static int tcg_initialized = 0;
1429 4acb54ba Edgar E. Iglesias
    int i;
1430 4acb54ba Edgar E. Iglesias
1431 4acb54ba Edgar E. Iglesias
    env = qemu_mallocz(sizeof(CPUState));
1432 4acb54ba Edgar E. Iglesias
1433 4acb54ba Edgar E. Iglesias
    cpu_exec_init(env);
1434 4acb54ba Edgar E. Iglesias
    cpu_reset(env);
1435 4acb54ba Edgar E. Iglesias
1436 4acb54ba Edgar E. Iglesias
    env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
1437 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_BARREL_MASK \
1438 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DIV_MASK \
1439 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_HW_MUL_MASK \
1440 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_EXC_MASK \
1441 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_ICACHE_MASK \
1442 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_DCACHE_MASK \
1443 4acb54ba Edgar E. Iglesias
                       | PVR0_USE_MMU \
1444 4acb54ba Edgar E. Iglesias
                       | (0xb << 8);
1445 4acb54ba Edgar E. Iglesias
     env->pvr.regs[2] = PVR2_D_OPB_MASK \
1446 4acb54ba Edgar E. Iglesias
                        | PVR2_D_LMB_MASK \
1447 4acb54ba Edgar E. Iglesias
                        | PVR2_I_OPB_MASK \
1448 4acb54ba Edgar E. Iglesias
                        | PVR2_I_LMB_MASK \
1449 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MSR_INSTR \
1450 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_PCMP_INSTR \
1451 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_BARREL_MASK \
1452 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_DIV_MASK \
1453 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_HW_MUL_MASK \
1454 4acb54ba Edgar E. Iglesias
                        | PVR2_USE_MUL64_MASK \
1455 4acb54ba Edgar E. Iglesias
                        | 0;
1456 4acb54ba Edgar E. Iglesias
     env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family.  */
1457 4acb54ba Edgar E. Iglesias
     env->pvr.regs[11] = PVR11_USE_MMU;
1458 4acb54ba Edgar E. Iglesias
1459 4acb54ba Edgar E. Iglesias
    if (tcg_initialized)
1460 4acb54ba Edgar E. Iglesias
        return env;
1461 4acb54ba Edgar E. Iglesias
1462 4acb54ba Edgar E. Iglesias
    tcg_initialized = 1;
1463 4acb54ba Edgar E. Iglesias
1464 4acb54ba Edgar E. Iglesias
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1465 4acb54ba Edgar E. Iglesias
1466 4acb54ba Edgar E. Iglesias
    env_debug = tcg_global_mem_new(TCG_AREG0, 
1467 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, debug),
1468 4acb54ba Edgar E. Iglesias
                    "debug0");
1469 4acb54ba Edgar E. Iglesias
    env_iflags = tcg_global_mem_new(TCG_AREG0, 
1470 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, iflags),
1471 4acb54ba Edgar E. Iglesias
                    "iflags");
1472 4acb54ba Edgar E. Iglesias
    env_imm = tcg_global_mem_new(TCG_AREG0, 
1473 4acb54ba Edgar E. Iglesias
                    offsetof(CPUState, imm),
1474 4acb54ba Edgar E. Iglesias
                    "imm");
1475 4acb54ba Edgar E. Iglesias
    env_btarget = tcg_global_mem_new(TCG_AREG0,
1476 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btarget),
1477 4acb54ba Edgar E. Iglesias
                     "btarget");
1478 4acb54ba Edgar E. Iglesias
    env_btaken = tcg_global_mem_new(TCG_AREG0,
1479 4acb54ba Edgar E. Iglesias
                     offsetof(CPUState, btaken),
1480 4acb54ba Edgar E. Iglesias
                     "btaken");
1481 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1482 4acb54ba Edgar E. Iglesias
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1483 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, regs[i]),
1484 4acb54ba Edgar E. Iglesias
                          regnames[i]);
1485 4acb54ba Edgar E. Iglesias
    }
1486 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1487 4acb54ba Edgar E. Iglesias
        cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
1488 4acb54ba Edgar E. Iglesias
                          offsetof(CPUState, sregs[i]),
1489 4acb54ba Edgar E. Iglesias
                          special_regnames[i]);
1490 4acb54ba Edgar E. Iglesias
    }
1491 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 2
1492 4acb54ba Edgar E. Iglesias
#include "helper.h"
1493 4acb54ba Edgar E. Iglesias
1494 4acb54ba Edgar E. Iglesias
    return env;
1495 4acb54ba Edgar E. Iglesias
}
1496 4acb54ba Edgar E. Iglesias
1497 4acb54ba Edgar E. Iglesias
void cpu_reset (CPUState *env)
1498 4acb54ba Edgar E. Iglesias
{
1499 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1500 4acb54ba Edgar E. Iglesias
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
1501 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1502 4acb54ba Edgar E. Iglesias
    }
1503 4acb54ba Edgar E. Iglesias
1504 4acb54ba Edgar E. Iglesias
    memset(env, 0, offsetof(CPUMBState, breakpoints));
1505 4acb54ba Edgar E. Iglesias
    tlb_flush(env, 1);
1506 4acb54ba Edgar E. Iglesias
1507 4acb54ba Edgar E. Iglesias
    env->sregs[SR_MSR] = 0;
1508 4acb54ba Edgar E. Iglesias
#if defined(CONFIG_USER_ONLY)
1509 4acb54ba Edgar E. Iglesias
    /* start in user mode with interrupts enabled.  */
1510 4acb54ba Edgar E. Iglesias
    env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp.  */
1511 4acb54ba Edgar E. Iglesias
#else
1512 4acb54ba Edgar E. Iglesias
    mmu_init(&env->mmu);
1513 4acb54ba Edgar E. Iglesias
#endif
1514 4acb54ba Edgar E. Iglesias
}
1515 4acb54ba Edgar E. Iglesias
1516 4acb54ba Edgar E. Iglesias
void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
1517 4acb54ba Edgar E. Iglesias
                 unsigned long searched_pc, int pc_pos, void *puc)
1518 4acb54ba Edgar E. Iglesias
{
1519 4acb54ba Edgar E. Iglesias
    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
1520 4acb54ba Edgar E. Iglesias
}