Statistics
| Branch: | Revision:

root / target-microblaze / translate.c @ ef5b2344

History | View | Annotate | Download (57.3 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 4acb54ba Edgar E. Iglesias
#include "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 4acb54ba Edgar E. Iglesias
#include "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 4acb54ba Edgar E. Iglesias
    gen_helper_raise_exception(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 4b4a72e5 Stefan Weil
        tcg_gen_exit_tb((tcg_target_long)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 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
507 4acb54ba Edgar E. Iglesias
        else
508 4acb54ba Edgar E. Iglesias
            gen_helper_mmu_read(cpu_R[dc->rd], 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 4acb54ba Edgar E. Iglesias
        gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
708 4acb54ba Edgar E. Iglesias
    else
709 4acb54ba Edgar E. Iglesias
        gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
710 4acb54ba Edgar E. Iglesias
    if (!dc->rd)
711 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], 0);
712 4acb54ba Edgar E. Iglesias
}
713 4acb54ba Edgar E. Iglesias
714 4acb54ba Edgar E. Iglesias
static void dec_barrel(DisasContext *dc)
715 4acb54ba Edgar E. Iglesias
{
716 4acb54ba Edgar E. Iglesias
    TCGv t0;
717 4acb54ba Edgar E. Iglesias
    unsigned int s, t;
718 4acb54ba Edgar E. Iglesias
719 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
720 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
721 1567a005 Edgar E. Iglesias
          && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
722 1567a005 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
723 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
724 1567a005 Edgar E. Iglesias
        return;
725 1567a005 Edgar E. Iglesias
    }
726 1567a005 Edgar E. Iglesias
727 4acb54ba Edgar E. Iglesias
    s = dc->imm & (1 << 10);
728 4acb54ba Edgar E. Iglesias
    t = dc->imm & (1 << 9);
729 4acb54ba Edgar E. Iglesias
730 4acb54ba Edgar E. Iglesias
    LOG_DIS("bs%s%s r%d r%d r%d\n",
731 4acb54ba Edgar E. Iglesias
            s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb);
732 4acb54ba Edgar E. Iglesias
733 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
734 4acb54ba Edgar E. Iglesias
735 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc)));
736 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, 31);
737 4acb54ba Edgar E. Iglesias
738 4acb54ba Edgar E. Iglesias
    if (s)
739 4acb54ba Edgar E. Iglesias
        tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
740 4acb54ba Edgar E. Iglesias
    else {
741 4acb54ba Edgar E. Iglesias
        if (t)
742 4acb54ba Edgar E. Iglesias
            tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
743 4acb54ba Edgar E. Iglesias
        else
744 4acb54ba Edgar E. Iglesias
            tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0);
745 4acb54ba Edgar E. Iglesias
    }
746 4acb54ba Edgar E. Iglesias
}
747 4acb54ba Edgar E. Iglesias
748 4acb54ba Edgar E. Iglesias
static void dec_bit(DisasContext *dc)
749 4acb54ba Edgar E. Iglesias
{
750 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
751 4acb54ba Edgar E. Iglesias
    unsigned int op;
752 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
753 4acb54ba Edgar E. Iglesias
754 ace2e4da Peter A. G. Crosthwaite
    op = dc->ir & ((1 << 9) - 1);
755 4acb54ba Edgar E. Iglesias
    switch (op) {
756 4acb54ba Edgar E. Iglesias
        case 0x21:
757 4acb54ba Edgar E. Iglesias
            /* src.  */
758 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
759 4acb54ba Edgar E. Iglesias
760 4acb54ba Edgar E. Iglesias
            LOG_DIS("src r%d r%d\n", dc->rd, dc->ra);
761 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
762 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
763 4acb54ba Edgar E. Iglesias
                t1 = tcg_temp_new();
764 4acb54ba Edgar E. Iglesias
                read_carry(dc, t1);
765 4acb54ba Edgar E. Iglesias
                tcg_gen_shli_tl(t1, t1, 31);
766 4acb54ba Edgar E. Iglesias
767 4acb54ba Edgar E. Iglesias
                tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
768 4acb54ba Edgar E. Iglesias
                tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t1);
769 4acb54ba Edgar E. Iglesias
                tcg_temp_free(t1);
770 4acb54ba Edgar E. Iglesias
            }
771 4acb54ba Edgar E. Iglesias
772 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
773 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
774 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
775 4acb54ba Edgar E. Iglesias
            break;
776 4acb54ba Edgar E. Iglesias
777 4acb54ba Edgar E. Iglesias
        case 0x1:
778 4acb54ba Edgar E. Iglesias
        case 0x41:
779 4acb54ba Edgar E. Iglesias
            /* srl.  */
780 4acb54ba Edgar E. Iglesias
            t0 = tcg_temp_new();
781 4acb54ba Edgar E. Iglesias
            LOG_DIS("srl r%d r%d\n", dc->rd, dc->ra);
782 4acb54ba Edgar E. Iglesias
783 4acb54ba Edgar E. Iglesias
            /* Update carry.  */
784 4acb54ba Edgar E. Iglesias
            tcg_gen_andi_tl(t0, cpu_R[dc->ra], 1);
785 4acb54ba Edgar E. Iglesias
            write_carry(dc, t0);
786 4acb54ba Edgar E. Iglesias
            tcg_temp_free(t0);
787 4acb54ba Edgar E. Iglesias
            if (dc->rd) {
788 4acb54ba Edgar E. Iglesias
                if (op == 0x41)
789 4acb54ba Edgar E. Iglesias
                    tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
790 4acb54ba Edgar E. Iglesias
                else
791 4acb54ba Edgar E. Iglesias
                    tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1);
792 4acb54ba Edgar E. Iglesias
            }
793 4acb54ba Edgar E. Iglesias
            break;
794 4acb54ba Edgar E. Iglesias
        case 0x60:
795 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext8s r%d r%d\n", dc->rd, dc->ra);
796 4acb54ba Edgar E. Iglesias
            tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
797 4acb54ba Edgar E. Iglesias
            break;
798 4acb54ba Edgar E. Iglesias
        case 0x61:
799 4acb54ba Edgar E. Iglesias
            LOG_DIS("ext16s r%d r%d\n", dc->rd, dc->ra);
800 4acb54ba Edgar E. Iglesias
            tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
801 4acb54ba Edgar E. Iglesias
            break;
802 4acb54ba Edgar E. Iglesias
        case 0x64:
803 f062a3c7 Edgar E. Iglesias
        case 0x66:
804 f062a3c7 Edgar E. Iglesias
        case 0x74:
805 f062a3c7 Edgar E. Iglesias
        case 0x76:
806 4acb54ba Edgar E. Iglesias
            /* wdc.  */
807 4acb54ba Edgar E. Iglesias
            LOG_DIS("wdc r%d\n", dc->ra);
808 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
809 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
810 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
811 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
812 1567a005 Edgar E. Iglesias
                return;
813 1567a005 Edgar E. Iglesias
            }
814 4acb54ba Edgar E. Iglesias
            break;
815 4acb54ba Edgar E. Iglesias
        case 0x68:
816 4acb54ba Edgar E. Iglesias
            /* wic.  */
817 4acb54ba Edgar E. Iglesias
            LOG_DIS("wic r%d\n", dc->ra);
818 1567a005 Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
819 1567a005 Edgar E. Iglesias
                 && mem_index == MMU_USER_IDX) {
820 1567a005 Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
821 1567a005 Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
822 1567a005 Edgar E. Iglesias
                return;
823 1567a005 Edgar E. Iglesias
            }
824 4acb54ba Edgar E. Iglesias
            break;
825 48b5e96f Edgar E. Iglesias
        case 0xe0:
826 48b5e96f Edgar E. Iglesias
            if ((dc->tb_flags & MSR_EE_FLAG)
827 48b5e96f Edgar E. Iglesias
                && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
828 48b5e96f Edgar E. Iglesias
                && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
829 48b5e96f Edgar E. Iglesias
                tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
830 48b5e96f Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_HW_EXCP);
831 48b5e96f Edgar E. Iglesias
            }
832 48b5e96f Edgar E. Iglesias
            if (dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR) {
833 48b5e96f Edgar E. Iglesias
                gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
834 48b5e96f Edgar E. Iglesias
            }
835 48b5e96f Edgar E. Iglesias
            break;
836 ace2e4da Peter A. G. Crosthwaite
        case 0x1e0:
837 ace2e4da Peter A. G. Crosthwaite
            /* swapb */
838 ace2e4da Peter A. G. Crosthwaite
            LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
839 ace2e4da Peter A. G. Crosthwaite
            tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
840 ace2e4da Peter A. G. Crosthwaite
            break;
841 ace2e4da Peter A. G. Crosthwaite
        case 0x1e1:
842 ace2e4da Peter A. G. Crosthwaite
            /*swaph */
843 ace2e4da Peter A. G. Crosthwaite
            LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
844 ace2e4da Peter A. G. Crosthwaite
            tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
845 ace2e4da Peter A. G. Crosthwaite
            break;
846 4acb54ba Edgar E. Iglesias
        default:
847 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
848 4acb54ba Edgar E. Iglesias
                     dc->pc, op, dc->rd, dc->ra, dc->rb);
849 4acb54ba Edgar E. Iglesias
            break;
850 4acb54ba Edgar E. Iglesias
    }
851 4acb54ba Edgar E. Iglesias
}
852 4acb54ba Edgar E. Iglesias
853 4acb54ba Edgar E. Iglesias
static inline void sync_jmpstate(DisasContext *dc)
854 4acb54ba Edgar E. Iglesias
{
855 844bab60 Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
856 844bab60 Edgar E. Iglesias
        if (dc->jmp == JMP_DIRECT) {
857 844bab60 Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
858 844bab60 Edgar E. Iglesias
        }
859 23979dc5 Edgar E. Iglesias
        dc->jmp = JMP_INDIRECT;
860 23979dc5 Edgar E. Iglesias
        tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
861 4acb54ba Edgar E. Iglesias
    }
862 4acb54ba Edgar E. Iglesias
}
863 4acb54ba Edgar E. Iglesias
864 4acb54ba Edgar E. Iglesias
static void dec_imm(DisasContext *dc)
865 4acb54ba Edgar E. Iglesias
{
866 4acb54ba Edgar E. Iglesias
    LOG_DIS("imm %x\n", dc->imm << 16);
867 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_imm, (dc->imm << 16));
868 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= IMM_FLAG;
869 4acb54ba Edgar E. Iglesias
    dc->clear_imm = 0;
870 4acb54ba Edgar E. Iglesias
}
871 4acb54ba Edgar E. Iglesias
872 4acb54ba Edgar E. Iglesias
static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
873 4acb54ba Edgar E. Iglesias
                            unsigned int size)
