Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ d2d979c6

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