Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ 48ff7a62

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