874 4acb54ba Edgar E. Iglesias
{
875 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
876 4acb54ba Edgar E. Iglesias
877 4acb54ba Edgar E. Iglesias
    if (size == 1) {
878 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld8u(dst, addr, mem_index);
879 4acb54ba Edgar E. Iglesias
    } else if (size == 2) {
880 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld16u(dst, addr, mem_index);
881 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
882 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_ld32u(dst, addr, mem_index);
883 4acb54ba Edgar E. Iglesias
    } else
884 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect load size %d\n", size);
885 4acb54ba Edgar E. Iglesias
}
886 4acb54ba Edgar E. Iglesias
887 4acb54ba Edgar E. Iglesias
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
888 4acb54ba Edgar E. Iglesias
{
889 4acb54ba Edgar E. Iglesias
    unsigned int extimm = dc->tb_flags & IMM_FLAG;
890 5818dee5 Edgar E. Iglesias
    /* Should be set to one if r1 is used by loadstores.  */
891 5818dee5 Edgar E. Iglesias
    int stackprot = 0;
892 5818dee5 Edgar E. Iglesias
893 5818dee5 Edgar E. Iglesias
    /* All load/stores use ra.  */
894 5818dee5 Edgar E. Iglesias
    if (dc->ra == 1) {
895 5818dee5 Edgar E. Iglesias
        stackprot = 1;
896 5818dee5 Edgar E. Iglesias
    }
897 4acb54ba Edgar E. Iglesias
898 9ef55357 Edgar E. Iglesias
    /* Treat the common cases first.  */
899 4acb54ba Edgar E. Iglesias
    if (!dc->type_b) {
900 4b5ef0b5 Edgar E. Iglesias
        /* If any of the regs is r0, return a ptr to the other.  */
901 4b5ef0b5 Edgar E. Iglesias
        if (dc->ra == 0) {
902 4b5ef0b5 Edgar E. Iglesias
            return &cpu_R[dc->rb];
903 4b5ef0b5 Edgar E. Iglesias
        } else if (dc->rb == 0) {
904 4b5ef0b5 Edgar E. Iglesias
            return &cpu_R[dc->ra];
905 4b5ef0b5 Edgar E. Iglesias
        }
906 4b5ef0b5 Edgar E. Iglesias
907 5818dee5 Edgar E. Iglesias
        if (dc->rb == 1) {
908 5818dee5 Edgar E. Iglesias
            stackprot = 1;
909 5818dee5 Edgar E. Iglesias
        }
910 5818dee5 Edgar E. Iglesias
911 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
912 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
913 5818dee5 Edgar E. Iglesias
914 5818dee5 Edgar E. Iglesias
        if (stackprot) {
915 5818dee5 Edgar E. Iglesias
            gen_helper_stackprot(*t);
916 5818dee5 Edgar E. Iglesias
        }
917 4acb54ba Edgar E. Iglesias
        return t;
918 4acb54ba Edgar E. Iglesias
    }
919 4acb54ba Edgar E. Iglesias
    /* Immediate.  */
920 4acb54ba Edgar E. Iglesias
    if (!extimm) {
921 4acb54ba Edgar E. Iglesias
        if (dc->imm == 0) {
922 4acb54ba Edgar E. Iglesias
            return &cpu_R[dc->ra];
923 4acb54ba Edgar E. Iglesias
        }
924 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
925 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));
926 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);
927 4acb54ba Edgar E. Iglesias
    } else {
928 4acb54ba Edgar E. Iglesias
        *t = tcg_temp_new();
929 4acb54ba Edgar E. Iglesias
        tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
930 4acb54ba Edgar E. Iglesias
    }
931 4acb54ba Edgar E. Iglesias
932 5818dee5 Edgar E. Iglesias
    if (stackprot) {
933 5818dee5 Edgar E. Iglesias
        gen_helper_stackprot(*t);
934 5818dee5 Edgar E. Iglesias
    }
935 4acb54ba Edgar E. Iglesias
    return t;
936 4acb54ba Edgar E. Iglesias
}
937 4acb54ba Edgar E. Iglesias
938 9f8beb66 Edgar E. Iglesias
static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
939 9f8beb66 Edgar E. Iglesias
{
940 9f8beb66 Edgar E. Iglesias
    if (size == 4) {
941 9f8beb66 Edgar E. Iglesias
        tcg_gen_bswap32_tl(dst, src);
942 9f8beb66 Edgar E. Iglesias
    } else if (size == 2) {
943 9f8beb66 Edgar E. Iglesias
        TCGv t = tcg_temp_new();
944 9f8beb66 Edgar E. Iglesias
945 9f8beb66 Edgar E. Iglesias
        /* bswap16 assumes the high bits are zero.  */
946 9f8beb66 Edgar E. Iglesias
        tcg_gen_andi_tl(t, src, 0xffff);
947 9f8beb66 Edgar E. Iglesias
        tcg_gen_bswap16_tl(dst, t);
948 9f8beb66 Edgar E. Iglesias
        tcg_temp_free(t);
949 9f8beb66 Edgar E. Iglesias
    } else {
950 9f8beb66 Edgar E. Iglesias
        /* Ignore.
951 9f8beb66 Edgar E. Iglesias
        cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
952 9f8beb66 Edgar E. Iglesias
        */
953 9f8beb66 Edgar E. Iglesias
    }
954 9f8beb66 Edgar E. Iglesias
}
955 9f8beb66 Edgar E. Iglesias
956 4acb54ba Edgar E. Iglesias
static void dec_load(DisasContext *dc)
957 4acb54ba Edgar E. Iglesias
{
958 4acb54ba Edgar E. Iglesias
    TCGv t, *addr;
959 8cc9b43f Peter A. G. Crosthwaite
    unsigned int size, rev = 0, ex = 0;
960 4acb54ba Edgar E. Iglesias
961 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
962 9f8beb66 Edgar E. Iglesias
963 9f8beb66 Edgar E. Iglesias
    if (!dc->type_b) {
964 9f8beb66 Edgar E. Iglesias
        rev = (dc->ir >> 9) & 1;
965 8cc9b43f Peter A. G. Crosthwaite
        ex = (dc->ir >> 10) & 1;
966 9f8beb66 Edgar E. Iglesias
    }
967 9f8beb66 Edgar E. Iglesias
968 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
969 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
970 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
971 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
972 0187688f Edgar E. Iglesias
        return;
973 0187688f Edgar E. Iglesias
    }
974 4acb54ba Edgar E. Iglesias
975 8cc9b43f Peter A. G. Crosthwaite
    LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
976 8cc9b43f Peter A. G. Crosthwaite
                                                        ex ? "x" : "");
977 9f8beb66 Edgar E. Iglesias
978 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
979 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
980 4acb54ba Edgar E. Iglesias
981 9f8beb66 Edgar E. Iglesias
    /*
982 9f8beb66 Edgar E. Iglesias
     * When doing reverse accesses we need to do two things.
983 9f8beb66 Edgar E. Iglesias
     *
984 4ff9786c Stefan Weil
     * 1. Reverse the address wrt endianness.
985 9f8beb66 Edgar E. Iglesias
     * 2. Byteswap the data lanes on the way back into the CPU core.
986 9f8beb66 Edgar E. Iglesias
     */
987 9f8beb66 Edgar E. Iglesias
    if (rev && size != 4) {
988 9f8beb66 Edgar E. Iglesias
        /* Endian reverse the address. t is addr.  */
989 9f8beb66 Edgar E. Iglesias
        switch (size) {
990 9f8beb66 Edgar E. Iglesias
            case 1:
991 9f8beb66 Edgar E. Iglesias
            {
992 9f8beb66 Edgar E. Iglesias
                /* 00 -> 11
993 9f8beb66 Edgar E. Iglesias
                   01 -> 10
994 9f8beb66 Edgar E. Iglesias
                   10 -> 10
995 9f8beb66 Edgar E. Iglesias
                   11 -> 00 */
996 9f8beb66 Edgar E. Iglesias
                TCGv low = tcg_temp_new();
997 9f8beb66 Edgar E. Iglesias
998 9f8beb66 Edgar E. Iglesias
                /* Force addr into the temp.  */
999 9f8beb66 Edgar E. Iglesias
                if (addr != &t) {
1000 9f8beb66 Edgar E. Iglesias
                    t = tcg_temp_new();
1001 9f8beb66 Edgar E. Iglesias
                    tcg_gen_mov_tl(t, *addr);
1002 9f8beb66 Edgar E. Iglesias
                    addr = &t;
1003 9f8beb66 Edgar E. Iglesias
                }
1004 9f8beb66 Edgar E. Iglesias
1005 9f8beb66 Edgar E. Iglesias
                tcg_gen_andi_tl(low, t, 3);
1006 9f8beb66 Edgar E. Iglesias
                tcg_gen_sub_tl(low, tcg_const_tl(3), low);
1007 9f8beb66 Edgar E. Iglesias
                tcg_gen_andi_tl(t, t, ~3);
1008 9f8beb66 Edgar E. Iglesias
                tcg_gen_or_tl(t, t, low);
1009 9f8beb66 Edgar E. Iglesias
                tcg_gen_mov_tl(env_imm, t);
1010 9f8beb66 Edgar E. Iglesias
                tcg_temp_free(low);
1011 9f8beb66 Edgar E. Iglesias
                break;
1012 9f8beb66 Edgar E. Iglesias
            }
1013 9f8beb66 Edgar E. Iglesias
1014 9f8beb66 Edgar E. Iglesias
            case 2:
1015 9f8beb66 Edgar E. Iglesias
                /* 00 -> 10
1016 9f8beb66 Edgar E. Iglesias
                   10 -> 00.  */
1017 9f8beb66 Edgar E. Iglesias
                /* Force addr into the temp.  */
1018 9f8beb66 Edgar E. Iglesias
                if (addr != &t) {
1019 9f8beb66 Edgar E. Iglesias
                    t = tcg_temp_new();
1020 9f8beb66 Edgar E. Iglesias
                    tcg_gen_xori_tl(t, *addr, 2);
1021 9f8beb66 Edgar E. Iglesias
                    addr = &t;
1022 9f8beb66 Edgar E. Iglesias
                } else {
1023 9f8beb66 Edgar E. Iglesias
                    tcg_gen_xori_tl(t, t, 2);
1024 9f8beb66 Edgar E. Iglesias
                }
1025 9f8beb66 Edgar E. Iglesias
                break;
1026 9f8beb66 Edgar E. Iglesias
            default:
1027 9f8beb66 Edgar E. Iglesias
                cpu_abort(dc->env, "Invalid reverse size\n");
1028 9f8beb66 Edgar E. Iglesias
                break;
1029 9f8beb66 Edgar E. Iglesias
        }
1030 9f8beb66 Edgar E. Iglesias
    }
1031 9f8beb66 Edgar E. Iglesias
1032 8cc9b43f Peter A. G. Crosthwaite
    /* lwx does not throw unaligned access errors, so force alignment */
1033 8cc9b43f Peter A. G. Crosthwaite
    if (ex) {
1034 8cc9b43f Peter A. G. Crosthwaite
        /* Force addr into the temp.  */
1035 8cc9b43f Peter A. G. Crosthwaite
        if (addr != &t) {
1036 8cc9b43f Peter A. G. Crosthwaite
            t = tcg_temp_new();
1037 8cc9b43f Peter A. G. Crosthwaite
            tcg_gen_mov_tl(t, *addr);
1038 8cc9b43f Peter A. G. Crosthwaite
            addr = &t;
1039 8cc9b43f Peter A. G. Crosthwaite
        }
1040 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_andi_tl(t, t, ~3);
1041 8cc9b43f Peter A. G. Crosthwaite
    }
