Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ 8cfd0495

History | View | Annotate | Download (58.5 kB)

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