Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ e6aa0f11

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