1042 8cc9b43f Peter A. G. Crosthwaite
1043 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
1044 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
1045 968a40f6 Edgar E. Iglesias
1046 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
1047 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
1048 a12f6507 Edgar E. Iglesias
        TCGv v = tcg_temp_new();
1049 a12f6507 Edgar E. Iglesias
1050 a12f6507 Edgar E. Iglesias
        /*
1051 a12f6507 Edgar E. Iglesias
         * Microblaze gives MMU faults priority over faults due to
1052 a12f6507 Edgar E. Iglesias
         * unaligned addresses. That's why we speculatively do the load
1053 a12f6507 Edgar E. Iglesias
         * into v. If the load succeeds, we verify alignment of the
1054 a12f6507 Edgar E. Iglesias
         * address and if that succeeds we write into the destination reg.
1055 a12f6507 Edgar E. Iglesias
         */
1056 a12f6507 Edgar E. Iglesias
        gen_load(dc, v, *addr, size);
1057 a12f6507 Edgar E. Iglesias
1058 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1059 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
1060 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(0), tcg_const_tl(size - 1));
1061 9f8beb66 Edgar E. Iglesias
        if (dc->rd) {
1062 9f8beb66 Edgar E. Iglesias
            if (rev) {
1063 9f8beb66 Edgar E. Iglesias
                dec_byteswap(dc, cpu_R[dc->rd], v, size);
1064 9f8beb66 Edgar E. Iglesias
            } else {
1065 9f8beb66 Edgar E. Iglesias
                tcg_gen_mov_tl(cpu_R[dc->rd], v);
1066 9f8beb66 Edgar E. Iglesias
            }
1067 9f8beb66 Edgar E. Iglesias
        }
1068 a12f6507 Edgar E. Iglesias
        tcg_temp_free(v);
1069 968a40f6 Edgar E. Iglesias
    } else {
1070 a12f6507 Edgar E. Iglesias
        if (dc->rd) {
1071 a12f6507 Edgar E. Iglesias
            gen_load(dc, cpu_R[dc->rd], *addr, size);
1072 9f8beb66 Edgar E. Iglesias
            if (rev) {
1073 9f8beb66 Edgar E. Iglesias
                dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
1074 9f8beb66 Edgar E. Iglesias
            }
1075 a12f6507 Edgar E. Iglesias
        } else {
1076 9f8beb66 Edgar E. Iglesias
            /* We are loading into r0, no need to reverse.  */
1077 a12f6507 Edgar E. Iglesias
            gen_load(dc, env_imm, *addr, size);
1078 a12f6507 Edgar E. Iglesias
        }
1079 4acb54ba Edgar E. Iglesias
    }
1080 4acb54ba Edgar E. Iglesias
1081 8cc9b43f Peter A. G. Crosthwaite
    if (ex) { /* lwx */
1082 8cc9b43f Peter A. G. Crosthwaite
        /* no support for for AXI exclusive so always clear C */
1083 8cc9b43f Peter A. G. Crosthwaite
        write_carryi(dc, 0);
1084 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr));
1085 8cc9b43f Peter A. G. Crosthwaite
    }
1086 8cc9b43f Peter A. G. Crosthwaite
1087 4acb54ba Edgar E. Iglesias
    if (addr == &t)
1088 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
1089 4acb54ba Edgar E. Iglesias
}
1090 4acb54ba Edgar E. Iglesias
1091 4acb54ba Edgar E. Iglesias
static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
1092 4acb54ba Edgar E. Iglesias
                      unsigned int size)
1093 4acb54ba Edgar E. Iglesias
{
1094 4acb54ba Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1095 4acb54ba Edgar E. Iglesias
1096 4acb54ba Edgar E. Iglesias
    if (size == 1)
1097 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st8(val, addr, mem_index);
1098 4acb54ba Edgar E. Iglesias
    else if (size == 2) {
1099 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st16(val, addr, mem_index);
1100 4acb54ba Edgar E. Iglesias
    } else if (size == 4) {
1101 4acb54ba Edgar E. Iglesias
        tcg_gen_qemu_st32(val, addr, mem_index);
1102 4acb54ba Edgar E. Iglesias
    } else
1103 4acb54ba Edgar E. Iglesias
        cpu_abort(dc->env, "Incorrect store size %d\n", size);
1104 4acb54ba Edgar E. Iglesias
}
1105 4acb54ba Edgar E. Iglesias
1106 4acb54ba Edgar E. Iglesias
static void dec_store(DisasContext *dc)
1107 4acb54ba Edgar E. Iglesias
{
1108 083dbf48 Peter A. G. Crosthwaite
    TCGv t, *addr, swx_addr, r_check;
1109 8cc9b43f Peter A. G. Crosthwaite
    int swx_skip = 0;
1110 8cc9b43f Peter A. G. Crosthwaite
    unsigned int size, rev = 0, ex = 0;
1111 4acb54ba Edgar E. Iglesias
1112 4acb54ba Edgar E. Iglesias
    size = 1 << (dc->opcode & 3);
1113 9f8beb66 Edgar E. Iglesias
    if (!dc->type_b) {
1114 9f8beb66 Edgar E. Iglesias
        rev = (dc->ir >> 9) & 1;
1115 8cc9b43f Peter A. G. Crosthwaite
        ex = (dc->ir >> 10) & 1;
1116 9f8beb66 Edgar E. Iglesias
    }
1117 4acb54ba Edgar E. Iglesias
1118 0187688f Edgar E. Iglesias
    if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
1119 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1120 0187688f Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1121 0187688f Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1122 0187688f Edgar E. Iglesias
        return;
1123 0187688f Edgar E. Iglesias
    }
1124 0187688f Edgar E. Iglesias
1125 8cc9b43f Peter A. G. Crosthwaite
    LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
1126 8cc9b43f Peter A. G. Crosthwaite
                                                        ex ? "x" : "");
1127 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1128 4acb54ba Edgar E. Iglesias
    /* If we get a fault on a dslot, the jmpstate better be in sync.  */
1129 4acb54ba Edgar E. Iglesias
    sync_jmpstate(dc);
1130 4acb54ba Edgar E. Iglesias
    addr = compute_ldst_addr(dc, &t);
1131 968a40f6 Edgar E. Iglesias
1132 083dbf48 Peter A. G. Crosthwaite
    r_check = tcg_temp_new();
1133 083dbf48 Peter A. G. Crosthwaite
    swx_addr = tcg_temp_local_new();
1134 8cc9b43f Peter A. G. Crosthwaite
    if (ex) { /* swx */
1135 8cc9b43f Peter A. G. Crosthwaite
1136 8cc9b43f Peter A. G. Crosthwaite
        /* Force addr into the swx_addr. */
1137 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_mov_tl(swx_addr, *addr);
1138 8cc9b43f Peter A. G. Crosthwaite
        addr = &swx_addr;
1139 8cc9b43f Peter A. G. Crosthwaite
        /* swx does not throw unaligned access errors, so force alignment */
1140 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
1141 8cc9b43f Peter A. G. Crosthwaite
1142 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr));
1143 8cc9b43f Peter A. G. Crosthwaite
        write_carryi(dc, 1);
1144 8cc9b43f Peter A. G. Crosthwaite
        swx_skip = gen_new_label();
1145 8cc9b43f Peter A. G. Crosthwaite
        tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip);
1146 8cc9b43f Peter A. G. Crosthwaite
        write_carryi(dc, 0);
1147 8cc9b43f Peter A. G. Crosthwaite
    }
1148 8cc9b43f Peter A. G. Crosthwaite
1149 9f8beb66 Edgar E. Iglesias
    if (rev && size != 4) {
1150 9f8beb66 Edgar E. Iglesias
        /* Endian reverse the address. t is addr.  */
1151 9f8beb66 Edgar E. Iglesias
        switch (size) {
1152 9f8beb66 Edgar E. Iglesias
            case 1:
1153 9f8beb66 Edgar E. Iglesias
            {
1154 9f8beb66 Edgar E. Iglesias
                /* 00 -> 11
1155 9f8beb66 Edgar E. Iglesias
                   01 -> 10
1156 9f8beb66 Edgar E. Iglesias
                   10 -> 10
1157 9f8beb66 Edgar E. Iglesias
                   11 -> 00 */
1158 9f8beb66 Edgar E. Iglesias
                TCGv low = tcg_temp_new();
1159 9f8beb66 Edgar E. Iglesias
1160 9f8beb66 Edgar E. Iglesias
                /* Force addr into the temp.  */
1161 9f8beb66 Edgar E. Iglesias
                if (addr != &t) {
1162 9f8beb66 Edgar E. Iglesias
                    t = tcg_temp_new();
1163 9f8beb66 Edgar E. Iglesias
                    tcg_gen_mov_tl(t, *addr);
1164 9f8beb66 Edgar E. Iglesias
                    addr = &t;
1165 9f8beb66 Edgar E. Iglesias
                }
1166 9f8beb66 Edgar E. Iglesias
1167 9f8beb66 Edgar E. Iglesias
                tcg_gen_andi_tl(low, t, 3);
1168 9f8beb66 Edgar E. Iglesias
                tcg_gen_sub_tl(low, tcg_const_tl(3), low);
1169 9f8beb66 Edgar E. Iglesias
                tcg_gen_andi_tl(t, t, ~3);
1170 9f8beb66 Edgar E. Iglesias
                tcg_gen_or_tl(t, t, low);
1171 9f8beb66 Edgar E. Iglesias
                tcg_gen_mov_tl(env_imm, t);
1172 9f8beb66 Edgar E. Iglesias
                tcg_temp_free(low);
1173 9f8beb66 Edgar E. Iglesias
                break;
1174 9f8beb66 Edgar E. Iglesias
            }
1175 9f8beb66 Edgar E. Iglesias
1176 9f8beb66 Edgar E. Iglesias
            case 2:
1177 9f8beb66 Edgar E. Iglesias
                /* 00 -> 10
1178 9f8beb66 Edgar E. Iglesias
                   10 -> 00.  */
1179 9f8beb66 Edgar E. Iglesias
                /* Force addr into the temp.  */
1180 9f8beb66 Edgar E. Iglesias
                if (addr != &t) {
1181 9f8beb66 Edgar E. Iglesias
                    t = tcg_temp_new();
1182 9f8beb66 Edgar E. Iglesias
                    tcg_gen_xori_tl(t, *addr, 2);
1183 9f8beb66 Edgar E. Iglesias
                    addr = &t;
1184 9f8beb66 Edgar E. Iglesias
                } else {
1185 9f8beb66 Edgar E. Iglesias
                    tcg_gen_xori_tl(t, t, 2);
1186 9f8beb66 Edgar E. Iglesias
                }
1187 9f8beb66 Edgar E. Iglesias
                break;
1188 9f8beb66 Edgar E. Iglesias
            default:
1189 9f8beb66 Edgar E. Iglesias
                cpu_abort(dc->env, "Invalid reverse size\n");
1190 9f8beb66 Edgar E. Iglesias
                break;
1191 9f8beb66 Edgar E. Iglesias
        }
1192 9f8beb66 Edgar E. Iglesias
1193 9f8beb66 Edgar E. Iglesias
        if (size != 1) {
1194 9f8beb66 Edgar E. Iglesias
            TCGv bs_data = tcg_temp_new();
1195 9f8beb66 Edgar E. Iglesias
            dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
1196 9f8beb66 Edgar E. Iglesias
            gen_store(dc, *addr, bs_data, size);
1197 9f8beb66 Edgar E. Iglesias
            tcg_temp_free(bs_data);
1198 9f8beb66 Edgar E. Iglesias
        } else {
1199 9f8beb66 Edgar E. Iglesias
            gen_store(dc, *addr, cpu_R[dc->rd], size);
1200 9f8beb66 Edgar E. Iglesias
        }
1201 9f8beb66 Edgar E. Iglesias
    } else {
1202 9f8beb66 Edgar E. Iglesias
        if (rev) {
1203 9f8beb66 Edgar E. Iglesias
            TCGv bs_data = tcg_temp_new();
1204 9f8beb66 Edgar E. Iglesias
            dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
1205 9f8beb66 Edgar E. Iglesias
            gen_store(dc, *addr, bs_data, size);
1206 9f8beb66 Edgar E. Iglesias
            tcg_temp_free(bs_data);
1207 9f8beb66 Edgar E. Iglesias
        } else {
1208 9f8beb66 Edgar E. Iglesias
            gen_store(dc, *addr, cpu_R[dc->rd], size);
1209 9f8beb66 Edgar E. Iglesias
        }
1210 9f8beb66 Edgar E. Iglesias
    }
1211 a12f6507 Edgar E. Iglesias
1212 968a40f6 Edgar E. Iglesias
    /* Verify alignment if needed.  */
1213 968a40f6 Edgar E. Iglesias
    if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
1214 a12f6507 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1215 a12f6507 Edgar E. Iglesias
        /* FIXME: if the alignment is wrong, we should restore the value
1216 4abf79a4 Dong Xu Wang
         *        in memory. One possible way to achieve this is to probe
1217 9f8beb66 Edgar E. Iglesias
         *        the MMU prior to the memaccess, thay way we could put
1218 9f8beb66 Edgar E. Iglesias
         *        the alignment checks in between the probe and the mem
1219 9f8beb66 Edgar E. Iglesias
         *        access.
1220 a12f6507 Edgar E. Iglesias
         */
1221 968a40f6 Edgar E. Iglesias
        gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
1222 3aa80988 Edgar E. Iglesias
                            tcg_const_tl(1), tcg_const_tl(size - 1));
1223 968a40f6 Edgar E. Iglesias
    }
1224 083dbf48 Peter A. G. Crosthwaite
1225 8cc9b43f Peter A. G. Crosthwaite
    if (ex) {
1226 8cc9b43f Peter A. G. Crosthwaite
        gen_set_label(swx_skip);
1227 8cc9b43f Peter A. G. Crosthwaite
    }
1228 083dbf48 Peter A. G. Crosthwaite
    tcg_temp_free(r_check);
1229 083dbf48 Peter A. G. Crosthwaite
    tcg_temp_free(swx_addr);
1230 968a40f6 Edgar E. Iglesias
1231 4acb54ba Edgar E. Iglesias
    if (addr == &t)
1232 4acb54ba Edgar E. Iglesias
        tcg_temp_free(t);
1233 4acb54ba Edgar E. Iglesias
}
1234 4acb54ba Edgar E. Iglesias
1235 4acb54ba Edgar E. Iglesias
static inline void eval_cc(DisasContext *dc, unsigned int cc,
1236 4acb54ba Edgar E. Iglesias
                           TCGv d, TCGv a, TCGv b)
1237 4acb54ba Edgar E. Iglesias
{
1238 4acb54ba Edgar E. Iglesias
    switch (cc) {
1239 4acb54ba Edgar E. Iglesias
        case CC_EQ:
1240 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b);
1241 4acb54ba Edgar E. Iglesias
            break;
1242 4acb54ba Edgar E. Iglesias
        case CC_NE:
1243 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_NE, d, a, b);
1244 4acb54ba Edgar E. Iglesias
            break;
1245 4acb54ba Edgar E. Iglesias
        case CC_LT:
1246 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_LT, d, a, b);
1247 4acb54ba Edgar E. Iglesias
            break;
1248 4acb54ba Edgar E. Iglesias
        case CC_LE:
1249 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_LE, d, a, b);
1250 4acb54ba Edgar E. Iglesias
            break;
1251 4acb54ba Edgar E. Iglesias
        case CC_GE:
1252 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_GE, d, a, b);
1253 4acb54ba Edgar E. Iglesias
            break;
1254 4acb54ba Edgar E. Iglesias
        case CC_GT:
1255 b2565c69 Edgar E. Iglesias
            tcg_gen_setcond_tl(TCG_COND_GT, d, a, b);
1256 4acb54ba Edgar E. Iglesias
            break;
1257 4acb54ba Edgar E. Iglesias
        default:
1258 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
1259 4acb54ba Edgar E. Iglesias
            break;
1260 4acb54ba Edgar E. Iglesias
    }
1261 4acb54ba Edgar E. Iglesias
}
1262 4acb54ba Edgar E. Iglesias
1263 4acb54ba Edgar E. Iglesias
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
1264 4acb54ba Edgar E. Iglesias
{
1265 4acb54ba Edgar E. Iglesias
    int l1;
1266 4acb54ba Edgar E. Iglesias
1267 4acb54ba Edgar E. Iglesias
    l1 = gen_new_label();
1268 4acb54ba Edgar E. Iglesias
    /* Conditional jmp.  */
1269 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
1270 4acb54ba Edgar E. Iglesias
    tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
1271 4acb54ba Edgar E. Iglesias
    tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true);
1272 4acb54ba Edgar E. Iglesias
    gen_set_label(l1);
1273 4acb54ba Edgar E. Iglesias
}
1274 4acb54ba Edgar E. Iglesias
1275 4acb54ba Edgar E. Iglesias
static void dec_bcc(DisasContext *dc)
1276 4acb54ba Edgar E. Iglesias
{
1277 4acb54ba Edgar E. Iglesias
    unsigned int cc;
1278 4acb54ba Edgar E. Iglesias
    unsigned int dslot;
1279 4acb54ba Edgar E. Iglesias
1280 4acb54ba Edgar E. Iglesias
    cc = EXTRACT_FIELD(dc->ir, 21, 23);
1281 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 25);
1282 4acb54ba Edgar E. Iglesias
    LOG_DIS("bcc%s r%d %x\n", dslot ? "d" : "", dc->ra, dc->imm);
1283 4acb54ba Edgar E. Iglesias
1284 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
1285 4acb54ba Edgar E. Iglesias
    if (dslot) {
1286 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
1287 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
1288 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1289 68cee38a Andreas Färber
                      cpu_env, offsetof(CPUMBState, bimm));
1290 4acb54ba Edgar E. Iglesias
    }
1291 4acb54ba Edgar E. Iglesias
1292 61204ce8 Edgar E. Iglesias
    if (dec_alu_op_b_is_small_imm(dc)) {
1293 61204ce8 Edgar E. Iglesias
        int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend.  */
1294 61204ce8 Edgar E. Iglesias
1295 61204ce8 Edgar E. Iglesias
        tcg_gen_movi_tl(env_btarget, dc->pc + offset);
1296 844bab60 Edgar E. Iglesias
        dc->jmp = JMP_DIRECT_CC;
1297 23979dc5 Edgar E. Iglesias
        dc->jmp_pc = dc->pc + offset;
1298 61204ce8 Edgar E. Iglesias
    } else {
1299 23979dc5 Edgar E. Iglesias
        dc->jmp = JMP_INDIRECT;
1300 61204ce8 Edgar E. Iglesias
        tcg_gen_movi_tl(env_btarget, dc->pc);
1301 61204ce8 Edgar E. Iglesias
        tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1302 61204ce8 Edgar E. Iglesias
    }
1303 61204ce8 Edgar E. Iglesias
    eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
1304 4acb54ba Edgar E. Iglesias
}
1305 4acb54ba Edgar E. Iglesias
1306 4acb54ba Edgar E. Iglesias
static void dec_br(DisasContext *dc)
1307 4acb54ba Edgar E. Iglesias
{
1308 9f6113c7 Edgar E. Iglesias
    unsigned int dslot, link, abs, mbar;
1309 ff21f70a Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1310 4acb54ba Edgar E. Iglesias
1311 4acb54ba Edgar E. Iglesias
    dslot = dc->ir & (1 << 20);
1312 4acb54ba Edgar E. Iglesias
    abs = dc->ir & (1 << 19);
1313 4acb54ba Edgar E. Iglesias
    link = dc->ir & (1 << 18);
1314 9f6113c7 Edgar E. Iglesias
1315 9f6113c7 Edgar E. Iglesias
    /* Memory barrier.  */
1316 9f6113c7 Edgar E. Iglesias
    mbar = (dc->ir >> 16) & 31;
1317 9f6113c7 Edgar E. Iglesias
    if (mbar == 2 && dc->imm == 4) {
1318 9f6113c7 Edgar E. Iglesias
        LOG_DIS("mbar %d\n", dc->rd);
1319 9f6113c7 Edgar E. Iglesias
        /* Break the TB.  */
1320 9f6113c7 Edgar E. Iglesias
        dc->cpustate_changed = 1;
1321 9f6113c7 Edgar E. Iglesias
        return;
1322 9f6113c7 Edgar E. Iglesias
    }
1323 9f6113c7 Edgar E. Iglesias
1324 4acb54ba Edgar E. Iglesias
    LOG_DIS("br%s%s%s%s imm=%x\n",
1325 4acb54ba Edgar E. Iglesias
             abs ? "a" : "", link ? "l" : "",
1326 4acb54ba Edgar E. Iglesias
             dc->type_b ? "i" : "", dslot ? "d" : "",
1327 4acb54ba Edgar E. Iglesias
             dc->imm);
1328 4acb54ba Edgar E. Iglesias
1329 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 1;
1330 4acb54ba Edgar E. Iglesias
    if (dslot) {
1331 4acb54ba Edgar E. Iglesias
        dc->delayed_branch = 2;
1332 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= D_FLAG;
1333 4acb54ba Edgar E. Iglesias
        tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1334 68cee38a Andreas Färber
                      cpu_env, offsetof(CPUMBState, bimm));
1335 4acb54ba Edgar E. Iglesias
    }
1336 4acb54ba Edgar E. Iglesias
    if (link && dc->rd)
1337 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
1338 4acb54ba Edgar E. Iglesias
1339 4acb54ba Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
1340 4acb54ba Edgar E. Iglesias
    if (abs) {
1341 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(env_btaken, 1);
1342 4acb54ba Edgar E. Iglesias
        tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc)));
1343 ff21f70a Edgar E. Iglesias
        if (link && !dslot) {
1344 ff21f70a Edgar E. Iglesias
            if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18))
1345 ff21f70a Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_BREAK);
1346 ff21f70a Edgar E. Iglesias
            if (dc->imm == 0) {
1347 ff21f70a Edgar E. Iglesias
                if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) {
1348 ff21f70a Edgar E. Iglesias
                    tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1349 ff21f70a Edgar E. Iglesias
                    t_gen_raise_exception(dc, EXCP_HW_EXCP);
1350 ff21f70a Edgar E. Iglesias
                    return;
1351 ff21f70a Edgar E. Iglesias
                }
1352 ff21f70a Edgar E. Iglesias
1353 ff21f70a Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1354 ff21f70a Edgar E. Iglesias
            }
1355 ff21f70a Edgar E. Iglesias
        }
1356 4acb54ba Edgar E. Iglesias
    } else {
1357 61204ce8 Edgar E. Iglesias
        if (dec_alu_op_b_is_small_imm(dc)) {
1358 61204ce8 Edgar E. Iglesias
            dc->jmp = JMP_DIRECT;
1359 61204ce8 Edgar E. Iglesias
            dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
1360 61204ce8 Edgar E. Iglesias
        } else {
1361 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btaken, 1);
1362 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(env_btarget, dc->pc);
1363 4acb54ba Edgar E. Iglesias
            tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
1364 4acb54ba Edgar E. Iglesias
        }
1365 4acb54ba Edgar E. Iglesias
    }
1366 4acb54ba Edgar E. Iglesias
}
1367 4acb54ba Edgar E. Iglesias
1368 4acb54ba Edgar E. Iglesias
static inline void do_rti(DisasContext *dc)
1369 4acb54ba Edgar E. Iglesias
{
1370 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1371 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1372 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1373 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1);
1374 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE);
1375 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1376 4acb54ba Edgar E. Iglesias
1377 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1378 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1379 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1380 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1381 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1382 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTI_FLAG;
1383 4acb54ba Edgar E. Iglesias
}
1384 4acb54ba Edgar E. Iglesias
1385 4acb54ba Edgar E. Iglesias
static inline void do_rtb(DisasContext *dc)
1386 4acb54ba Edgar E. Iglesias
{
1387 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1388 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1389 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1390 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP);
1391 4acb54ba Edgar E. Iglesias
    tcg_gen_shri_tl(t0, t1, 1);
1392 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM));
1393 4acb54ba Edgar E. Iglesias
1394 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM));
1395 4acb54ba Edgar E. Iglesias
    tcg_gen_or_tl(t1, t1, t0);
1396 4acb54ba Edgar E. Iglesias
    msr_write(dc, t1);
1397 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t1);
1398 4acb54ba Edgar E. Iglesias
    tcg_temp_free(t0);
1399 4acb54ba Edgar E. Iglesias
    dc->tb_flags &= ~DRTB_FLAG;
1400 4acb54ba Edgar E. Iglesias
}
1401 4acb54ba Edgar E. Iglesias
1402 4acb54ba Edgar E. Iglesias
static inline void do_rte(DisasContext *dc)
1403 4acb54ba Edgar E. Iglesias
{
1404 4acb54ba Edgar E. Iglesias
    TCGv t0, t1;
1405 4acb54ba Edgar E. Iglesias
    t0 = tcg_temp_new();
1406 4acb54ba Edgar E. Iglesias
    t1 = tcg_temp_new();
1407 4acb54ba Edgar E. Iglesias
1408 4acb54ba Edgar E. Iglesias
    tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE);
1409 4acb54ba Edgar E. Iglesias
    tcg_gen_andi_tl(t1, t1, ~MSR_EIP);
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 &= ~DRTE_FLAG;
1419 4acb54ba Edgar E. Iglesias
}
1420 4acb54ba Edgar E. Iglesias
1421 4acb54ba Edgar E. Iglesias
static void dec_rts(DisasContext *dc)
1422 4acb54ba Edgar E. Iglesias
{
1423 4acb54ba Edgar E. Iglesias
    unsigned int b_bit, i_bit, e_bit;
1424 1567a005 Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1425 4acb54ba Edgar E. Iglesias
1426 4acb54ba Edgar E. Iglesias
    i_bit = dc->ir & (1 << 21);
1427 4acb54ba Edgar E. Iglesias
    b_bit = dc->ir & (1 << 22);
1428 4acb54ba Edgar E. Iglesias
    e_bit = dc->ir & (1 << 23);
1429 4acb54ba Edgar E. Iglesias
1430 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = 2;
1431 4acb54ba Edgar E. Iglesias
    dc->tb_flags |= D_FLAG;
1432 4acb54ba Edgar E. Iglesias
    tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
1433 68cee38a Andreas Färber
                  cpu_env, offsetof(CPUMBState, bimm));
1434 4acb54ba Edgar E. Iglesias
1435 4acb54ba Edgar E. Iglesias
    if (i_bit) {
1436 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtid ir=%x\n", dc->ir);
1437 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1438 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1439 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1440 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1441 1567a005 Edgar E. Iglesias
        }
1442 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTI_FLAG;
1443 4acb54ba Edgar E. Iglesias
    } else if (b_bit) {
1444 4acb54ba Edgar E. Iglesias
        LOG_DIS("rtbd ir=%x\n", dc->ir);
1445 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1446 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1447 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1448 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1449 1567a005 Edgar E. Iglesias
        }
1450 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTB_FLAG;
1451 4acb54ba Edgar E. Iglesias
    } else if (e_bit) {
1452 4acb54ba Edgar E. Iglesias
        LOG_DIS("rted ir=%x\n", dc->ir);
1453 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1454 1567a005 Edgar E. Iglesias
             && mem_index == MMU_USER_IDX) {
1455 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1456 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1457 1567a005 Edgar E. Iglesias
        }
1458 4acb54ba Edgar E. Iglesias
        dc->tb_flags |= DRTE_FLAG;
1459 4acb54ba Edgar E. Iglesias
    } else
1460 4acb54ba Edgar E. Iglesias
        LOG_DIS("rts ir=%x\n", dc->ir);
1461 4acb54ba Edgar E. Iglesias
1462 23979dc5 Edgar E. Iglesias
    dc->jmp = JMP_INDIRECT;
1463 4acb54ba Edgar E. Iglesias
    tcg_gen_movi_tl(env_btaken, 1);
1464 4acb54ba Edgar E. Iglesias
    tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
1465 4acb54ba Edgar E. Iglesias
}
1466 4acb54ba Edgar E. Iglesias
1467 97694c57 Edgar E. Iglesias
static int dec_check_fpuv2(DisasContext *dc)
1468 97694c57 Edgar E. Iglesias
{
1469 97694c57 Edgar E. Iglesias
    int r;
1470 97694c57 Edgar E. Iglesias
1471 97694c57 Edgar E. Iglesias
    r = dc->env->pvr.regs[2] & PVR2_USE_FPU2_MASK;
1472 97694c57 Edgar E. Iglesias
1473 97694c57 Edgar E. Iglesias
    if (!r && (dc->tb_flags & MSR_EE_FLAG)) {
1474 97694c57 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
1475 97694c57 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1476 97694c57 Edgar E. Iglesias
    }
1477 97694c57 Edgar E. Iglesias
    return r;
1478 97694c57 Edgar E. Iglesias
}
1479 97694c57 Edgar E. Iglesias
1480 1567a005 Edgar E. Iglesias
static void dec_fpu(DisasContext *dc)
1481 1567a005 Edgar E. Iglesias
{
1482 97694c57 Edgar E. Iglesias
    unsigned int fpu_insn;
1483 97694c57 Edgar E. Iglesias
1484 1567a005 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1485 97f90cbf Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1486 1567a005 Edgar E. Iglesias
          && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
1487 97694c57 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1488 1567a005 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1489 1567a005 Edgar E. Iglesias
        return;
1490 1567a005 Edgar E. Iglesias
    }
1491 1567a005 Edgar E. Iglesias
1492 97694c57 Edgar E. Iglesias
    fpu_insn = (dc->ir >> 7) & 7;
1493 97694c57 Edgar E. Iglesias
1494 97694c57 Edgar E. Iglesias
    switch (fpu_insn) {
1495 97694c57 Edgar E. Iglesias
        case 0:
1496 97694c57 Edgar E. Iglesias
            gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
1497 97694c57 Edgar E. Iglesias
            break;
1498 97694c57 Edgar E. Iglesias
1499 97694c57 Edgar E. Iglesias
        case 1:
1500 97694c57 Edgar E. Iglesias
            gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
1501 97694c57 Edgar E. Iglesias
            break;
1502 97694c57 Edgar E. Iglesias
1503 97694c57 Edgar E. Iglesias
        case 2:
1504 97694c57 Edgar E. Iglesias
            gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
1505 97694c57 Edgar E. Iglesias
            break;
1506 97694c57 Edgar E. Iglesias
1507 97694c57 Edgar E. Iglesias
        case 3:
1508 97694c57 Edgar E. Iglesias
            gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
1509 97694c57 Edgar E. Iglesias
            break;
1510 97694c57 Edgar E. Iglesias
1511 97694c57 Edgar E. Iglesias
        case 4:
1512 97694c57 Edgar E. Iglesias
            switch ((dc->ir >> 4) & 7) {
1513 97694c57 Edgar E. Iglesias
                case 0:
1514 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_un(cpu_R[dc->rd],
1515 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1516 97694c57 Edgar E. Iglesias
                    break;
1517 97694c57 Edgar E. Iglesias
                case 1:
1518 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_lt(cpu_R[dc->rd],
1519 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1520 97694c57 Edgar E. Iglesias
                    break;
1521 97694c57 Edgar E. Iglesias
                case 2:
1522 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_eq(cpu_R[dc->rd],
1523 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1524 97694c57 Edgar E. Iglesias
                    break;
1525 97694c57 Edgar E. Iglesias
                case 3:
1526 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_le(cpu_R[dc->rd],
1527 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1528 97694c57 Edgar E. Iglesias
                    break;
1529 97694c57 Edgar E. Iglesias
                case 4:
1530 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_gt(cpu_R[dc->rd],
1531 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1532 97694c57 Edgar E. Iglesias
                    break;
1533 97694c57 Edgar E. Iglesias
                case 5:
1534 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_ne(cpu_R[dc->rd],
1535 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1536 97694c57 Edgar E. Iglesias
                    break;
1537 97694c57 Edgar E. Iglesias
                case 6:
1538 97694c57 Edgar E. Iglesias
                    gen_helper_fcmp_ge(cpu_R[dc->rd],
1539 97694c57 Edgar E. Iglesias
                                       cpu_R[dc->ra], cpu_R[dc->rb]);
1540 97694c57 Edgar E. Iglesias
                    break;
1541 97694c57 Edgar E. Iglesias
                default:
1542 71547a3b Blue Swirl
                    qemu_log_mask(LOG_UNIMP,
1543 71547a3b Blue Swirl
                                  "unimplemented fcmp fpu_insn=%x pc=%x"
1544 71547a3b Blue Swirl
                                  " opc=%x\n",
1545 71547a3b Blue Swirl
                                  fpu_insn, dc->pc, dc->opcode);
1546 97694c57 Edgar E. Iglesias
                    dc->abort_at_next_insn = 1;
1547 97694c57 Edgar E. Iglesias
                    break;
1548 97694c57 Edgar E. Iglesias
            }
1549 97694c57 Edgar E. Iglesias
            break;
1550 97694c57 Edgar E. Iglesias
1551 97694c57 Edgar E. Iglesias
        case 5:
1552 97694c57 Edgar E. Iglesias
            if (!dec_check_fpuv2(dc)) {
1553 97694c57 Edgar E. Iglesias
                return;
1554 97694c57 Edgar E. Iglesias
            }
1555 97694c57 Edgar E. Iglesias
            gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]);
1556 97694c57 Edgar E. Iglesias
            break;
1557 97694c57 Edgar E. Iglesias
1558 97694c57 Edgar E. Iglesias
        case 6:
1559 97694c57 Edgar E. Iglesias
            if (!dec_check_fpuv2(dc)) {
1560 97694c57 Edgar E. Iglesias
                return;
1561 97694c57 Edgar E. Iglesias
            }
1562 97694c57 Edgar E. Iglesias
            gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]);
1563 97694c57 Edgar E. Iglesias
            break;
1564 97694c57 Edgar E. Iglesias
1565 97694c57 Edgar E. Iglesias
        case 7:
1566 97694c57 Edgar E. Iglesias
            if (!dec_check_fpuv2(dc)) {
1567 97694c57 Edgar E. Iglesias
                return;
1568 97694c57 Edgar E. Iglesias
            }
1569 97694c57 Edgar E. Iglesias
            gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]);
1570 97694c57 Edgar E. Iglesias
            break;
1571 97694c57 Edgar E. Iglesias
1572 97694c57 Edgar E. Iglesias
        default:
1573 71547a3b Blue Swirl
            qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x"
1574 71547a3b Blue Swirl
                          " opc=%x\n",
1575 71547a3b Blue Swirl
                          fpu_insn, dc->pc, dc->opcode);
1576 97694c57 Edgar E. Iglesias
            dc->abort_at_next_insn = 1;
1577 97694c57 Edgar E. Iglesias
            break;
1578 97694c57 Edgar E. Iglesias
    }
1579 1567a005 Edgar E. Iglesias
}
1580 1567a005 Edgar E. Iglesias
1581 4acb54ba Edgar E. Iglesias
static void dec_null(DisasContext *dc)
1582 4acb54ba Edgar E. Iglesias
{
1583 02b33596 Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG)
1584 02b33596 Edgar E. Iglesias
          && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
1585 02b33596 Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1586 02b33596 Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1587 02b33596 Edgar E. Iglesias
        return;
1588 02b33596 Edgar E. Iglesias
    }
1589 4acb54ba Edgar E. Iglesias
    qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
1590 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 1;
1591 4acb54ba Edgar E. Iglesias
}
1592 4acb54ba Edgar E. Iglesias
1593 6d76d23e Edgar E. Iglesias
/* Insns connected to FSL or AXI stream attached devices.  */
1594 6d76d23e Edgar E. Iglesias
static void dec_stream(DisasContext *dc)
1595 6d76d23e Edgar E. Iglesias
{
1596 6d76d23e Edgar E. Iglesias
    int mem_index = cpu_mmu_index(dc->env);
1597 6d76d23e Edgar E. Iglesias
    TCGv_i32 t_id, t_ctrl;
1598 6d76d23e Edgar E. Iglesias
    int ctrl;
1599 6d76d23e Edgar E. Iglesias
1600 6d76d23e Edgar E. Iglesias
    LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put",
1601 6d76d23e Edgar E. Iglesias
            dc->type_b ? "" : "d", dc->imm);
1602 6d76d23e Edgar E. Iglesias
1603 6d76d23e Edgar E. Iglesias
    if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) {
1604 6d76d23e Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN);
1605 6d76d23e Edgar E. Iglesias
        t_gen_raise_exception(dc, EXCP_HW_EXCP);
1606 6d76d23e Edgar E. Iglesias
        return;
1607 6d76d23e Edgar E. Iglesias
    }
1608 6d76d23e Edgar E. Iglesias
1609 6d76d23e Edgar E. Iglesias
    t_id = tcg_temp_new();
1610 6d76d23e Edgar E. Iglesias
    if (dc->type_b) {
1611 6d76d23e Edgar E. Iglesias
        tcg_gen_movi_tl(t_id, dc->imm & 0xf);
1612 6d76d23e Edgar E. Iglesias
        ctrl = dc->imm >> 10;
1613 6d76d23e Edgar E. Iglesias
    } else {
1614 6d76d23e Edgar E. Iglesias
        tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf);
1615 6d76d23e Edgar E. Iglesias
        ctrl = dc->imm >> 5;
1616 6d76d23e Edgar E. Iglesias
    }
1617 6d76d23e Edgar E. Iglesias
1618 6d76d23e Edgar E. Iglesias
    t_ctrl = tcg_const_tl(ctrl);
1619 6d76d23e Edgar E. Iglesias
1620 6d76d23e Edgar E. Iglesias
    if (dc->rd == 0) {
1621 6d76d23e Edgar E. Iglesias
        gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]);
1622 6d76d23e Edgar E. Iglesias
    } else {
1623 6d76d23e Edgar E. Iglesias
        gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl);
1624 6d76d23e Edgar E. Iglesias
    }
1625 6d76d23e Edgar E. Iglesias
    tcg_temp_free(t_id);
1626 6d76d23e Edgar E. Iglesias
    tcg_temp_free(t_ctrl);
1627 6d76d23e Edgar E. Iglesias
}
1628 6d76d23e Edgar E. Iglesias
1629 4acb54ba Edgar E. Iglesias
static struct decoder_info {
1630 4acb54ba Edgar E. Iglesias
    struct {
1631 4acb54ba Edgar E. Iglesias
        uint32_t bits;
1632 4acb54ba Edgar E. Iglesias
        uint32_t mask;
1633 4acb54ba Edgar E. Iglesias
    };
1634 4acb54ba Edgar E. Iglesias
    void (*dec)(DisasContext *dc);
1635 4acb54ba Edgar E. Iglesias
} decinfo[] = {
1636 4acb54ba Edgar E. Iglesias
    {DEC_ADD, dec_add},
1637 4acb54ba Edgar E. Iglesias
    {DEC_SUB, dec_sub},
1638 4acb54ba Edgar E. Iglesias
    {DEC_AND, dec_and},
1639 4acb54ba Edgar E. Iglesias
    {DEC_XOR, dec_xor},
1640 4acb54ba Edgar E. Iglesias
    {DEC_OR, dec_or},
1641 4acb54ba Edgar E. Iglesias
    {DEC_BIT, dec_bit},
1642 4acb54ba Edgar E. Iglesias
    {DEC_BARREL, dec_barrel},
1643 4acb54ba Edgar E. Iglesias
    {DEC_LD, dec_load},
1644 4acb54ba Edgar E. Iglesias
    {DEC_ST, dec_store},
1645 4acb54ba Edgar E. Iglesias
    {DEC_IMM, dec_imm},
1646 4acb54ba Edgar E. Iglesias
    {DEC_BR, dec_br},
1647 4acb54ba Edgar E. Iglesias
    {DEC_BCC, dec_bcc},
1648 4acb54ba Edgar E. Iglesias
    {DEC_RTS, dec_rts},
1649 1567a005 Edgar E. Iglesias
    {DEC_FPU, dec_fpu},
1650 4acb54ba Edgar E. Iglesias
    {DEC_MUL, dec_mul},
1651 4acb54ba Edgar E. Iglesias
    {DEC_DIV, dec_div},
1652 4acb54ba Edgar E. Iglesias
    {DEC_MSR, dec_msr},
1653 6d76d23e Edgar E. Iglesias
    {DEC_STREAM, dec_stream},
1654 4acb54ba Edgar E. Iglesias
    {{0, 0}, dec_null}
1655 4acb54ba Edgar E. Iglesias
};
1656 4acb54ba Edgar E. Iglesias
1657 4acb54ba Edgar E. Iglesias
static inline void decode(DisasContext *dc)
1658 4acb54ba Edgar E. Iglesias
{
1659 4acb54ba Edgar E. Iglesias
    uint32_t ir;
1660 4acb54ba Edgar E. Iglesias
    int i;
1661 4acb54ba Edgar E. Iglesias
1662 4acb54ba Edgar E. Iglesias
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
1663 4acb54ba Edgar E. Iglesias
        tcg_gen_debug_insn_start(dc->pc);
1664 4acb54ba Edgar E. Iglesias
1665 4acb54ba Edgar E. Iglesias
    dc->ir = ir = ldl_code(dc->pc);
1666 4acb54ba Edgar E. Iglesias
    LOG_DIS("%8.8x\t", dc->ir);
1667 4acb54ba Edgar E. Iglesias
1668 4acb54ba Edgar E. Iglesias
    if (dc->ir)
1669 4acb54ba Edgar E. Iglesias
        dc->nr_nops = 0;
1670 4acb54ba Edgar E. Iglesias
    else {
1671 1567a005 Edgar E. Iglesias
        if ((dc->tb_flags & MSR_EE_FLAG)
1672 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
1673 97f90cbf Edgar E. Iglesias
              && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
1674 1567a005 Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
1675 1567a005 Edgar E. Iglesias
            t_gen_raise_exception(dc, EXCP_HW_EXCP);
1676 1567a005 Edgar E. Iglesias
            return;
1677 1567a005 Edgar E. Iglesias
        }
1678 1567a005 Edgar E. Iglesias
1679 4acb54ba Edgar E. Iglesias
        LOG_DIS("nr_nops=%d\t", dc->nr_nops);
1680 4acb54ba Edgar E. Iglesias
        dc->nr_nops++;
1681 4acb54ba Edgar E. Iglesias
        if (dc->nr_nops > 4)
1682 4acb54ba Edgar E. Iglesias
            cpu_abort(dc->env, "fetching nop sequence\n");
1683 4acb54ba Edgar E. Iglesias
    }
1684 4acb54ba Edgar E. Iglesias
    /* bit 2 seems to indicate insn type.  */
1685 4acb54ba Edgar E. Iglesias
    dc->type_b = ir & (1 << 29);
1686 4acb54ba Edgar E. Iglesias
1687 4acb54ba Edgar E. Iglesias
    dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1688 4acb54ba Edgar E. Iglesias
    dc->rd = EXTRACT_FIELD(ir, 21, 25);
1689 4acb54ba Edgar E. Iglesias
    dc->ra = EXTRACT_FIELD(ir, 16, 20);
1690 4acb54ba Edgar E. Iglesias
    dc->rb = EXTRACT_FIELD(ir, 11, 15);
1691 4acb54ba Edgar E. Iglesias
    dc->imm = EXTRACT_FIELD(ir, 0, 15);
1692 4acb54ba Edgar E. Iglesias
1693 4acb54ba Edgar E. Iglesias
    /* Large switch for all insns.  */
1694 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
1695 4acb54ba Edgar E. Iglesias
        if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
1696 4acb54ba Edgar E. Iglesias
            decinfo[i].dec(dc);
1697 4acb54ba Edgar E. Iglesias
            break;
1698 4acb54ba Edgar E. Iglesias
        }
1699 4acb54ba Edgar E. Iglesias
    }
1700 4acb54ba Edgar E. Iglesias
}
1701 4acb54ba Edgar E. Iglesias
1702 68cee38a Andreas Färber
static void check_breakpoint(CPUMBState *env, DisasContext *dc)
1703 4acb54ba Edgar E. Iglesias
{
1704 4acb54ba Edgar E. Iglesias
    CPUBreakpoint *bp;
1705 4acb54ba Edgar E. Iglesias
1706 72cf2d4f Blue Swirl
    if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
1707 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
1708 4acb54ba Edgar E. Iglesias
            if (bp->pc == dc->pc) {
1709 4acb54ba Edgar E. Iglesias
                t_gen_raise_exception(dc, EXCP_DEBUG);
1710 4acb54ba Edgar E. Iglesias
                dc->is_jmp = DISAS_UPDATE;
1711 4acb54ba Edgar E. Iglesias
             }
1712 4acb54ba Edgar E. Iglesias
        }
1713 4acb54ba Edgar E. Iglesias
    }
1714 4acb54ba Edgar E. Iglesias
}
1715 4acb54ba Edgar E. Iglesias
1716 4acb54ba Edgar E. Iglesias
/* generate intermediate code for basic block 'tb'.  */
1717 4acb54ba Edgar E. Iglesias
static void
1718 68cee38a Andreas Färber
gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
1719 4acb54ba Edgar E. Iglesias
                               int search_pc)
1720 4acb54ba Edgar E. Iglesias
{
1721 4acb54ba Edgar E. Iglesias
    uint16_t *gen_opc_end;
1722 4acb54ba Edgar E. Iglesias
    uint32_t pc_start;
1723 4acb54ba Edgar E. Iglesias
    int j, lj;
1724 4acb54ba Edgar E. Iglesias
    struct DisasContext ctx;
1725 4acb54ba Edgar E. Iglesias
    struct DisasContext *dc = &ctx;
1726 4acb54ba Edgar E. Iglesias
    uint32_t next_page_start, org_flags;
1727 4acb54ba Edgar E. Iglesias
    target_ulong npc;
1728 4acb54ba Edgar E. Iglesias
    int num_insns;
1729 4acb54ba Edgar E. Iglesias
    int max_insns;
1730 4acb54ba Edgar E. Iglesias
1731 4acb54ba Edgar E. Iglesias
    qemu_log_try_set_file(stderr);
1732 4acb54ba Edgar E. Iglesias
1733 4acb54ba Edgar E. Iglesias
    pc_start = tb->pc;
1734 4acb54ba Edgar E. Iglesias
    dc->env = env;
1735 4acb54ba Edgar E. Iglesias
    dc->tb = tb;
1736 4acb54ba Edgar E. Iglesias
    org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
1737 4acb54ba Edgar E. Iglesias
1738 4acb54ba Edgar E. Iglesias
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1739 4acb54ba Edgar E. Iglesias
1740 4acb54ba Edgar E. Iglesias
    dc->is_jmp = DISAS_NEXT;
1741 4acb54ba Edgar E. Iglesias
    dc->jmp = 0;
1742 4acb54ba Edgar E. Iglesias
    dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
1743 23979dc5 Edgar E. Iglesias
    if (dc->delayed_branch) {
1744 23979dc5 Edgar E. Iglesias
        dc->jmp = JMP_INDIRECT;
1745 23979dc5 Edgar E. Iglesias
    }
1746 4acb54ba Edgar E. Iglesias
    dc->pc = pc_start;
1747 4acb54ba Edgar E. Iglesias
    dc->singlestep_enabled = env->singlestep_enabled;
1748 4acb54ba Edgar E. Iglesias
    dc->cpustate_changed = 0;
1749 4acb54ba Edgar E. Iglesias
    dc->abort_at_next_insn = 0;
1750 4acb54ba Edgar E. Iglesias
    dc->nr_nops = 0;
1751 4acb54ba Edgar E. Iglesias
1752 4acb54ba Edgar E. Iglesias
    if (pc_start & 3)
1753 4acb54ba Edgar E. Iglesias
        cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
1754 4acb54ba Edgar E. Iglesias
1755 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1756 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1757 4acb54ba Edgar E. Iglesias
        qemu_log("--------------\n");
1758 4acb54ba Edgar E. Iglesias
        log_cpu_state(env, 0);
1759 4acb54ba Edgar E. Iglesias
#endif
1760 4acb54ba Edgar E. Iglesias
    }
1761 4acb54ba Edgar E. Iglesias
1762 4acb54ba Edgar E. Iglesias
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
1763 4acb54ba Edgar E. Iglesias
    lj = -1;
1764 4acb54ba Edgar E. Iglesias
    num_insns = 0;
1765 4acb54ba Edgar E. Iglesias
    max_insns = tb->cflags & CF_COUNT_MASK;
1766 4acb54ba Edgar E. Iglesias
    if (max_insns == 0)
1767 4acb54ba Edgar E. Iglesias
        max_insns = CF_COUNT_MASK;
1768 4acb54ba Edgar E. Iglesias
1769 4acb54ba Edgar E. Iglesias
    gen_icount_start();
1770 4acb54ba Edgar E. Iglesias
    do
1771 4acb54ba Edgar E. Iglesias
    {
1772 4acb54ba Edgar E. Iglesias
#if SIM_COMPAT
1773 4acb54ba Edgar E. Iglesias
        if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1774 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
1775 4acb54ba Edgar E. Iglesias
            gen_helper_debug();
1776 4acb54ba Edgar E. Iglesias
        }
1777 4acb54ba Edgar E. Iglesias
#endif
1778 4acb54ba Edgar E. Iglesias
        check_breakpoint(env, dc);
1779 4acb54ba Edgar E. Iglesias
1780 4acb54ba Edgar E. Iglesias
        if (search_pc) {
1781 4acb54ba Edgar E. Iglesias
            j = gen_opc_ptr - gen_opc_buf;
1782 4acb54ba Edgar E. Iglesias
            if (lj < j) {
1783 4acb54ba Edgar E. Iglesias
                lj++;
1784 4acb54ba Edgar E. Iglesias
                while (lj < j)
1785 4acb54ba Edgar E. Iglesias
                    gen_opc_instr_start[lj++] = 0;
1786 4acb54ba Edgar E. Iglesias
            }
1787 4acb54ba Edgar E. Iglesias
            gen_opc_pc[lj] = dc->pc;
1788 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj] = 1;
1789 4acb54ba Edgar E. Iglesias
                        gen_opc_icount[lj] = num_insns;
1790 4acb54ba Edgar E. Iglesias
        }
1791 4acb54ba Edgar E. Iglesias
1792 4acb54ba Edgar E. Iglesias
        /* Pretty disas.  */
1793 4acb54ba Edgar E. Iglesias
        LOG_DIS("%8.8x:\t", dc->pc);
1794 4acb54ba Edgar E. Iglesias
1795 4acb54ba Edgar E. Iglesias
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1796 4acb54ba Edgar E. Iglesias
            gen_io_start();
1797 4acb54ba Edgar E. Iglesias
1798 4acb54ba Edgar E. Iglesias
        dc->clear_imm = 1;
1799 4acb54ba Edgar E. Iglesias
        decode(dc);
1800 4acb54ba Edgar E. Iglesias
        if (dc->clear_imm)
1801 4acb54ba Edgar E. Iglesias
            dc->tb_flags &= ~IMM_FLAG;
1802 4acb54ba Edgar E. Iglesias
        dc->pc += 4;
1803 4acb54ba Edgar E. Iglesias
        num_insns++;
1804 4acb54ba Edgar E. Iglesias
1805 4acb54ba Edgar E. Iglesias
        if (dc->delayed_branch) {
1806 4acb54ba Edgar E. Iglesias
            dc->delayed_branch--;
1807 4acb54ba Edgar E. Iglesias
            if (!dc->delayed_branch) {
1808 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTI_FLAG)
1809 4acb54ba Edgar E. Iglesias
                    do_rti(dc);
1810 4acb54ba Edgar E. Iglesias
                 if (dc->tb_flags & DRTB_FLAG)
1811 4acb54ba Edgar E. Iglesias
                    do_rtb(dc);
1812 4acb54ba Edgar E. Iglesias
                if (dc->tb_flags & DRTE_FLAG)
1813 4acb54ba Edgar E. Iglesias
                    do_rte(dc);
1814 4acb54ba Edgar E. Iglesias
                /* Clear the delay slot flag.  */
1815 4acb54ba Edgar E. Iglesias
                dc->tb_flags &= ~D_FLAG;
1816 4acb54ba Edgar E. Iglesias
                /* If it is a direct jump, try direct chaining.  */
1817 23979dc5 Edgar E. Iglesias
                if (dc->jmp == JMP_INDIRECT) {
1818 4acb54ba Edgar E. Iglesias
                    eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
1819 4acb54ba Edgar E. Iglesias
                    dc->is_jmp = DISAS_JUMP;
1820 23979dc5 Edgar E. Iglesias
                } else if (dc->jmp == JMP_DIRECT) {
1821 844bab60 Edgar E. Iglesias
                    t_sync_flags(dc);
1822 844bab60 Edgar E. Iglesias
                    gen_goto_tb(dc, 0, dc->jmp_pc);
1823 844bab60 Edgar E. Iglesias
                    dc->is_jmp = DISAS_TB_JUMP;
1824 844bab60 Edgar E. Iglesias
                } else if (dc->jmp == JMP_DIRECT_CC) {
1825 23979dc5 Edgar E. Iglesias
                    int l1;
1826 23979dc5 Edgar E. Iglesias
1827 23979dc5 Edgar E. Iglesias
                    t_sync_flags(dc);
1828 23979dc5 Edgar E. Iglesias
                    l1 = gen_new_label();
1829 23979dc5 Edgar E. Iglesias
                    /* Conditional jmp.  */
1830 23979dc5 Edgar E. Iglesias
                    tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
1831 23979dc5 Edgar E. Iglesias
                    gen_goto_tb(dc, 1, dc->pc);
1832 23979dc5 Edgar E. Iglesias
                    gen_set_label(l1);
1833 23979dc5 Edgar E. Iglesias
                    gen_goto_tb(dc, 0, dc->jmp_pc);
1834 23979dc5 Edgar E. Iglesias
1835 23979dc5 Edgar E. Iglesias
                    dc->is_jmp = DISAS_TB_JUMP;
1836 4acb54ba Edgar E. Iglesias
                }
1837 4acb54ba Edgar E. Iglesias
                break;
1838 4acb54ba Edgar E. Iglesias
            }
1839 4acb54ba Edgar E. Iglesias
        }
1840 4acb54ba Edgar E. Iglesias
        if (env->singlestep_enabled)
1841 4acb54ba Edgar E. Iglesias
            break;
1842 4acb54ba Edgar E. Iglesias
    } while (!dc->is_jmp && !dc->cpustate_changed
1843 4acb54ba Edgar E. Iglesias
         && gen_opc_ptr < gen_opc_end
1844 4acb54ba Edgar E. Iglesias
                 && !singlestep
1845 4acb54ba Edgar E. Iglesias
         && (dc->pc < next_page_start)
1846 4acb54ba Edgar E. Iglesias
                 && num_insns < max_insns);
1847 4acb54ba Edgar E. Iglesias
1848 4acb54ba Edgar E. Iglesias
    npc = dc->pc;
1849 844bab60 Edgar E. Iglesias
    if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
1850 4acb54ba Edgar E. Iglesias
        if (dc->tb_flags & D_FLAG) {
1851 4acb54ba Edgar E. Iglesias
            dc->is_jmp = DISAS_UPDATE;
1852 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1853 4acb54ba Edgar E. Iglesias
            sync_jmpstate(dc);
1854 4acb54ba Edgar E. Iglesias
        } else
1855 4acb54ba Edgar E. Iglesias
            npc = dc->jmp_pc;
1856 4acb54ba Edgar E. Iglesias
    }
1857 4acb54ba Edgar E. Iglesias
1858 4acb54ba Edgar E. Iglesias
    if (tb->cflags & CF_LAST_IO)
1859 4acb54ba Edgar E. Iglesias
        gen_io_end();
1860 4acb54ba Edgar E. Iglesias
    /* Force an update if the per-tb cpu state has changed.  */
1861 4acb54ba Edgar E. Iglesias
    if (dc->is_jmp == DISAS_NEXT
1862 4acb54ba Edgar E. Iglesias
        && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
1863 4acb54ba Edgar E. Iglesias
        dc->is_jmp = DISAS_UPDATE;
1864 4acb54ba Edgar E. Iglesias
        tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1865 4acb54ba Edgar E. Iglesias
    }
1866 4acb54ba Edgar E. Iglesias
    t_sync_flags(dc);
1867 4acb54ba Edgar E. Iglesias
1868 4acb54ba Edgar E. Iglesias
    if (unlikely(env->singlestep_enabled)) {
1869 6c5f738d Edgar E. Iglesias
        TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
1870 6c5f738d Edgar E. Iglesias
1871 6c5f738d Edgar E. Iglesias
        if (dc->is_jmp != DISAS_JUMP) {
1872 4acb54ba Edgar E. Iglesias
            tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
1873 6c5f738d Edgar E. Iglesias
        }
1874 6c5f738d Edgar E. Iglesias
        gen_helper_raise_exception(tmp);
1875 6c5f738d Edgar E. Iglesias
        tcg_temp_free_i32(tmp);
1876 4acb54ba Edgar E. Iglesias
    } else {
1877 4acb54ba Edgar E. Iglesias
        switch(dc->is_jmp) {
1878 4acb54ba Edgar E. Iglesias
            case DISAS_NEXT:
1879 4acb54ba Edgar E. Iglesias
                gen_goto_tb(dc, 1, npc);
1880 4acb54ba Edgar E. Iglesias
                break;
1881 4acb54ba Edgar E. Iglesias
            default:
1882 4acb54ba Edgar E. Iglesias
            case DISAS_JUMP:
1883 4acb54ba Edgar E. Iglesias
            case DISAS_UPDATE:
1884 4acb54ba Edgar E. Iglesias
                /* indicate that the hash table must be used
1885 4acb54ba Edgar E. Iglesias
                   to find the next TB */
1886 4acb54ba Edgar E. Iglesias
                tcg_gen_exit_tb(0);
1887 4acb54ba Edgar E. Iglesias
                break;
1888 4acb54ba Edgar E. Iglesias
            case DISAS_TB_JUMP:
1889 4acb54ba Edgar E. Iglesias
                /* nothing more to generate */
1890 4acb54ba Edgar E. Iglesias
                break;
1891 4acb54ba Edgar E. Iglesias
        }
1892 4acb54ba Edgar E. Iglesias
    }
1893 4acb54ba Edgar E. Iglesias
    gen_icount_end(tb, num_insns);
1894 4acb54ba Edgar E. Iglesias
    *gen_opc_ptr = INDEX_op_end;
1895 4acb54ba Edgar E. Iglesias
    if (search_pc) {
1896 4acb54ba Edgar E. Iglesias
        j = gen_opc_ptr - gen_opc_buf;
1897 4acb54ba Edgar E. Iglesias
        lj++;
1898 4acb54ba Edgar E. Iglesias
        while (lj <= j)
1899 4acb54ba Edgar E. Iglesias
            gen_opc_instr_start[lj++] = 0;
1900 4acb54ba Edgar E. Iglesias
    } else {
1901 4acb54ba Edgar E. Iglesias
        tb->size = dc->pc - pc_start;
1902 4acb54ba Edgar E. Iglesias
                tb->icount = num_insns;
1903 4acb54ba Edgar E. Iglesias
    }
1904 4acb54ba Edgar E. Iglesias
1905 4acb54ba Edgar E. Iglesias
#ifdef DEBUG_DISAS
1906 4acb54ba Edgar E. Iglesias
#if !SIM_COMPAT
1907 4acb54ba Edgar E. Iglesias
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1908 4acb54ba Edgar E. Iglesias
        qemu_log("\n");
1909 4acb54ba Edgar E. Iglesias
#if DISAS_GNU
1910 4acb54ba Edgar E. Iglesias
        log_target_disas(pc_start, dc->pc - pc_start, 0);
1911 4acb54ba Edgar E. Iglesias
#endif
1912 e6aa0f11 Stefan Weil
        qemu_log("\nisize=%d osize=%td\n",
1913 4acb54ba Edgar E. Iglesias
            dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
1914 4acb54ba Edgar E. Iglesias
    }
1915 4acb54ba Edgar E. Iglesias
#endif
1916 4acb54ba Edgar E. Iglesias
#endif
1917 4acb54ba Edgar E. Iglesias
    assert(!dc->abort_at_next_insn);
1918 4acb54ba Edgar E. Iglesias
}
1919 4acb54ba Edgar E. Iglesias
1920 68cee38a Andreas Färber
void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
1921 4acb54ba Edgar E. Iglesias
{
1922 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 0);
1923 4acb54ba Edgar E. Iglesias
}
1924 4acb54ba Edgar E. Iglesias
1925 68cee38a Andreas Färber
void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
1926 4acb54ba Edgar E. Iglesias
{
1927 4acb54ba Edgar E. Iglesias
    gen_intermediate_code_internal(env, tb, 1);
1928 4acb54ba Edgar E. Iglesias
}
1929 4acb54ba Edgar E. Iglesias
1930 68cee38a Andreas Färber
void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf,
1931 4acb54ba Edgar E. Iglesias
                     int flags)
1932 4acb54ba Edgar E. Iglesias
{
1933 4acb54ba Edgar E. Iglesias
    int i;
1934 4acb54ba Edgar E. Iglesias
1935 4acb54ba Edgar E. Iglesias
    if (!env || !f)
1936 4acb54ba Edgar E. Iglesias
        return;
1937 4acb54ba Edgar E. Iglesias
1938 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "IN: PC=%x %s\n",
1939 4acb54ba Edgar E. Iglesias
                env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
1940 97694c57 Edgar E. Iglesias
    cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n",
1941 4c24aa0a Michal Simek
             env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
1942 97694c57 Edgar E. Iglesias
             env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
1943 17c52a43 Edgar E. Iglesias
    cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
1944 4acb54ba Edgar E. Iglesias
             env->btaken, env->btarget,
1945 4acb54ba Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
1946 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
1947 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_EIP),
1948 17c52a43 Edgar E. Iglesias
             (env->sregs[SR_MSR] & MSR_IE));
1949 17c52a43 Edgar E. Iglesias
1950 4acb54ba Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
1951 4acb54ba Edgar E. Iglesias
        cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1952 4acb54ba Edgar E. Iglesias
        if ((i + 1) % 4 == 0)
1953 4acb54ba Edgar E. Iglesias
            cpu_fprintf(f, "\n");
1954 4acb54ba Edgar E. Iglesias
        }
1955 4acb54ba Edgar E. Iglesias
    cpu_fprintf(f, "\n\n");
1956 4acb54ba Edgar E. Iglesias
}
1957 4acb54ba Edgar E. Iglesias
1958 b33ab1f7 Andreas Färber
MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
1959 4acb54ba Edgar E. Iglesias
{
1960 b77f98ca Andreas Färber
    MicroBlazeCPU *cpu;
1961 4acb54ba Edgar E. Iglesias
    static int tcg_initialized = 0;
1962 4acb54ba Edgar E. Iglesias
    int i;
1963 4acb54ba Edgar E. Iglesias
1964 b77f98ca Andreas Färber
    cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
1965 4acb54ba Edgar E. Iglesias
1966 61b6208f Andreas Färber
    cpu_reset(CPU(cpu));
1967 b33ab1f7 Andreas Färber
    qemu_init_vcpu(&cpu->env);
1968 4acb54ba Edgar E. Iglesias
1969 b33ab1f7 Andreas Färber
    if (tcg_initialized) {
1970 b33ab1f7 Andreas Färber
        return cpu;
1971 b33ab1f7 Andreas Färber
    }
1972 4acb54ba Edgar E. Iglesias
1973 4acb54ba Edgar E. Iglesias
    tcg_initialized = 1;
1974 4acb54ba Edgar E. Iglesias
1975 4acb54ba Edgar E. Iglesias
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1976 4acb54ba Edgar E. Iglesias
1977 4acb54ba Edgar E. Iglesias
    env_debug = tcg_global_mem_new(TCG_AREG0, 
1978 68cee38a Andreas Färber
                    offsetof(CPUMBState, debug),
1979 4acb54ba Edgar E. Iglesias
                    "debug0");
1980 4acb54ba Edgar E. Iglesias
    env_iflags = tcg_global_mem_new(TCG_AREG0, 
1981 68cee38a Andreas Färber
                    offsetof(CPUMBState, iflags),
1982 4acb54ba Edgar E. Iglesias
                    "iflags");
1983 4acb54ba Edgar E. Iglesias
    env_imm = tcg_global_mem_new(TCG_AREG0, 
1984 68cee38a Andreas Färber
                    offsetof(CPUMBState, imm),
1985 4acb54ba Edgar E. Iglesias
                    "imm");
1986 4acb54ba Edgar E. Iglesias
    env_btarget = tcg_global_mem_new(TCG_AREG0,
1987 68cee38a Andreas Färber
                     offsetof(CPUMBState, btarget),
1988 4acb54ba Edgar E. Iglesias
                     "btarget");
1989 4acb54ba Edgar E. Iglesias
    env_btaken = tcg_global_mem_new(TCG_AREG0,
1990 68cee38a Andreas Färber
                     offsetof(CPUMBState, btaken),
1991 4acb54ba Edgar E. Iglesias
                     "btaken");
1992 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1993 4acb54ba Edgar E. Iglesias
        cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
1994 68cee38a Andreas Färber
                          offsetof(CPUMBState, regs[i]),
1995 4acb54ba Edgar E. Iglesias
                          regnames[i]);
1996 4acb54ba Edgar E. Iglesias
    }
1997 4acb54ba Edgar E. Iglesias
    for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
1998 4acb54ba Edgar E. Iglesias
        cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
1999 68cee38a Andreas Färber
                          offsetof(CPUMBState, sregs[i]),
2000 4acb54ba Edgar E. Iglesias
                          special_regnames[i]);
2001 4acb54ba Edgar E. Iglesias
    }
2002 4acb54ba Edgar E. Iglesias
#define GEN_HELPER 2
2003 4acb54ba Edgar E. Iglesias
#include "helper.h"
2004 4acb54ba Edgar E. Iglesias
2005 b33ab1f7 Andreas Färber
    return cpu;
2006 4acb54ba Edgar E. Iglesias
}
2007 4acb54ba Edgar E. Iglesias
2008 68cee38a Andreas Färber
void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
2009 4acb54ba Edgar E. Iglesias
{
2010 4acb54ba Edgar E. Iglesias
    env->sregs[SR_PC] = gen_opc_pc[pc_pos];
2011 4acb54ba Edgar E. Iglesias
}