Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 50d3eeae

History | View | Annotate | Download (77.5 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  ARM translation
3 2c0262af bellard
 * 
4 2c0262af bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 b7bcbe95 bellard
 *  Copyright (c) 2005 CodeSourcery, LLC
6 2c0262af bellard
 *
7 2c0262af bellard
 * This library is free software; you can redistribute it and/or
8 2c0262af bellard
 * modify it under the terms of the GNU Lesser General Public
9 2c0262af bellard
 * License as published by the Free Software Foundation; either
10 2c0262af bellard
 * version 2 of the License, or (at your option) any later version.
11 2c0262af bellard
 *
12 2c0262af bellard
 * This library is distributed in the hope that it will be useful,
13 2c0262af bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 2c0262af bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 2c0262af bellard
 * Lesser General Public License for more details.
16 2c0262af bellard
 *
17 2c0262af bellard
 * You should have received a copy of the GNU Lesser General Public
18 2c0262af bellard
 * License along with this library; if not, write to the Free Software
19 2c0262af bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 2c0262af bellard
 */
21 2c0262af bellard
#include <stdarg.h>
22 2c0262af bellard
#include <stdlib.h>
23 2c0262af bellard
#include <stdio.h>
24 2c0262af bellard
#include <string.h>
25 2c0262af bellard
#include <inttypes.h>
26 2c0262af bellard
27 2c0262af bellard
#include "cpu.h"
28 2c0262af bellard
#include "exec-all.h"
29 2c0262af bellard
#include "disas.h"
30 2c0262af bellard
31 b5ff1b31 bellard
#define ENABLE_ARCH_5J  0
32 b5ff1b31 bellard
#define ENABLE_ARCH_6   1
33 b5ff1b31 bellard
#define ENABLE_ARCH_6T2 1
34 b5ff1b31 bellard
35 b5ff1b31 bellard
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
36 b5ff1b31 bellard
37 2c0262af bellard
/* internal defines */
38 2c0262af bellard
typedef struct DisasContext {
39 0fa85d43 bellard
    target_ulong pc;
40 2c0262af bellard
    int is_jmp;
41 e50e6a20 bellard
    /* Nonzero if this instruction has been conditionally skipped.  */
42 e50e6a20 bellard
    int condjmp;
43 e50e6a20 bellard
    /* The label that will be jumped to when the instruction is skipped.  */
44 e50e6a20 bellard
    int condlabel;
45 2c0262af bellard
    struct TranslationBlock *tb;
46 8aaca4c0 bellard
    int singlestep_enabled;
47 5899f386 bellard
    int thumb;
48 6658ffb8 pbrook
    int is_mem;
49 b5ff1b31 bellard
#if !defined(CONFIG_USER_ONLY)
50 b5ff1b31 bellard
    int user;
51 b5ff1b31 bellard
#endif
52 2c0262af bellard
} DisasContext;
53 2c0262af bellard
54 b5ff1b31 bellard
#if defined(CONFIG_USER_ONLY)
55 b5ff1b31 bellard
#define IS_USER(s) 1
56 b5ff1b31 bellard
#else
57 b5ff1b31 bellard
#define IS_USER(s) (s->user)
58 b5ff1b31 bellard
#endif
59 b5ff1b31 bellard
60 2c0262af bellard
#define DISAS_JUMP_NEXT 4
61 2c0262af bellard
62 c53be334 bellard
#ifdef USE_DIRECT_JUMP
63 c53be334 bellard
#define TBPARAM(x)
64 c53be334 bellard
#else
65 c53be334 bellard
#define TBPARAM(x) (long)(x)
66 c53be334 bellard
#endif
67 c53be334 bellard
68 2c0262af bellard
/* XXX: move that elsewhere */
69 2c0262af bellard
static uint16_t *gen_opc_ptr;
70 2c0262af bellard
static uint32_t *gen_opparam_ptr;
71 2c0262af bellard
extern FILE *logfile;
72 2c0262af bellard
extern int loglevel;
73 2c0262af bellard
74 2c0262af bellard
enum {
75 2c0262af bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
76 2c0262af bellard
#include "opc.h"
77 2c0262af bellard
#undef DEF
78 2c0262af bellard
    NB_OPS,
79 2c0262af bellard
};
80 2c0262af bellard
81 2c0262af bellard
#include "gen-op.h"
82 2c0262af bellard
83 e50e6a20 bellard
static GenOpFunc1 *gen_test_cc[14] = {
84 2c0262af bellard
    gen_op_test_eq,
85 2c0262af bellard
    gen_op_test_ne,
86 2c0262af bellard
    gen_op_test_cs,
87 2c0262af bellard
    gen_op_test_cc,
88 2c0262af bellard
    gen_op_test_mi,
89 2c0262af bellard
    gen_op_test_pl,
90 2c0262af bellard
    gen_op_test_vs,
91 2c0262af bellard
    gen_op_test_vc,
92 2c0262af bellard
    gen_op_test_hi,
93 2c0262af bellard
    gen_op_test_ls,
94 2c0262af bellard
    gen_op_test_ge,
95 2c0262af bellard
    gen_op_test_lt,
96 2c0262af bellard
    gen_op_test_gt,
97 2c0262af bellard
    gen_op_test_le,
98 2c0262af bellard
};
99 2c0262af bellard
100 2c0262af bellard
const uint8_t table_logic_cc[16] = {
101 2c0262af bellard
    1, /* and */
102 2c0262af bellard
    1, /* xor */
103 2c0262af bellard
    0, /* sub */
104 2c0262af bellard
    0, /* rsb */
105 2c0262af bellard
    0, /* add */
106 2c0262af bellard
    0, /* adc */
107 2c0262af bellard
    0, /* sbc */
108 2c0262af bellard
    0, /* rsc */
109 2c0262af bellard
    1, /* andl */
110 2c0262af bellard
    1, /* xorl */
111 2c0262af bellard
    0, /* cmp */
112 2c0262af bellard
    0, /* cmn */
113 2c0262af bellard
    1, /* orr */
114 2c0262af bellard
    1, /* mov */
115 2c0262af bellard
    1, /* bic */
116 2c0262af bellard
    1, /* mvn */
117 2c0262af bellard
};
118 2c0262af bellard
    
119 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im[4] = {
120 2c0262af bellard
    gen_op_shll_T1_im,
121 2c0262af bellard
    gen_op_shrl_T1_im,
122 2c0262af bellard
    gen_op_sarl_T1_im,
123 2c0262af bellard
    gen_op_rorl_T1_im,
124 2c0262af bellard
};
125 2c0262af bellard
126 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0[4] = {
127 1e8d4eec bellard
    NULL,
128 1e8d4eec bellard
    gen_op_shrl_T1_0,
129 1e8d4eec bellard
    gen_op_sarl_T1_0,
130 1e8d4eec bellard
    gen_op_rrxl_T1,
131 1e8d4eec bellard
};
132 1e8d4eec bellard
133 2c0262af bellard
static GenOpFunc1 *gen_shift_T2_im[4] = {
134 2c0262af bellard
    gen_op_shll_T2_im,
135 2c0262af bellard
    gen_op_shrl_T2_im,
136 2c0262af bellard
    gen_op_sarl_T2_im,
137 2c0262af bellard
    gen_op_rorl_T2_im,
138 2c0262af bellard
};
139 2c0262af bellard
140 1e8d4eec bellard
static GenOpFunc *gen_shift_T2_0[4] = {
141 1e8d4eec bellard
    NULL,
142 1e8d4eec bellard
    gen_op_shrl_T2_0,
143 1e8d4eec bellard
    gen_op_sarl_T2_0,
144 1e8d4eec bellard
    gen_op_rrxl_T2,
145 1e8d4eec bellard
};
146 1e8d4eec bellard
147 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
148 2c0262af bellard
    gen_op_shll_T1_im_cc,
149 2c0262af bellard
    gen_op_shrl_T1_im_cc,
150 2c0262af bellard
    gen_op_sarl_T1_im_cc,
151 2c0262af bellard
    gen_op_rorl_T1_im_cc,
152 2c0262af bellard
};
153 2c0262af bellard
154 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0_cc[4] = {
155 1e8d4eec bellard
    NULL,
156 1e8d4eec bellard
    gen_op_shrl_T1_0_cc,
157 1e8d4eec bellard
    gen_op_sarl_T1_0_cc,
158 1e8d4eec bellard
    gen_op_rrxl_T1_cc,
159 1e8d4eec bellard
};
160 1e8d4eec bellard
161 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0[4] = {
162 2c0262af bellard
    gen_op_shll_T1_T0,
163 2c0262af bellard
    gen_op_shrl_T1_T0,
164 2c0262af bellard
    gen_op_sarl_T1_T0,
165 2c0262af bellard
    gen_op_rorl_T1_T0,
166 2c0262af bellard
};
167 2c0262af bellard
168 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
169 2c0262af bellard
    gen_op_shll_T1_T0_cc,
170 2c0262af bellard
    gen_op_shrl_T1_T0_cc,
171 2c0262af bellard
    gen_op_sarl_T1_T0_cc,
172 2c0262af bellard
    gen_op_rorl_T1_T0_cc,
173 2c0262af bellard
};
174 2c0262af bellard
175 2c0262af bellard
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
176 2c0262af bellard
    {
177 2c0262af bellard
        gen_op_movl_T0_r0,
178 2c0262af bellard
        gen_op_movl_T0_r1,
179 2c0262af bellard
        gen_op_movl_T0_r2,
180 2c0262af bellard
        gen_op_movl_T0_r3,
181 2c0262af bellard
        gen_op_movl_T0_r4,
182 2c0262af bellard
        gen_op_movl_T0_r5,
183 2c0262af bellard
        gen_op_movl_T0_r6,
184 2c0262af bellard
        gen_op_movl_T0_r7,
185 2c0262af bellard
        gen_op_movl_T0_r8,
186 2c0262af bellard
        gen_op_movl_T0_r9,
187 2c0262af bellard
        gen_op_movl_T0_r10,
188 2c0262af bellard
        gen_op_movl_T0_r11,
189 2c0262af bellard
        gen_op_movl_T0_r12,
190 2c0262af bellard
        gen_op_movl_T0_r13,
191 2c0262af bellard
        gen_op_movl_T0_r14,
192 2c0262af bellard
        gen_op_movl_T0_r15,
193 2c0262af bellard
    },
194 2c0262af bellard
    {
195 2c0262af bellard
        gen_op_movl_T1_r0,
196 2c0262af bellard
        gen_op_movl_T1_r1,
197 2c0262af bellard
        gen_op_movl_T1_r2,
198 2c0262af bellard
        gen_op_movl_T1_r3,
199 2c0262af bellard
        gen_op_movl_T1_r4,
200 2c0262af bellard
        gen_op_movl_T1_r5,
201 2c0262af bellard
        gen_op_movl_T1_r6,
202 2c0262af bellard
        gen_op_movl_T1_r7,
203 2c0262af bellard
        gen_op_movl_T1_r8,
204 2c0262af bellard
        gen_op_movl_T1_r9,
205 2c0262af bellard
        gen_op_movl_T1_r10,
206 2c0262af bellard
        gen_op_movl_T1_r11,
207 2c0262af bellard
        gen_op_movl_T1_r12,
208 2c0262af bellard
        gen_op_movl_T1_r13,
209 2c0262af bellard
        gen_op_movl_T1_r14,
210 2c0262af bellard
        gen_op_movl_T1_r15,
211 2c0262af bellard
    },
212 2c0262af bellard
    {
213 2c0262af bellard
        gen_op_movl_T2_r0,
214 2c0262af bellard
        gen_op_movl_T2_r1,
215 2c0262af bellard
        gen_op_movl_T2_r2,
216 2c0262af bellard
        gen_op_movl_T2_r3,
217 2c0262af bellard
        gen_op_movl_T2_r4,
218 2c0262af bellard
        gen_op_movl_T2_r5,
219 2c0262af bellard
        gen_op_movl_T2_r6,
220 2c0262af bellard
        gen_op_movl_T2_r7,
221 2c0262af bellard
        gen_op_movl_T2_r8,
222 2c0262af bellard
        gen_op_movl_T2_r9,
223 2c0262af bellard
        gen_op_movl_T2_r10,
224 2c0262af bellard
        gen_op_movl_T2_r11,
225 2c0262af bellard
        gen_op_movl_T2_r12,
226 2c0262af bellard
        gen_op_movl_T2_r13,
227 2c0262af bellard
        gen_op_movl_T2_r14,
228 2c0262af bellard
        gen_op_movl_T2_r15,
229 2c0262af bellard
    },
230 2c0262af bellard
};
231 2c0262af bellard
232 2c0262af bellard
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
233 2c0262af bellard
    {
234 2c0262af bellard
        gen_op_movl_r0_T0,
235 2c0262af bellard
        gen_op_movl_r1_T0,
236 2c0262af bellard
        gen_op_movl_r2_T0,
237 2c0262af bellard
        gen_op_movl_r3_T0,
238 2c0262af bellard
        gen_op_movl_r4_T0,
239 2c0262af bellard
        gen_op_movl_r5_T0,
240 2c0262af bellard
        gen_op_movl_r6_T0,
241 2c0262af bellard
        gen_op_movl_r7_T0,
242 2c0262af bellard
        gen_op_movl_r8_T0,
243 2c0262af bellard
        gen_op_movl_r9_T0,
244 2c0262af bellard
        gen_op_movl_r10_T0,
245 2c0262af bellard
        gen_op_movl_r11_T0,
246 2c0262af bellard
        gen_op_movl_r12_T0,
247 2c0262af bellard
        gen_op_movl_r13_T0,
248 2c0262af bellard
        gen_op_movl_r14_T0,
249 2c0262af bellard
        gen_op_movl_r15_T0,
250 2c0262af bellard
    },
251 2c0262af bellard
    {
252 2c0262af bellard
        gen_op_movl_r0_T1,
253 2c0262af bellard
        gen_op_movl_r1_T1,
254 2c0262af bellard
        gen_op_movl_r2_T1,
255 2c0262af bellard
        gen_op_movl_r3_T1,
256 2c0262af bellard
        gen_op_movl_r4_T1,
257 2c0262af bellard
        gen_op_movl_r5_T1,
258 2c0262af bellard
        gen_op_movl_r6_T1,
259 2c0262af bellard
        gen_op_movl_r7_T1,
260 2c0262af bellard
        gen_op_movl_r8_T1,
261 2c0262af bellard
        gen_op_movl_r9_T1,
262 2c0262af bellard
        gen_op_movl_r10_T1,
263 2c0262af bellard
        gen_op_movl_r11_T1,
264 2c0262af bellard
        gen_op_movl_r12_T1,
265 2c0262af bellard
        gen_op_movl_r13_T1,
266 2c0262af bellard
        gen_op_movl_r14_T1,
267 2c0262af bellard
        gen_op_movl_r15_T1,
268 2c0262af bellard
    },
269 2c0262af bellard
};
270 2c0262af bellard
271 2c0262af bellard
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
272 2c0262af bellard
    gen_op_movl_T0_im,
273 2c0262af bellard
    gen_op_movl_T1_im,
274 2c0262af bellard
    gen_op_movl_T2_im,
275 2c0262af bellard
};
276 2c0262af bellard
277 99c475ab bellard
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
278 99c475ab bellard
    gen_op_shll_T0_im_thumb,
279 99c475ab bellard
    gen_op_shrl_T0_im_thumb,
280 99c475ab bellard
    gen_op_sarl_T0_im_thumb,
281 99c475ab bellard
};
282 99c475ab bellard
283 99c475ab bellard
static inline void gen_bx(DisasContext *s)
284 99c475ab bellard
{
285 99c475ab bellard
  s->is_jmp = DISAS_UPDATE;
286 99c475ab bellard
  gen_op_bx_T0();
287 99c475ab bellard
}
288 99c475ab bellard
289 b5ff1b31 bellard
290 b5ff1b31 bellard
#if defined(CONFIG_USER_ONLY)
291 b5ff1b31 bellard
#define gen_ldst(name, s) gen_op_##name##_raw()
292 b5ff1b31 bellard
#else
293 b5ff1b31 bellard
#define gen_ldst(name, s) do { \
294 6658ffb8 pbrook
    s->is_mem = 1; \
295 b5ff1b31 bellard
    if (IS_USER(s)) \
296 b5ff1b31 bellard
        gen_op_##name##_user(); \
297 b5ff1b31 bellard
    else \
298 b5ff1b31 bellard
        gen_op_##name##_kernel(); \
299 b5ff1b31 bellard
    } while (0)
300 b5ff1b31 bellard
#endif
301 b5ff1b31 bellard
302 2c0262af bellard
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
303 2c0262af bellard
{
304 2c0262af bellard
    int val;
305 2c0262af bellard
306 2c0262af bellard
    if (reg == 15) {
307 5899f386 bellard
        /* normaly, since we updated PC, we need only to add one insn */
308 5899f386 bellard
        if (s->thumb)
309 5899f386 bellard
            val = (long)s->pc + 2;
310 5899f386 bellard
        else
311 5899f386 bellard
            val = (long)s->pc + 4;
312 2c0262af bellard
        gen_op_movl_TN_im[t](val);
313 2c0262af bellard
    } else {
314 2c0262af bellard
        gen_op_movl_TN_reg[t][reg]();
315 2c0262af bellard
    }
316 2c0262af bellard
}
317 2c0262af bellard
318 2c0262af bellard
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
319 2c0262af bellard
{
320 2c0262af bellard
    gen_movl_TN_reg(s, reg, 0);
321 2c0262af bellard
}
322 2c0262af bellard
323 2c0262af bellard
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
324 2c0262af bellard
{
325 2c0262af bellard
    gen_movl_TN_reg(s, reg, 1);
326 2c0262af bellard
}
327 2c0262af bellard
328 2c0262af bellard
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
329 2c0262af bellard
{
330 2c0262af bellard
    gen_movl_TN_reg(s, reg, 2);
331 2c0262af bellard
}
332 2c0262af bellard
333 2c0262af bellard
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
334 2c0262af bellard
{
335 2c0262af bellard
    gen_op_movl_reg_TN[t][reg]();
336 2c0262af bellard
    if (reg == 15) {
337 2c0262af bellard
        s->is_jmp = DISAS_JUMP;
338 2c0262af bellard
    }
339 2c0262af bellard
}
340 2c0262af bellard
341 2c0262af bellard
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
342 2c0262af bellard
{
343 2c0262af bellard
    gen_movl_reg_TN(s, reg, 0);
344 2c0262af bellard
}
345 2c0262af bellard
346 2c0262af bellard
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
347 2c0262af bellard
{
348 2c0262af bellard
    gen_movl_reg_TN(s, reg, 1);
349 2c0262af bellard
}
350 2c0262af bellard
351 b5ff1b31 bellard
/* Force a TB lookup after an instruction that changes the CPU state.  */
352 b5ff1b31 bellard
static inline void gen_lookup_tb(DisasContext *s)
353 b5ff1b31 bellard
{
354 b5ff1b31 bellard
    gen_op_movl_T0_im(s->pc);
355 b5ff1b31 bellard
    gen_movl_reg_T0(s, 15);
356 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
357 b5ff1b31 bellard
}
358 b5ff1b31 bellard
359 2c0262af bellard
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
360 2c0262af bellard
{
361 1e8d4eec bellard
    int val, rm, shift, shiftop;
362 2c0262af bellard
363 2c0262af bellard
    if (!(insn & (1 << 25))) {
364 2c0262af bellard
        /* immediate */
365 2c0262af bellard
        val = insn & 0xfff;
366 2c0262af bellard
        if (!(insn & (1 << 23)))
367 2c0262af bellard
            val = -val;
368 537730b9 bellard
        if (val != 0)
369 537730b9 bellard
            gen_op_addl_T1_im(val);
370 2c0262af bellard
    } else {
371 2c0262af bellard
        /* shift/register */
372 2c0262af bellard
        rm = (insn) & 0xf;
373 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
374 2c0262af bellard
        gen_movl_T2_reg(s, rm);
375 1e8d4eec bellard
        shiftop = (insn >> 5) & 3;
376 2c0262af bellard
        if (shift != 0) {
377 1e8d4eec bellard
            gen_shift_T2_im[shiftop](shift);
378 1e8d4eec bellard
        } else if (shiftop != 0) {
379 1e8d4eec bellard
            gen_shift_T2_0[shiftop]();
380 2c0262af bellard
        }
381 2c0262af bellard
        if (!(insn & (1 << 23)))
382 2c0262af bellard
            gen_op_subl_T1_T2();
383 2c0262af bellard
        else
384 2c0262af bellard
            gen_op_addl_T1_T2();
385 2c0262af bellard
    }
386 2c0262af bellard
}
387 2c0262af bellard
388 191f9a93 pbrook
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
389 191f9a93 pbrook
                                        int extra)
390 2c0262af bellard
{
391 2c0262af bellard
    int val, rm;
392 2c0262af bellard
    
393 2c0262af bellard
    if (insn & (1 << 22)) {
394 2c0262af bellard
        /* immediate */
395 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
396 2c0262af bellard
        if (!(insn & (1 << 23)))
397 2c0262af bellard
            val = -val;
398 18acad92 pbrook
        val += extra;
399 537730b9 bellard
        if (val != 0)
400 537730b9 bellard
            gen_op_addl_T1_im(val);
401 2c0262af bellard
    } else {
402 2c0262af bellard
        /* register */
403 191f9a93 pbrook
        if (extra)
404 191f9a93 pbrook
            gen_op_addl_T1_im(extra);
405 2c0262af bellard
        rm = (insn) & 0xf;
406 2c0262af bellard
        gen_movl_T2_reg(s, rm);
407 2c0262af bellard
        if (!(insn & (1 << 23)))
408 2c0262af bellard
            gen_op_subl_T1_T2();
409 2c0262af bellard
        else
410 2c0262af bellard
            gen_op_addl_T1_T2();
411 2c0262af bellard
    }
412 2c0262af bellard
}
413 2c0262af bellard
414 b7bcbe95 bellard
#define VFP_OP(name)                      \
415 b7bcbe95 bellard
static inline void gen_vfp_##name(int dp) \
416 b7bcbe95 bellard
{                                         \
417 b7bcbe95 bellard
    if (dp)                               \
418 b7bcbe95 bellard
        gen_op_vfp_##name##d();           \
419 b7bcbe95 bellard
    else                                  \
420 b7bcbe95 bellard
        gen_op_vfp_##name##s();           \
421 b7bcbe95 bellard
}
422 b7bcbe95 bellard
423 b7bcbe95 bellard
VFP_OP(add)
424 b7bcbe95 bellard
VFP_OP(sub)
425 b7bcbe95 bellard
VFP_OP(mul)
426 b7bcbe95 bellard
VFP_OP(div)
427 b7bcbe95 bellard
VFP_OP(neg)
428 b7bcbe95 bellard
VFP_OP(abs)
429 b7bcbe95 bellard
VFP_OP(sqrt)
430 b7bcbe95 bellard
VFP_OP(cmp)
431 b7bcbe95 bellard
VFP_OP(cmpe)
432 b7bcbe95 bellard
VFP_OP(F1_ld0)
433 b7bcbe95 bellard
VFP_OP(uito)
434 b7bcbe95 bellard
VFP_OP(sito)
435 b7bcbe95 bellard
VFP_OP(toui)
436 b7bcbe95 bellard
VFP_OP(touiz)
437 b7bcbe95 bellard
VFP_OP(tosi)
438 b7bcbe95 bellard
VFP_OP(tosiz)
439 b7bcbe95 bellard
440 b7bcbe95 bellard
#undef VFP_OP
441 b7bcbe95 bellard
442 b5ff1b31 bellard
static inline void gen_vfp_ld(DisasContext *s, int dp)
443 b5ff1b31 bellard
{
444 b5ff1b31 bellard
    if (dp)
445 b5ff1b31 bellard
        gen_ldst(vfp_ldd, s);
446 b5ff1b31 bellard
    else
447 b5ff1b31 bellard
        gen_ldst(vfp_lds, s);
448 b5ff1b31 bellard
}
449 b5ff1b31 bellard
450 b5ff1b31 bellard
static inline void gen_vfp_st(DisasContext *s, int dp)
451 b5ff1b31 bellard
{
452 b5ff1b31 bellard
    if (dp)
453 b5ff1b31 bellard
        gen_ldst(vfp_std, s);
454 b5ff1b31 bellard
    else
455 b5ff1b31 bellard
        gen_ldst(vfp_sts, s);
456 b5ff1b31 bellard
}
457 b5ff1b31 bellard
458 8e96005d bellard
static inline long
459 8e96005d bellard
vfp_reg_offset (int dp, int reg)
460 8e96005d bellard
{
461 8e96005d bellard
    if (dp)
462 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg]);
463 8e96005d bellard
    else if (reg & 1) {
464 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
465 8e96005d bellard
          + offsetof(CPU_DoubleU, l.upper);
466 8e96005d bellard
    } else {
467 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
468 8e96005d bellard
          + offsetof(CPU_DoubleU, l.lower);
469 8e96005d bellard
    }
470 8e96005d bellard
}
471 b7bcbe95 bellard
static inline void gen_mov_F0_vreg(int dp, int reg)
472 b7bcbe95 bellard
{
473 b7bcbe95 bellard
    if (dp)
474 8e96005d bellard
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
475 b7bcbe95 bellard
    else
476 8e96005d bellard
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
477 b7bcbe95 bellard
}
478 b7bcbe95 bellard
479 b7bcbe95 bellard
static inline void gen_mov_F1_vreg(int dp, int reg)
480 b7bcbe95 bellard
{
481 b7bcbe95 bellard
    if (dp)
482 8e96005d bellard
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
483 b7bcbe95 bellard
    else
484 8e96005d bellard
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
485 b7bcbe95 bellard
}
486 b7bcbe95 bellard
487 b7bcbe95 bellard
static inline void gen_mov_vreg_F0(int dp, int reg)
488 b7bcbe95 bellard
{
489 b7bcbe95 bellard
    if (dp)
490 8e96005d bellard
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
491 b7bcbe95 bellard
    else
492 8e96005d bellard
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
493 b7bcbe95 bellard
}
494 b7bcbe95 bellard
495 b5ff1b31 bellard
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
496 b5ff1b31 bellard
   instruction is not defined.  */
497 b5ff1b31 bellard
static int disas_cp15_insn(DisasContext *s, uint32_t insn)
498 b5ff1b31 bellard
{
499 b5ff1b31 bellard
    uint32_t rd;
500 b5ff1b31 bellard
501 b5ff1b31 bellard
    /* ??? Some cp15 registers are accessible from userspace.  */
502 b5ff1b31 bellard
    if (IS_USER(s)) {
503 b5ff1b31 bellard
        return 1;
504 b5ff1b31 bellard
    }
505 9332f9da bellard
    if ((insn & 0x0fff0fff) == 0x0e070f90
506 9332f9da bellard
        || (insn & 0x0fff0fff) == 0x0e070f58) {
507 9332f9da bellard
        /* Wait for interrupt.  */
508 9332f9da bellard
        gen_op_movl_T0_im((long)s->pc);
509 9332f9da bellard
        gen_op_movl_reg_TN[0][15]();
510 9332f9da bellard
        gen_op_wfi();
511 9332f9da bellard
        s->is_jmp = DISAS_JUMP;
512 9332f9da bellard
        return 0;
513 9332f9da bellard
    }
514 b5ff1b31 bellard
    rd = (insn >> 12) & 0xf;
515 b5ff1b31 bellard
    if (insn & (1 << 20)) {
516 b5ff1b31 bellard
        gen_op_movl_T0_cp15(insn);
517 b5ff1b31 bellard
        /* If the destination register is r15 then sets condition codes.  */
518 b5ff1b31 bellard
        if (rd != 15)
519 b5ff1b31 bellard
            gen_movl_reg_T0(s, rd);
520 b5ff1b31 bellard
    } else {
521 b5ff1b31 bellard
        gen_movl_T0_reg(s, rd);
522 b5ff1b31 bellard
        gen_op_movl_cp15_T0(insn);
523 b5ff1b31 bellard
    }
524 b5ff1b31 bellard
    gen_lookup_tb(s);
525 b5ff1b31 bellard
    return 0;
526 b5ff1b31 bellard
}
527 b5ff1b31 bellard
528 b7bcbe95 bellard
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
529 b7bcbe95 bellard
   (ie. an undefined instruction).  */
530 b7bcbe95 bellard
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
531 b7bcbe95 bellard
{
532 b7bcbe95 bellard
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
533 b7bcbe95 bellard
    int dp, veclen;
534 b7bcbe95 bellard
535 40f137e1 pbrook
    if (!arm_feature(env, ARM_FEATURE_VFP))
536 40f137e1 pbrook
        return 1;
537 40f137e1 pbrook
538 40f137e1 pbrook
    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
539 40f137e1 pbrook
        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */
540 40f137e1 pbrook
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
541 40f137e1 pbrook
            return 1;
542 40f137e1 pbrook
        rn = (insn >> 16) & 0xf;
543 40f137e1 pbrook
        if (rn != 0 && rn != 8)
544 40f137e1 pbrook
            return 1;
545 40f137e1 pbrook
    }
546 b7bcbe95 bellard
    dp = ((insn & 0xf00) == 0xb00);
547 b7bcbe95 bellard
    switch ((insn >> 24) & 0xf) {
548 b7bcbe95 bellard
    case 0xe:
549 b7bcbe95 bellard
        if (insn & (1 << 4)) {
550 b7bcbe95 bellard
            /* single register transfer */
551 b7bcbe95 bellard
            if ((insn & 0x6f) != 0x00)
552 b7bcbe95 bellard
                return 1;
553 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
554 b7bcbe95 bellard
            if (dp) {
555 b7bcbe95 bellard
                if (insn & 0x80)
556 b7bcbe95 bellard
                    return 1;
557 b7bcbe95 bellard
                rn = (insn >> 16) & 0xf;
558 b7bcbe95 bellard
                /* Get the existing value even for arm->vfp moves because
559 b7bcbe95 bellard
                   we only set half the register.  */
560 b7bcbe95 bellard
                gen_mov_F0_vreg(1, rn);
561 b7bcbe95 bellard
                gen_op_vfp_mrrd();
562 b7bcbe95 bellard
                if (insn & (1 << 20)) {
563 b7bcbe95 bellard
                    /* vfp->arm */
564 b7bcbe95 bellard
                    if (insn & (1 << 21))
565 b7bcbe95 bellard
                        gen_movl_reg_T1(s, rd);
566 b7bcbe95 bellard
                    else
567 b7bcbe95 bellard
                        gen_movl_reg_T0(s, rd);
568 b7bcbe95 bellard
                } else {
569 b7bcbe95 bellard
                    /* arm->vfp */
570 b7bcbe95 bellard
                    if (insn & (1 << 21))
571 b7bcbe95 bellard
                        gen_movl_T1_reg(s, rd);
572 b7bcbe95 bellard
                    else
573 b7bcbe95 bellard
                        gen_movl_T0_reg(s, rd);
574 b7bcbe95 bellard
                    gen_op_vfp_mdrr();
575 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rn);
576 b7bcbe95 bellard
                }
577 b7bcbe95 bellard
            } else {
578 b7bcbe95 bellard
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
579 b7bcbe95 bellard
                if (insn & (1 << 20)) {
580 b7bcbe95 bellard
                    /* vfp->arm */
581 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
582 b7bcbe95 bellard
                        /* system register */
583 40f137e1 pbrook
                        rn >>= 1;
584 b7bcbe95 bellard
                        switch (rn) {
585 40f137e1 pbrook
                        case ARM_VFP_FPSID:
586 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
587 40f137e1 pbrook
                        case ARM_VFP_FPINST:
588 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
589 40f137e1 pbrook
                            gen_op_vfp_movl_T0_xreg(rn);
590 b7bcbe95 bellard
                            break;
591 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
592 b7bcbe95 bellard
                            if (rd == 15)
593 b7bcbe95 bellard
                                gen_op_vfp_movl_T0_fpscr_flags();
594 b7bcbe95 bellard
                            else
595 b7bcbe95 bellard
                                gen_op_vfp_movl_T0_fpscr();
596 b7bcbe95 bellard
                            break;
597 b7bcbe95 bellard
                        default:
598 b7bcbe95 bellard
                            return 1;
599 b7bcbe95 bellard
                        }
600 b7bcbe95 bellard
                    } else {
601 b7bcbe95 bellard
                        gen_mov_F0_vreg(0, rn);
602 b7bcbe95 bellard
                        gen_op_vfp_mrs();
603 b7bcbe95 bellard
                    }
604 b7bcbe95 bellard
                    if (rd == 15) {
605 b5ff1b31 bellard
                        /* Set the 4 flag bits in the CPSR.  */
606 b5ff1b31 bellard
                        gen_op_movl_cpsr_T0(0xf0000000);
607 b7bcbe95 bellard
                    } else
608 b7bcbe95 bellard
                        gen_movl_reg_T0(s, rd);
609 b7bcbe95 bellard
                } else {
610 b7bcbe95 bellard
                    /* arm->vfp */
611 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
612 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
613 40f137e1 pbrook
                        rn >>= 1;
614 b7bcbe95 bellard
                        /* system register */
615 b7bcbe95 bellard
                        switch (rn) {
616 40f137e1 pbrook
                        case ARM_VFP_FPSID:
617 b7bcbe95 bellard
                            /* Writes are ignored.  */
618 b7bcbe95 bellard
                            break;
619 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
620 b7bcbe95 bellard
                            gen_op_vfp_movl_fpscr_T0();
621 b5ff1b31 bellard
                            gen_lookup_tb(s);
622 b7bcbe95 bellard
                            break;
623 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
624 40f137e1 pbrook
                            gen_op_vfp_movl_xreg_T0(rn);
625 40f137e1 pbrook
                            gen_lookup_tb(s);
626 40f137e1 pbrook
                            break;
627 40f137e1 pbrook
                        case ARM_VFP_FPINST:
628 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
629 40f137e1 pbrook
                            gen_op_vfp_movl_xreg_T0(rn);
630 40f137e1 pbrook
                            break;
631 b7bcbe95 bellard
                        default:
632 b7bcbe95 bellard
                            return 1;
633 b7bcbe95 bellard
                        }
634 b7bcbe95 bellard
                    } else {
635 b7bcbe95 bellard
                        gen_op_vfp_msr();
636 b7bcbe95 bellard
                        gen_mov_vreg_F0(0, rn);
637 b7bcbe95 bellard
                    }
638 b7bcbe95 bellard
                }
639 b7bcbe95 bellard
            }
640 b7bcbe95 bellard
        } else {
641 b7bcbe95 bellard
            /* data processing */
642 b7bcbe95 bellard
            /* The opcode is in bits 23, 21, 20 and 6.  */
643 b7bcbe95 bellard
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
644 b7bcbe95 bellard
            if (dp) {
645 b7bcbe95 bellard
                if (op == 15) {
646 b7bcbe95 bellard
                    /* rn is opcode */
647 b7bcbe95 bellard
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
648 b7bcbe95 bellard
                } else {
649 b7bcbe95 bellard
                    /* rn is register number */
650 b7bcbe95 bellard
                    if (insn & (1 << 7))
651 b7bcbe95 bellard
                        return 1;
652 b7bcbe95 bellard
                    rn = (insn >> 16) & 0xf;
653 b7bcbe95 bellard
                }
654 b7bcbe95 bellard
655 b7bcbe95 bellard
                if (op == 15 && (rn == 15 || rn > 17)) {
656 b7bcbe95 bellard
                    /* Integer or single precision destination.  */
657 b7bcbe95 bellard
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
658 b7bcbe95 bellard
                } else {
659 b7bcbe95 bellard
                    if (insn & (1 << 22))
660 b7bcbe95 bellard
                        return 1;
661 b7bcbe95 bellard
                    rd = (insn >> 12) & 0xf;
662 b7bcbe95 bellard
                }
663 b7bcbe95 bellard
664 b7bcbe95 bellard
                if (op == 15 && (rn == 16 || rn == 17)) {
665 b7bcbe95 bellard
                    /* Integer source.  */
666 b7bcbe95 bellard
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
667 b7bcbe95 bellard
                } else {
668 b7bcbe95 bellard
                    if (insn & (1 << 5))
669 b7bcbe95 bellard
                        return 1;
670 b7bcbe95 bellard
                    rm = insn & 0xf;
671 b7bcbe95 bellard
                }
672 b7bcbe95 bellard
            } else {
673 b7bcbe95 bellard
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
674 b7bcbe95 bellard
                if (op == 15 && rn == 15) {
675 b7bcbe95 bellard
                    /* Double precision destination.  */
676 b7bcbe95 bellard
                    if (insn & (1 << 22))
677 b7bcbe95 bellard
                        return 1;
678 b7bcbe95 bellard
                    rd = (insn >> 12) & 0xf;
679 b7bcbe95 bellard
                } else
680 b7bcbe95 bellard
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
681 b7bcbe95 bellard
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
682 b7bcbe95 bellard
            }
683 b7bcbe95 bellard
684 b7bcbe95 bellard
            veclen = env->vfp.vec_len;
685 b7bcbe95 bellard
            if (op == 15 && rn > 3)
686 b7bcbe95 bellard
                veclen = 0;
687 b7bcbe95 bellard
688 b7bcbe95 bellard
            /* Shut up compiler warnings.  */
689 b7bcbe95 bellard
            delta_m = 0;
690 b7bcbe95 bellard
            delta_d = 0;
691 b7bcbe95 bellard
            bank_mask = 0;
692 b7bcbe95 bellard
            
693 b7bcbe95 bellard
            if (veclen > 0) {
694 b7bcbe95 bellard
                if (dp)
695 b7bcbe95 bellard
                    bank_mask = 0xc;
696 b7bcbe95 bellard
                else
697 b7bcbe95 bellard
                    bank_mask = 0x18;
698 b7bcbe95 bellard
699 b7bcbe95 bellard
                /* Figure out what type of vector operation this is.  */
700 b7bcbe95 bellard
                if ((rd & bank_mask) == 0) {
701 b7bcbe95 bellard
                    /* scalar */
702 b7bcbe95 bellard
                    veclen = 0;
703 b7bcbe95 bellard
                } else {
704 b7bcbe95 bellard
                    if (dp)
705 b7bcbe95 bellard
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
706 b7bcbe95 bellard
                    else
707 b7bcbe95 bellard
                        delta_d = env->vfp.vec_stride + 1;
708 b7bcbe95 bellard
709 b7bcbe95 bellard
                    if ((rm & bank_mask) == 0) {
710 b7bcbe95 bellard
                        /* mixed scalar/vector */
711 b7bcbe95 bellard
                        delta_m = 0;
712 b7bcbe95 bellard
                    } else {
713 b7bcbe95 bellard
                        /* vector */
714 b7bcbe95 bellard
                        delta_m = delta_d;
715 b7bcbe95 bellard
                    }
716 b7bcbe95 bellard
                }
717 b7bcbe95 bellard
            }
718 b7bcbe95 bellard
719 b7bcbe95 bellard
            /* Load the initial operands.  */
720 b7bcbe95 bellard
            if (op == 15) {
721 b7bcbe95 bellard
                switch (rn) {
722 b7bcbe95 bellard
                case 16:
723 b7bcbe95 bellard
                case 17:
724 b7bcbe95 bellard
                    /* Integer source */
725 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
726 b7bcbe95 bellard
                    break;
727 b7bcbe95 bellard
                case 8:
728 b7bcbe95 bellard
                case 9:
729 b7bcbe95 bellard
                    /* Compare */
730 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
731 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rm);
732 b7bcbe95 bellard
                    break;
733 b7bcbe95 bellard
                case 10:
734 b7bcbe95 bellard
                case 11:
735 b7bcbe95 bellard
                    /* Compare with zero */
736 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
737 b7bcbe95 bellard
                    gen_vfp_F1_ld0(dp);
738 b7bcbe95 bellard
                    break;
739 b7bcbe95 bellard
                default:
740 b7bcbe95 bellard
                    /* One source operand.  */
741 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
742 b7bcbe95 bellard
                }
743 b7bcbe95 bellard
            } else {
744 b7bcbe95 bellard
                /* Two source operands.  */
745 b7bcbe95 bellard
                gen_mov_F0_vreg(dp, rn);
746 b7bcbe95 bellard
                gen_mov_F1_vreg(dp, rm);
747 b7bcbe95 bellard
            }
748 b7bcbe95 bellard
749 b7bcbe95 bellard
            for (;;) {
750 b7bcbe95 bellard
                /* Perform the calculation.  */
751 b7bcbe95 bellard
                switch (op) {
752 b7bcbe95 bellard
                case 0: /* mac: fd + (fn * fm) */
753 b7bcbe95 bellard
                    gen_vfp_mul(dp);
754 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
755 b7bcbe95 bellard
                    gen_vfp_add(dp);
756 b7bcbe95 bellard
                    break;
757 b7bcbe95 bellard
                case 1: /* nmac: fd - (fn * fm) */
758 b7bcbe95 bellard
                    gen_vfp_mul(dp);
759 b7bcbe95 bellard
                    gen_vfp_neg(dp);
760 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
761 b7bcbe95 bellard
                    gen_vfp_add(dp);
762 b7bcbe95 bellard
                    break;
763 b7bcbe95 bellard
                case 2: /* msc: -fd + (fn * fm) */
764 b7bcbe95 bellard
                    gen_vfp_mul(dp);
765 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
766 b7bcbe95 bellard
                    gen_vfp_sub(dp);
767 b7bcbe95 bellard
                    break;
768 b7bcbe95 bellard
                case 3: /* nmsc: -fd - (fn * fm)  */
769 b7bcbe95 bellard
                    gen_vfp_mul(dp);
770 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
771 b7bcbe95 bellard
                    gen_vfp_add(dp);
772 b7bcbe95 bellard
                    gen_vfp_neg(dp);
773 b7bcbe95 bellard
                    break;
774 b7bcbe95 bellard
                case 4: /* mul: fn * fm */
775 b7bcbe95 bellard
                    gen_vfp_mul(dp);
776 b7bcbe95 bellard
                    break;
777 b7bcbe95 bellard
                case 5: /* nmul: -(fn * fm) */
778 b7bcbe95 bellard
                    gen_vfp_mul(dp);
779 b7bcbe95 bellard
                    gen_vfp_neg(dp);
780 b7bcbe95 bellard
                    break;
781 b7bcbe95 bellard
                case 6: /* add: fn + fm */
782 b7bcbe95 bellard
                    gen_vfp_add(dp);
783 b7bcbe95 bellard
                    break;
784 b7bcbe95 bellard
                case 7: /* sub: fn - fm */
785 b7bcbe95 bellard
                    gen_vfp_sub(dp);
786 b7bcbe95 bellard
                    break;
787 b7bcbe95 bellard
                case 8: /* div: fn / fm */
788 b7bcbe95 bellard
                    gen_vfp_div(dp);
789 b7bcbe95 bellard
                    break;
790 b7bcbe95 bellard
                case 15: /* extension space */
791 b7bcbe95 bellard
                    switch (rn) {
792 b7bcbe95 bellard
                    case 0: /* cpy */
793 b7bcbe95 bellard
                        /* no-op */
794 b7bcbe95 bellard
                        break;
795 b7bcbe95 bellard
                    case 1: /* abs */
796 b7bcbe95 bellard
                        gen_vfp_abs(dp);
797 b7bcbe95 bellard
                        break;
798 b7bcbe95 bellard
                    case 2: /* neg */
799 b7bcbe95 bellard
                        gen_vfp_neg(dp);
800 b7bcbe95 bellard
                        break;
801 b7bcbe95 bellard
                    case 3: /* sqrt */
802 b7bcbe95 bellard
                        gen_vfp_sqrt(dp);
803 b7bcbe95 bellard
                        break;
804 b7bcbe95 bellard
                    case 8: /* cmp */
805 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
806 b7bcbe95 bellard
                        break;
807 b7bcbe95 bellard
                    case 9: /* cmpe */
808 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
809 b7bcbe95 bellard
                        break;
810 b7bcbe95 bellard
                    case 10: /* cmpz */
811 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
812 b7bcbe95 bellard
                        break;
813 b7bcbe95 bellard
                    case 11: /* cmpez */
814 b7bcbe95 bellard
                        gen_vfp_F1_ld0(dp);
815 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
816 b7bcbe95 bellard
                        break;
817 b7bcbe95 bellard
                    case 15: /* single<->double conversion */
818 b7bcbe95 bellard
                        if (dp)
819 b7bcbe95 bellard
                            gen_op_vfp_fcvtsd();
820 b7bcbe95 bellard
                        else
821 b7bcbe95 bellard
                            gen_op_vfp_fcvtds();
822 b7bcbe95 bellard
                        break;
823 b7bcbe95 bellard
                    case 16: /* fuito */
824 b7bcbe95 bellard
                        gen_vfp_uito(dp);
825 b7bcbe95 bellard
                        break;
826 b7bcbe95 bellard
                    case 17: /* fsito */
827 b7bcbe95 bellard
                        gen_vfp_sito(dp);
828 b7bcbe95 bellard
                        break;
829 b7bcbe95 bellard
                    case 24: /* ftoui */
830 b7bcbe95 bellard
                        gen_vfp_toui(dp);
831 b7bcbe95 bellard
                        break;
832 b7bcbe95 bellard
                    case 25: /* ftouiz */
833 b7bcbe95 bellard
                        gen_vfp_touiz(dp);
834 b7bcbe95 bellard
                        break;
835 b7bcbe95 bellard
                    case 26: /* ftosi */
836 b7bcbe95 bellard
                        gen_vfp_tosi(dp);
837 b7bcbe95 bellard
                        break;
838 b7bcbe95 bellard
                    case 27: /* ftosiz */
839 b7bcbe95 bellard
                        gen_vfp_tosiz(dp);
840 b7bcbe95 bellard
                        break;
841 b7bcbe95 bellard
                    default: /* undefined */
842 b7bcbe95 bellard
                        printf ("rn:%d\n", rn);
843 b7bcbe95 bellard
                        return 1;
844 b7bcbe95 bellard
                    }
845 b7bcbe95 bellard
                    break;
846 b7bcbe95 bellard
                default: /* undefined */
847 b7bcbe95 bellard
                    printf ("op:%d\n", op);
848 b7bcbe95 bellard
                    return 1;
849 b7bcbe95 bellard
                }
850 b7bcbe95 bellard
851 b7bcbe95 bellard
                /* Write back the result.  */
852 b7bcbe95 bellard
                if (op == 15 && (rn >= 8 && rn <= 11))
853 b7bcbe95 bellard
                    ; /* Comparison, do nothing.  */
854 b7bcbe95 bellard
                else if (op == 15 && rn > 17)
855 b7bcbe95 bellard
                    /* Integer result.  */
856 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rd);
857 b7bcbe95 bellard
                else if (op == 15 && rn == 15)
858 b7bcbe95 bellard
                    /* conversion */
859 b7bcbe95 bellard
                    gen_mov_vreg_F0(!dp, rd);
860 b7bcbe95 bellard
                else
861 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
862 b7bcbe95 bellard
863 b7bcbe95 bellard
                /* break out of the loop if we have finished  */
864 b7bcbe95 bellard
                if (veclen == 0)
865 b7bcbe95 bellard
                    break;
866 b7bcbe95 bellard
867 b7bcbe95 bellard
                if (op == 15 && delta_m == 0) {
868 b7bcbe95 bellard
                    /* single source one-many */
869 b7bcbe95 bellard
                    while (veclen--) {
870 b7bcbe95 bellard
                        rd = ((rd + delta_d) & (bank_mask - 1))
871 b7bcbe95 bellard
                             | (rd & bank_mask);
872 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd);
873 b7bcbe95 bellard
                    }
874 b7bcbe95 bellard
                    break;
875 b7bcbe95 bellard
                }
876 b7bcbe95 bellard
                /* Setup the next operands.  */
877 b7bcbe95 bellard
                veclen--;
878 b7bcbe95 bellard
                rd = ((rd + delta_d) & (bank_mask - 1))
879 b7bcbe95 bellard
                     | (rd & bank_mask);
880 b7bcbe95 bellard
881 b7bcbe95 bellard
                if (op == 15) {
882 b7bcbe95 bellard
                    /* One source operand.  */
883 b7bcbe95 bellard
                    rm = ((rm + delta_m) & (bank_mask - 1))
884 b7bcbe95 bellard
                         | (rm & bank_mask);
885 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
886 b7bcbe95 bellard
                } else {
887 b7bcbe95 bellard
                    /* Two source operands.  */
888 b7bcbe95 bellard
                    rn = ((rn + delta_d) & (bank_mask - 1))
889 b7bcbe95 bellard
                         | (rn & bank_mask);
890 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rn);
891 b7bcbe95 bellard
                    if (delta_m) {
892 b7bcbe95 bellard
                        rm = ((rm + delta_m) & (bank_mask - 1))
893 b7bcbe95 bellard
                             | (rm & bank_mask);
894 b7bcbe95 bellard
                        gen_mov_F1_vreg(dp, rm);
895 b7bcbe95 bellard
                    }
896 b7bcbe95 bellard
                }
897 b7bcbe95 bellard
            }
898 b7bcbe95 bellard
        }
899 b7bcbe95 bellard
        break;
900 b7bcbe95 bellard
    case 0xc:
901 b7bcbe95 bellard
    case 0xd:
902 b7bcbe95 bellard
        if (dp && (insn & (1 << 22))) {
903 b7bcbe95 bellard
            /* two-register transfer */
904 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
905 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
906 b7bcbe95 bellard
            if (dp) {
907 b7bcbe95 bellard
                if (insn & (1 << 5))
908 b7bcbe95 bellard
                    return 1;
909 b7bcbe95 bellard
                rm = insn & 0xf;
910 b7bcbe95 bellard
            } else
911 b7bcbe95 bellard
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
912 b7bcbe95 bellard
913 b7bcbe95 bellard
            if (insn & (1 << 20)) {
914 b7bcbe95 bellard
                /* vfp->arm */
915 b7bcbe95 bellard
                if (dp) {
916 b7bcbe95 bellard
                    gen_mov_F0_vreg(1, rm);
917 b7bcbe95 bellard
                    gen_op_vfp_mrrd();
918 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rd);
919 b7bcbe95 bellard
                    gen_movl_reg_T1(s, rn);
920 b7bcbe95 bellard
                } else {
921 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
922 b7bcbe95 bellard
                    gen_op_vfp_mrs();
923 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rn);
924 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm + 1);
925 b7bcbe95 bellard
                    gen_op_vfp_mrs();
926 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rd);
927 b7bcbe95 bellard
                }
928 b7bcbe95 bellard
            } else {
929 b7bcbe95 bellard
                /* arm->vfp */
930 b7bcbe95 bellard
                if (dp) {
931 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
932 b7bcbe95 bellard
                    gen_movl_T1_reg(s, rn);
933 b7bcbe95 bellard
                    gen_op_vfp_mdrr();
934 b7bcbe95 bellard
                    gen_mov_vreg_F0(1, rm);
935 b7bcbe95 bellard
                } else {
936 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rn);
937 b7bcbe95 bellard
                    gen_op_vfp_msr();
938 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm);
939 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
940 b7bcbe95 bellard
                    gen_op_vfp_msr();
941 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm + 1);
942 b7bcbe95 bellard
                }
943 b7bcbe95 bellard
            }
944 b7bcbe95 bellard
        } else {
945 b7bcbe95 bellard
            /* Load/store */
946 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
947 b7bcbe95 bellard
            if (dp)
948 b7bcbe95 bellard
                rd = (insn >> 12) & 0xf;
949 b7bcbe95 bellard
            else
950 b7bcbe95 bellard
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
951 b7bcbe95 bellard
            gen_movl_T1_reg(s, rn);
952 b7bcbe95 bellard
            if ((insn & 0x01200000) == 0x01000000) {
953 b7bcbe95 bellard
                /* Single load/store */
954 b7bcbe95 bellard
                offset = (insn & 0xff) << 2;
955 b7bcbe95 bellard
                if ((insn & (1 << 23)) == 0)
956 b7bcbe95 bellard
                    offset = -offset;
957 b7bcbe95 bellard
                gen_op_addl_T1_im(offset);
958 b7bcbe95 bellard
                if (insn & (1 << 20)) {
959 b5ff1b31 bellard
                    gen_vfp_ld(s, dp);
960 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
961 b7bcbe95 bellard
                } else {
962 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
963 b5ff1b31 bellard
                    gen_vfp_st(s, dp);
964 b7bcbe95 bellard
                }
965 b7bcbe95 bellard
            } else {
966 b7bcbe95 bellard
                /* load/store multiple */
967 b7bcbe95 bellard
                if (dp)
968 b7bcbe95 bellard
                    n = (insn >> 1) & 0x7f;
969 b7bcbe95 bellard
                else
970 b7bcbe95 bellard
                    n = insn & 0xff;
971 b7bcbe95 bellard
972 b7bcbe95 bellard
                if (insn & (1 << 24)) /* pre-decrement */
973 b7bcbe95 bellard
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
974 b7bcbe95 bellard
975 b7bcbe95 bellard
                if (dp)
976 b7bcbe95 bellard
                    offset = 8;
977 b7bcbe95 bellard
                else
978 b7bcbe95 bellard
                    offset = 4;
979 b7bcbe95 bellard
                for (i = 0; i < n; i++) {
980 b7bcbe95 bellard
                    if (insn & (1 << 20)) {
981 b7bcbe95 bellard
                        /* load */
982 b5ff1b31 bellard
                        gen_vfp_ld(s, dp);
983 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd + i);
984 b7bcbe95 bellard
                    } else {
985 b7bcbe95 bellard
                        /* store */
986 b7bcbe95 bellard
                        gen_mov_F0_vreg(dp, rd + i);
987 b5ff1b31 bellard
                        gen_vfp_st(s, dp);
988 b7bcbe95 bellard
                    }
989 b7bcbe95 bellard
                    gen_op_addl_T1_im(offset);
990 b7bcbe95 bellard
                }
991 b7bcbe95 bellard
                if (insn & (1 << 21)) {
992 b7bcbe95 bellard
                    /* writeback */
993 b7bcbe95 bellard
                    if (insn & (1 << 24))
994 b7bcbe95 bellard
                        offset = -offset * n;
995 b7bcbe95 bellard
                    else if (dp && (insn & 1))
996 b7bcbe95 bellard
                        offset = 4;
997 b7bcbe95 bellard
                    else
998 b7bcbe95 bellard
                        offset = 0;
999 b7bcbe95 bellard
1000 b7bcbe95 bellard
                    if (offset != 0)
1001 b7bcbe95 bellard
                        gen_op_addl_T1_im(offset);
1002 b7bcbe95 bellard
                    gen_movl_reg_T1(s, rn);
1003 b7bcbe95 bellard
                }
1004 b7bcbe95 bellard
            }
1005 b7bcbe95 bellard
        }
1006 b7bcbe95 bellard
        break;
1007 b7bcbe95 bellard
    default:
1008 b7bcbe95 bellard
        /* Should never happen.  */
1009 b7bcbe95 bellard
        return 1;
1010 b7bcbe95 bellard
    }
1011 b7bcbe95 bellard
    return 0;
1012 b7bcbe95 bellard
}
1013 b7bcbe95 bellard
1014 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1015 c53be334 bellard
{
1016 6e256c93 bellard
    TranslationBlock *tb;
1017 6e256c93 bellard
1018 6e256c93 bellard
    tb = s->tb;
1019 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1020 6e256c93 bellard
        if (n == 0)
1021 6e256c93 bellard
            gen_op_goto_tb0(TBPARAM(tb));
1022 6e256c93 bellard
        else
1023 6e256c93 bellard
            gen_op_goto_tb1(TBPARAM(tb));
1024 6e256c93 bellard
        gen_op_movl_T0_im(dest);
1025 6e256c93 bellard
        gen_op_movl_r15_T0();
1026 6e256c93 bellard
        gen_op_movl_T0_im((long)tb + n);
1027 6e256c93 bellard
        gen_op_exit_tb();
1028 6e256c93 bellard
    } else {
1029 6e256c93 bellard
        gen_op_movl_T0_im(dest);
1030 6e256c93 bellard
        gen_op_movl_r15_T0();
1031 6e256c93 bellard
        gen_op_movl_T0_0();
1032 6e256c93 bellard
        gen_op_exit_tb();
1033 6e256c93 bellard
    }
1034 c53be334 bellard
}
1035 c53be334 bellard
1036 8aaca4c0 bellard
static inline void gen_jmp (DisasContext *s, uint32_t dest)
1037 8aaca4c0 bellard
{
1038 8aaca4c0 bellard
    if (__builtin_expect(s->singlestep_enabled, 0)) {
1039 8aaca4c0 bellard
        /* An indirect jump so that we still trigger the debug exception.  */
1040 5899f386 bellard
        if (s->thumb)
1041 5899f386 bellard
          dest |= 1;
1042 8aaca4c0 bellard
        gen_op_movl_T0_im(dest);
1043 8aaca4c0 bellard
        gen_bx(s);
1044 8aaca4c0 bellard
    } else {
1045 6e256c93 bellard
        gen_goto_tb(s, 0, dest);
1046 8aaca4c0 bellard
        s->is_jmp = DISAS_TB_JUMP;
1047 8aaca4c0 bellard
    }
1048 8aaca4c0 bellard
}
1049 8aaca4c0 bellard
1050 b5ff1b31 bellard
static inline void gen_mulxy(int x, int y)
1051 b5ff1b31 bellard
{
1052 ee097184 bellard
    if (x)
1053 b5ff1b31 bellard
        gen_op_sarl_T0_im(16);
1054 b5ff1b31 bellard
    else
1055 b5ff1b31 bellard
        gen_op_sxth_T0();
1056 ee097184 bellard
    if (y)
1057 b5ff1b31 bellard
        gen_op_sarl_T1_im(16);
1058 b5ff1b31 bellard
    else
1059 b5ff1b31 bellard
        gen_op_sxth_T1();
1060 b5ff1b31 bellard
    gen_op_mul_T0_T1();
1061 b5ff1b31 bellard
}
1062 b5ff1b31 bellard
1063 b5ff1b31 bellard
/* Return the mask of PSR bits set by a MSR instruction.  */
1064 2ae23e75 pbrook
static uint32_t msr_mask(DisasContext *s, int flags, int spsr) {
1065 b5ff1b31 bellard
    uint32_t mask;
1066 b5ff1b31 bellard
1067 b5ff1b31 bellard
    mask = 0;
1068 b5ff1b31 bellard
    if (flags & (1 << 0))
1069 b5ff1b31 bellard
        mask |= 0xff;
1070 b5ff1b31 bellard
    if (flags & (1 << 1))
1071 b5ff1b31 bellard
        mask |= 0xff00;
1072 b5ff1b31 bellard
    if (flags & (1 << 2))
1073 b5ff1b31 bellard
        mask |= 0xff0000;
1074 b5ff1b31 bellard
    if (flags & (1 << 3))
1075 b5ff1b31 bellard
        mask |= 0xff000000;
1076 2ae23e75 pbrook
    /* Mask out undefined bits.  */
1077 2ae23e75 pbrook
    mask &= 0xf90f03ff;
1078 2ae23e75 pbrook
    /* Mask out state bits.  */
1079 2ae23e75 pbrook
    if (!spsr)
1080 2ae23e75 pbrook
        mask &= ~0x01000020;
1081 b5ff1b31 bellard
    /* Mask out privileged bits.  */
1082 b5ff1b31 bellard
    if (IS_USER(s))
1083 b5ff1b31 bellard
        mask &= 0xf80f0200;
1084 b5ff1b31 bellard
    return mask;
1085 b5ff1b31 bellard
}
1086 b5ff1b31 bellard
1087 b5ff1b31 bellard
/* Returns nonzero if access to the PSR is not permitted.  */
1088 b5ff1b31 bellard
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
1089 b5ff1b31 bellard
{
1090 b5ff1b31 bellard
    if (spsr) {
1091 b5ff1b31 bellard
        /* ??? This is also undefined in system mode.  */
1092 b5ff1b31 bellard
        if (IS_USER(s))
1093 b5ff1b31 bellard
            return 1;
1094 b5ff1b31 bellard
        gen_op_movl_spsr_T0(mask);
1095 b5ff1b31 bellard
    } else {
1096 b5ff1b31 bellard
        gen_op_movl_cpsr_T0(mask);
1097 b5ff1b31 bellard
    }
1098 b5ff1b31 bellard
    gen_lookup_tb(s);
1099 b5ff1b31 bellard
    return 0;
1100 b5ff1b31 bellard
}
1101 b5ff1b31 bellard
1102 b5ff1b31 bellard
static void gen_exception_return(DisasContext *s)
1103 b5ff1b31 bellard
{
1104 b5ff1b31 bellard
    gen_op_movl_reg_TN[0][15]();
1105 b5ff1b31 bellard
    gen_op_movl_T0_spsr();
1106 b5ff1b31 bellard
    gen_op_movl_cpsr_T0(0xffffffff);
1107 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
1108 b5ff1b31 bellard
}
1109 b5ff1b31 bellard
1110 b7bcbe95 bellard
static void disas_arm_insn(CPUState * env, DisasContext *s)
1111 2c0262af bellard
{
1112 2c0262af bellard
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
1113 2c0262af bellard
    
1114 b5ff1b31 bellard
    insn = ldl_code(s->pc);
1115 2c0262af bellard
    s->pc += 4;
1116 2c0262af bellard
    
1117 2c0262af bellard
    cond = insn >> 28;
1118 99c475ab bellard
    if (cond == 0xf){
1119 b7bcbe95 bellard
        /* Unconditional instructions.  */
1120 99c475ab bellard
        if ((insn & 0x0d70f000) == 0x0550f000)
1121 99c475ab bellard
            return; /* PLD */
1122 99c475ab bellard
        else if ((insn & 0x0e000000) == 0x0a000000) {
1123 99c475ab bellard
            /* branch link and change to thumb (blx <offset>) */
1124 99c475ab bellard
            int32_t offset;
1125 99c475ab bellard
1126 99c475ab bellard
            val = (uint32_t)s->pc;
1127 99c475ab bellard
            gen_op_movl_T0_im(val);
1128 99c475ab bellard
            gen_movl_reg_T0(s, 14);
1129 99c475ab bellard
            /* Sign-extend the 24-bit offset */
1130 99c475ab bellard
            offset = (((int32_t)insn) << 8) >> 8;
1131 99c475ab bellard
            /* offset * 4 + bit24 * 2 + (thumb bit) */
1132 99c475ab bellard
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
1133 99c475ab bellard
            /* pipeline offset */
1134 99c475ab bellard
            val += 4;
1135 99c475ab bellard
            gen_op_movl_T0_im(val);
1136 99c475ab bellard
            gen_bx(s);
1137 99c475ab bellard
            return;
1138 b7bcbe95 bellard
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
1139 b7bcbe95 bellard
            /* Coprocessor double register transfer.  */
1140 b7bcbe95 bellard
        } else if ((insn & 0x0f000010) == 0x0e000010) {
1141 b7bcbe95 bellard
            /* Additional coprocessor register transfer.  */
1142 b5ff1b31 bellard
        } else if ((insn & 0x0ff10010) == 0x01000000) {
1143 b5ff1b31 bellard
            /* cps (privileged) */
1144 b5ff1b31 bellard
        } else if ((insn & 0x0ffffdff) == 0x01010000) {
1145 b5ff1b31 bellard
            /* setend */
1146 b5ff1b31 bellard
            if (insn & (1 << 9)) {
1147 b5ff1b31 bellard
                /* BE8 mode not implemented.  */
1148 b5ff1b31 bellard
                goto illegal_op;
1149 b5ff1b31 bellard
            }
1150 b5ff1b31 bellard
            return;
1151 99c475ab bellard
        }
1152 2c0262af bellard
        goto illegal_op;
1153 99c475ab bellard
    }
1154 2c0262af bellard
    if (cond != 0xe) {
1155 2c0262af bellard
        /* if not always execute, we generate a conditional jump to
1156 2c0262af bellard
           next instruction */
1157 e50e6a20 bellard
        s->condlabel = gen_new_label();
1158 e50e6a20 bellard
        gen_test_cc[cond ^ 1](s->condlabel);
1159 e50e6a20 bellard
        s->condjmp = 1;
1160 e50e6a20 bellard
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1161 e50e6a20 bellard
        //s->is_jmp = DISAS_JUMP_NEXT;
1162 2c0262af bellard
    }
1163 99c475ab bellard
    if ((insn & 0x0f900000) == 0x03000000) {
1164 b5ff1b31 bellard
        if ((insn & 0x0fb0f000) != 0x0320f000)
1165 99c475ab bellard
            goto illegal_op;
1166 99c475ab bellard
        /* CPSR = immediate */
1167 99c475ab bellard
        val = insn & 0xff;
1168 99c475ab bellard
        shift = ((insn >> 8) & 0xf) * 2;
1169 99c475ab bellard
        if (shift)
1170 99c475ab bellard
            val = (val >> shift) | (val << (32 - shift));
1171 99c475ab bellard
        gen_op_movl_T0_im(val);
1172 2ae23e75 pbrook
        i = ((insn & (1 << 22)) != 0);
1173 2ae23e75 pbrook
        if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1174 b5ff1b31 bellard
            goto illegal_op;
1175 99c475ab bellard
    } else if ((insn & 0x0f900000) == 0x01000000
1176 99c475ab bellard
               && (insn & 0x00000090) != 0x00000090) {
1177 99c475ab bellard
        /* miscellaneous instructions */
1178 99c475ab bellard
        op1 = (insn >> 21) & 3;
1179 99c475ab bellard
        sh = (insn >> 4) & 0xf;
1180 99c475ab bellard
        rm = insn & 0xf;
1181 99c475ab bellard
        switch (sh) {
1182 99c475ab bellard
        case 0x0: /* move program status register */
1183 99c475ab bellard
            if (op1 & 1) {
1184 b5ff1b31 bellard
                /* PSR = reg */
1185 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1186 2ae23e75 pbrook
                i = ((op1 & 2) != 0);
1187 2ae23e75 pbrook
                if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1188 b5ff1b31 bellard
                    goto illegal_op;
1189 99c475ab bellard
            } else {
1190 2ae23e75 pbrook
                /* reg = PSR */
1191 99c475ab bellard
                rd = (insn >> 12) & 0xf;
1192 b5ff1b31 bellard
                if (op1 & 2) {
1193 b5ff1b31 bellard
                    if (IS_USER(s))
1194 b5ff1b31 bellard
                        goto illegal_op;
1195 b5ff1b31 bellard
                    gen_op_movl_T0_spsr();
1196 b5ff1b31 bellard
                } else {
1197 b5ff1b31 bellard
                    gen_op_movl_T0_cpsr();
1198 b5ff1b31 bellard
                }
1199 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1200 99c475ab bellard
            }
1201 b8a9e8f1 bellard
            break;
1202 99c475ab bellard
        case 0x1:
1203 99c475ab bellard
            if (op1 == 1) {
1204 99c475ab bellard
                /* branch/exchange thumb (bx).  */
1205 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1206 99c475ab bellard
                gen_bx(s);
1207 99c475ab bellard
            } else if (op1 == 3) {
1208 99c475ab bellard
                /* clz */
1209 99c475ab bellard
                rd = (insn >> 12) & 0xf;
1210 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1211 99c475ab bellard
                gen_op_clz_T0();
1212 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1213 99c475ab bellard
            } else {
1214 99c475ab bellard
                goto illegal_op;
1215 99c475ab bellard
            }
1216 99c475ab bellard
            break;
1217 b5ff1b31 bellard
        case 0x2:
1218 b5ff1b31 bellard
            if (op1 == 1) {
1219 b5ff1b31 bellard
                ARCH(5J); /* bxj */
1220 b5ff1b31 bellard
                /* Trivial implementation equivalent to bx.  */
1221 b5ff1b31 bellard
                gen_movl_T0_reg(s, rm);
1222 b5ff1b31 bellard
                gen_bx(s);
1223 b5ff1b31 bellard
            } else {
1224 b5ff1b31 bellard
                goto illegal_op;
1225 b5ff1b31 bellard
            }
1226 b5ff1b31 bellard
            break;
1227 99c475ab bellard
        case 0x3:
1228 99c475ab bellard
            if (op1 != 1)
1229 99c475ab bellard
              goto illegal_op;
1230 99c475ab bellard
1231 99c475ab bellard
            /* branch link/exchange thumb (blx) */
1232 99c475ab bellard
            val = (uint32_t)s->pc;
1233 99c475ab bellard
            gen_op_movl_T0_im(val);
1234 99c475ab bellard
            gen_movl_reg_T0(s, 14);
1235 99c475ab bellard
            gen_movl_T0_reg(s, rm);
1236 99c475ab bellard
            gen_bx(s);
1237 99c475ab bellard
            break;
1238 99c475ab bellard
        case 0x5: /* saturating add/subtract */
1239 99c475ab bellard
            rd = (insn >> 12) & 0xf;
1240 99c475ab bellard
            rn = (insn >> 16) & 0xf;
1241 ff8263a9 bellard
            gen_movl_T0_reg(s, rm);
1242 ff8263a9 bellard
            gen_movl_T1_reg(s, rn);
1243 ff8263a9 bellard
            if (op1 & 2)
1244 ff8263a9 bellard
                gen_op_double_T1_saturate();
1245 99c475ab bellard
            if (op1 & 1)
1246 99c475ab bellard
                gen_op_subl_T0_T1_saturate();
1247 99c475ab bellard
            else
1248 99c475ab bellard
                gen_op_addl_T0_T1_saturate();
1249 ff8263a9 bellard
            gen_movl_reg_T0(s, rd);
1250 99c475ab bellard
            break;
1251 06c949e6 pbrook
        case 7: /* bkpt */
1252 06c949e6 pbrook
            gen_op_movl_T0_im((long)s->pc - 4);
1253 06c949e6 pbrook
            gen_op_movl_reg_TN[0][15]();
1254 06c949e6 pbrook
            gen_op_bkpt();
1255 06c949e6 pbrook
            s->is_jmp = DISAS_JUMP;
1256 06c949e6 pbrook
            break;
1257 99c475ab bellard
        case 0x8: /* signed multiply */
1258 99c475ab bellard
        case 0xa:
1259 99c475ab bellard
        case 0xc:
1260 99c475ab bellard
        case 0xe:
1261 99c475ab bellard
            rs = (insn >> 8) & 0xf;
1262 99c475ab bellard
            rn = (insn >> 12) & 0xf;
1263 99c475ab bellard
            rd = (insn >> 16) & 0xf;
1264 99c475ab bellard
            if (op1 == 1) {
1265 99c475ab bellard
                /* (32 * 16) >> 16 */
1266 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1267 99c475ab bellard
                gen_movl_T1_reg(s, rs);
1268 99c475ab bellard
                if (sh & 4)
1269 99c475ab bellard
                    gen_op_sarl_T1_im(16);
1270 99c475ab bellard
                else
1271 b5ff1b31 bellard
                    gen_op_sxth_T1();
1272 99c475ab bellard
                gen_op_imulw_T0_T1();
1273 99c475ab bellard
                if ((sh & 2) == 0) {
1274 99c475ab bellard
                    gen_movl_T1_reg(s, rn);
1275 99c475ab bellard
                    gen_op_addl_T0_T1_setq();
1276 99c475ab bellard
                }
1277 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1278 99c475ab bellard
            } else {
1279 99c475ab bellard
                /* 16 * 16 */
1280 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1281 99c475ab bellard
                gen_movl_T1_reg(s, rs);
1282 b5ff1b31 bellard
                gen_mulxy(sh & 2, sh & 4);
1283 99c475ab bellard
                if (op1 == 2) {
1284 b5ff1b31 bellard
                    gen_op_signbit_T1_T0();
1285 99c475ab bellard
                    gen_op_addq_T0_T1(rn, rd);
1286 99c475ab bellard
                    gen_movl_reg_T0(s, rn);
1287 99c475ab bellard
                    gen_movl_reg_T1(s, rd);
1288 99c475ab bellard
                } else {
1289 99c475ab bellard
                    if (op1 == 0) {
1290 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
1291 99c475ab bellard
                        gen_op_addl_T0_T1_setq();
1292 99c475ab bellard
                    }
1293 99c475ab bellard
                    gen_movl_reg_T0(s, rd);
1294 99c475ab bellard
                }
1295 99c475ab bellard
            }
1296 99c475ab bellard
            break;
1297 99c475ab bellard
        default:
1298 99c475ab bellard
            goto illegal_op;
1299 99c475ab bellard
        }
1300 99c475ab bellard
    } else if (((insn & 0x0e000000) == 0 &&
1301 99c475ab bellard
                (insn & 0x00000090) != 0x90) ||
1302 99c475ab bellard
               ((insn & 0x0e000000) == (1 << 25))) {
1303 2c0262af bellard
        int set_cc, logic_cc, shiftop;
1304 2c0262af bellard
        
1305 2c0262af bellard
        op1 = (insn >> 21) & 0xf;
1306 2c0262af bellard
        set_cc = (insn >> 20) & 1;
1307 2c0262af bellard
        logic_cc = table_logic_cc[op1] & set_cc;
1308 2c0262af bellard
1309 2c0262af bellard
        /* data processing instruction */
1310 2c0262af bellard
        if (insn & (1 << 25)) {
1311 2c0262af bellard
            /* immediate operand */
1312 2c0262af bellard
            val = insn & 0xff;
1313 2c0262af bellard
            shift = ((insn >> 8) & 0xf) * 2;
1314 2c0262af bellard
            if (shift)
1315 2c0262af bellard
                val = (val >> shift) | (val << (32 - shift));
1316 2c0262af bellard
            gen_op_movl_T1_im(val);
1317 7ff4d218 bellard
            if (logic_cc && shift)
1318 7ff4d218 bellard
                gen_op_mov_CF_T1();
1319 2c0262af bellard
        } else {
1320 2c0262af bellard
            /* register */
1321 2c0262af bellard
            rm = (insn) & 0xf;
1322 2c0262af bellard
            gen_movl_T1_reg(s, rm);
1323 2c0262af bellard
            shiftop = (insn >> 5) & 3;
1324 2c0262af bellard
            if (!(insn & (1 << 4))) {
1325 2c0262af bellard
                shift = (insn >> 7) & 0x1f;
1326 2c0262af bellard
                if (shift != 0) {
1327 2c0262af bellard
                    if (logic_cc) {
1328 2c0262af bellard
                        gen_shift_T1_im_cc[shiftop](shift);
1329 2c0262af bellard
                    } else {
1330 2c0262af bellard
                        gen_shift_T1_im[shiftop](shift);
1331 2c0262af bellard
                    }
1332 1e8d4eec bellard
                } else if (shiftop != 0) {
1333 1e8d4eec bellard
                    if (logic_cc) {
1334 1e8d4eec bellard
                        gen_shift_T1_0_cc[shiftop]();
1335 1e8d4eec bellard
                    } else {
1336 1e8d4eec bellard
                        gen_shift_T1_0[shiftop]();
1337 1e8d4eec bellard
                    }
1338 2c0262af bellard
                }
1339 2c0262af bellard
            } else {
1340 2c0262af bellard
                rs = (insn >> 8) & 0xf;
1341 2c0262af bellard
                gen_movl_T0_reg(s, rs);
1342 2c0262af bellard
                if (logic_cc) {
1343 2c0262af bellard
                    gen_shift_T1_T0_cc[shiftop]();
1344 2c0262af bellard
                } else {
1345 2c0262af bellard
                    gen_shift_T1_T0[shiftop]();
1346 2c0262af bellard
                }
1347 2c0262af bellard
            }
1348 2c0262af bellard
        }
1349 2c0262af bellard
        if (op1 != 0x0f && op1 != 0x0d) {
1350 2c0262af bellard
            rn = (insn >> 16) & 0xf;
1351 2c0262af bellard
            gen_movl_T0_reg(s, rn);
1352 2c0262af bellard
        }
1353 2c0262af bellard
        rd = (insn >> 12) & 0xf;
1354 2c0262af bellard
        switch(op1) {
1355 2c0262af bellard
        case 0x00:
1356 2c0262af bellard
            gen_op_andl_T0_T1();
1357 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1358 2c0262af bellard
            if (logic_cc)
1359 2c0262af bellard
                gen_op_logic_T0_cc();
1360 2c0262af bellard
            break;
1361 2c0262af bellard
        case 0x01:
1362 2c0262af bellard
            gen_op_xorl_T0_T1();
1363 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1364 2c0262af bellard
            if (logic_cc)
1365 2c0262af bellard
                gen_op_logic_T0_cc();
1366 2c0262af bellard
            break;
1367 2c0262af bellard
        case 0x02:
1368 b5ff1b31 bellard
            if (set_cc && rd == 15) {
1369 b5ff1b31 bellard
                /* SUBS r15, ... is used for exception return.  */
1370 b5ff1b31 bellard
                if (IS_USER(s))
1371 b5ff1b31 bellard
                    goto illegal_op;
1372 2c0262af bellard
                gen_op_subl_T0_T1_cc();
1373 b5ff1b31 bellard
                gen_exception_return(s);
1374 b5ff1b31 bellard
            } else {
1375 b5ff1b31 bellard
                if (set_cc)
1376 b5ff1b31 bellard
                    gen_op_subl_T0_T1_cc();
1377 b5ff1b31 bellard
                else
1378 b5ff1b31 bellard
                    gen_op_subl_T0_T1();
1379 b5ff1b31 bellard
                gen_movl_reg_T0(s, rd);
1380 b5ff1b31 bellard
            }
1381 2c0262af bellard
            break;
1382 2c0262af bellard
        case 0x03:
1383 2c0262af bellard
            if (set_cc)
1384 2c0262af bellard
                gen_op_rsbl_T0_T1_cc();
1385 2c0262af bellard
            else
1386 2c0262af bellard
                gen_op_rsbl_T0_T1();
1387 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1388 2c0262af bellard
            break;
1389 2c0262af bellard
        case 0x04:
1390 2c0262af bellard
            if (set_cc)
1391 2c0262af bellard
                gen_op_addl_T0_T1_cc();
1392 2c0262af bellard
            else
1393 2c0262af bellard
                gen_op_addl_T0_T1();
1394 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1395 2c0262af bellard
            break;
1396 2c0262af bellard
        case 0x05:
1397 2c0262af bellard
            if (set_cc)
1398 2c0262af bellard
                gen_op_adcl_T0_T1_cc();
1399 2c0262af bellard
            else
1400 2c0262af bellard
                gen_op_adcl_T0_T1();
1401 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1402 2c0262af bellard
            break;
1403 2c0262af bellard
        case 0x06:
1404 2c0262af bellard
            if (set_cc)
1405 2c0262af bellard
                gen_op_sbcl_T0_T1_cc();
1406 2c0262af bellard
            else
1407 2c0262af bellard
                gen_op_sbcl_T0_T1();
1408 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1409 2c0262af bellard
            break;
1410 2c0262af bellard
        case 0x07:
1411 2c0262af bellard
            if (set_cc)
1412 2c0262af bellard
                gen_op_rscl_T0_T1_cc();
1413 2c0262af bellard
            else
1414 2c0262af bellard
                gen_op_rscl_T0_T1();
1415 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1416 2c0262af bellard
            break;
1417 2c0262af bellard
        case 0x08:
1418 2c0262af bellard
            if (set_cc) {
1419 2c0262af bellard
                gen_op_andl_T0_T1();
1420 2c0262af bellard
                gen_op_logic_T0_cc();
1421 2c0262af bellard
            }
1422 2c0262af bellard
            break;
1423 2c0262af bellard
        case 0x09:
1424 2c0262af bellard
            if (set_cc) {
1425 2c0262af bellard
                gen_op_xorl_T0_T1();
1426 2c0262af bellard
                gen_op_logic_T0_cc();
1427 2c0262af bellard
            }
1428 2c0262af bellard
            break;
1429 2c0262af bellard
        case 0x0a:
1430 2c0262af bellard
            if (set_cc) {
1431 2c0262af bellard
                gen_op_subl_T0_T1_cc();
1432 2c0262af bellard
            }
1433 2c0262af bellard
            break;
1434 2c0262af bellard
        case 0x0b:
1435 2c0262af bellard
            if (set_cc) {
1436 2c0262af bellard
                gen_op_addl_T0_T1_cc();
1437 2c0262af bellard
            }
1438 2c0262af bellard
            break;
1439 2c0262af bellard
        case 0x0c:
1440 2c0262af bellard
            gen_op_orl_T0_T1();
1441 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1442 2c0262af bellard
            if (logic_cc)
1443 2c0262af bellard
                gen_op_logic_T0_cc();
1444 2c0262af bellard
            break;
1445 2c0262af bellard
        case 0x0d:
1446 b5ff1b31 bellard
            if (logic_cc && rd == 15) {
1447 b5ff1b31 bellard
                /* MOVS r15, ... is used for exception return.  */
1448 b5ff1b31 bellard
                if (IS_USER(s))
1449 b5ff1b31 bellard
                    goto illegal_op;
1450 b5ff1b31 bellard
                gen_op_movl_T0_T1();
1451 b5ff1b31 bellard
                gen_exception_return(s);
1452 b5ff1b31 bellard
            } else {
1453 b5ff1b31 bellard
                gen_movl_reg_T1(s, rd);
1454 b5ff1b31 bellard
                if (logic_cc)
1455 b5ff1b31 bellard
                    gen_op_logic_T1_cc();
1456 b5ff1b31 bellard
            }
1457 2c0262af bellard
            break;
1458 2c0262af bellard
        case 0x0e:
1459 2c0262af bellard
            gen_op_bicl_T0_T1();
1460 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1461 2c0262af bellard
            if (logic_cc)
1462 2c0262af bellard
                gen_op_logic_T0_cc();
1463 2c0262af bellard
            break;
1464 2c0262af bellard
        default:
1465 2c0262af bellard
        case 0x0f:
1466 2c0262af bellard
            gen_op_notl_T1();
1467 2c0262af bellard
            gen_movl_reg_T1(s, rd);
1468 2c0262af bellard
            if (logic_cc)
1469 2c0262af bellard
                gen_op_logic_T1_cc();
1470 2c0262af bellard
            break;
1471 2c0262af bellard
        }
1472 2c0262af bellard
    } else {
1473 2c0262af bellard
        /* other instructions */
1474 2c0262af bellard
        op1 = (insn >> 24) & 0xf;
1475 2c0262af bellard
        switch(op1) {
1476 2c0262af bellard
        case 0x0:
1477 2c0262af bellard
        case 0x1:
1478 99c475ab bellard
            /* multiplies, extra load/stores */
1479 2c0262af bellard
            sh = (insn >> 5) & 3;
1480 2c0262af bellard
            if (sh == 0) {
1481 2c0262af bellard
                if (op1 == 0x0) {
1482 2c0262af bellard
                    rd = (insn >> 16) & 0xf;
1483 2c0262af bellard
                    rn = (insn >> 12) & 0xf;
1484 2c0262af bellard
                    rs = (insn >> 8) & 0xf;
1485 2c0262af bellard
                    rm = (insn) & 0xf;
1486 99c475ab bellard
                    if (((insn >> 22) & 3) == 0) {
1487 2c0262af bellard
                        /* 32 bit mul */
1488 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
1489 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
1490 2c0262af bellard
                        gen_op_mul_T0_T1();
1491 2c0262af bellard
                        if (insn & (1 << 21)) {
1492 2c0262af bellard
                            gen_movl_T1_reg(s, rn);
1493 2c0262af bellard
                            gen_op_addl_T0_T1();
1494 2c0262af bellard
                        }
1495 2c0262af bellard
                        if (insn & (1 << 20)) 
1496 2c0262af bellard
                            gen_op_logic_T0_cc();
1497 2c0262af bellard
                        gen_movl_reg_T0(s, rd);
1498 2c0262af bellard
                    } else {
1499 2c0262af bellard
                        /* 64 bit mul */
1500 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
1501 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
1502 2c0262af bellard
                        if (insn & (1 << 22)) 
1503 2c0262af bellard
                            gen_op_imull_T0_T1();
1504 2e134c9c bellard
                        else
1505 2e134c9c bellard
                            gen_op_mull_T0_T1();
1506 99c475ab bellard
                        if (insn & (1 << 21)) /* mult accumulate */
1507 2c0262af bellard
                            gen_op_addq_T0_T1(rn, rd);
1508 99c475ab bellard
                        if (!(insn & (1 << 23))) { /* double accumulate */
1509 b5ff1b31 bellard
                            ARCH(6);
1510 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rn);
1511 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rd);
1512 99c475ab bellard
                        }
1513 2c0262af bellard
                        if (insn & (1 << 20)) 
1514 2c0262af bellard
                            gen_op_logicq_cc();
1515 2c0262af bellard
                        gen_movl_reg_T0(s, rn);
1516 2c0262af bellard
                        gen_movl_reg_T1(s, rd);
1517 2c0262af bellard
                    }
1518 2c0262af bellard
                } else {
1519 2c0262af bellard
                    rn = (insn >> 16) & 0xf;
1520 2c0262af bellard
                    rd = (insn >> 12) & 0xf;
1521 99c475ab bellard
                    if (insn & (1 << 23)) {
1522 99c475ab bellard
                        /* load/store exclusive */
1523 99c475ab bellard
                        goto illegal_op;
1524 2c0262af bellard
                    } else {
1525 99c475ab bellard
                        /* SWP instruction */
1526 99c475ab bellard
                        rm = (insn) & 0xf;
1527 99c475ab bellard
                        
1528 99c475ab bellard
                        gen_movl_T0_reg(s, rm);
1529 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
1530 99c475ab bellard
                        if (insn & (1 << 22)) {
1531 b5ff1b31 bellard
                            gen_ldst(swpb, s);
1532 99c475ab bellard
                        } else {
1533 b5ff1b31 bellard
                            gen_ldst(swpl, s);
1534 99c475ab bellard
                        }
1535 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
1536 2c0262af bellard
                    }
1537 2c0262af bellard
                }
1538 2c0262af bellard
            } else {
1539 191f9a93 pbrook
                int address_offset;
1540 5fd46862 pbrook
                int load;
1541 99c475ab bellard
                /* Misc load/store */
1542 2c0262af bellard
                rn = (insn >> 16) & 0xf;
1543 2c0262af bellard
                rd = (insn >> 12) & 0xf;
1544 2c0262af bellard
                gen_movl_T1_reg(s, rn);
1545 beddab75 bellard
                if (insn & (1 << 24))
1546 191f9a93 pbrook
                    gen_add_datah_offset(s, insn, 0);
1547 191f9a93 pbrook
                address_offset = 0;
1548 2c0262af bellard
                if (insn & (1 << 20)) {
1549 2c0262af bellard
                    /* load */
1550 2c0262af bellard
                    switch(sh) {
1551 2c0262af bellard
                    case 1:
1552 b5ff1b31 bellard
                        gen_ldst(lduw, s);
1553 2c0262af bellard
                        break;
1554 2c0262af bellard
                    case 2:
1555 b5ff1b31 bellard
                        gen_ldst(ldsb, s);
1556 2c0262af bellard
                        break;
1557 2c0262af bellard
                    default:
1558 2c0262af bellard
                    case 3:
1559 b5ff1b31 bellard
                        gen_ldst(ldsw, s);
1560 2c0262af bellard
                        break;
1561 2c0262af bellard
                    }
1562 5fd46862 pbrook
                    load = 1;
1563 99c475ab bellard
                } else if (sh & 2) {
1564 99c475ab bellard
                    /* doubleword */
1565 99c475ab bellard
                    if (sh & 1) {
1566 99c475ab bellard
                        /* store */
1567 99c475ab bellard
                        gen_movl_T0_reg(s, rd);
1568 b5ff1b31 bellard
                        gen_ldst(stl, s);
1569 99c475ab bellard
                        gen_op_addl_T1_im(4);
1570 99c475ab bellard
                        gen_movl_T0_reg(s, rd + 1);
1571 b5ff1b31 bellard
                        gen_ldst(stl, s);
1572 5fd46862 pbrook
                        load = 0;
1573 99c475ab bellard
                    } else {
1574 99c475ab bellard
                        /* load */
1575 b5ff1b31 bellard
                        gen_ldst(ldl, s);
1576 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
1577 99c475ab bellard
                        gen_op_addl_T1_im(4);
1578 b5ff1b31 bellard
                        gen_ldst(ldl, s);
1579 5fd46862 pbrook
                        rd++;
1580 5fd46862 pbrook
                        load = 1;
1581 99c475ab bellard
                    }
1582 191f9a93 pbrook
                    address_offset = -4;
1583 2c0262af bellard
                } else {
1584 2c0262af bellard
                    /* store */
1585 e748ba4f bellard
                    gen_movl_T0_reg(s, rd);
1586 b5ff1b31 bellard
                    gen_ldst(stw, s);
1587 5fd46862 pbrook
                    load = 0;
1588 2c0262af bellard
                }
1589 5fd46862 pbrook
                /* Perform base writeback before the loaded value to
1590 5fd46862 pbrook
                   ensure correct behavior with overlapping index registers.
1591 5fd46862 pbrook
                   ldrd with base writeback is is undefined if the
1592 5fd46862 pbrook
                   destination and index registers overlap.  */
1593 2c0262af bellard
                if (!(insn & (1 << 24))) {
1594 191f9a93 pbrook
                    gen_add_datah_offset(s, insn, address_offset);
1595 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1596 2c0262af bellard
                } else if (insn & (1 << 21)) {
1597 191f9a93 pbrook
                    if (address_offset)
1598 191f9a93 pbrook
                        gen_op_addl_T1_im(address_offset);
1599 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1600 2c0262af bellard
                }
1601 5fd46862 pbrook
                if (load) {
1602 5fd46862 pbrook
                    /* Complete the load.  */
1603 5fd46862 pbrook
                    gen_movl_reg_T0(s, rd);
1604 5fd46862 pbrook
                }
1605 2c0262af bellard
            }
1606 2c0262af bellard
            break;
1607 2c0262af bellard
        case 0x4:
1608 2c0262af bellard
        case 0x5:
1609 2c0262af bellard
        case 0x6:
1610 2c0262af bellard
        case 0x7:
1611 159f3663 bellard
            /* Check for undefined extension instructions
1612 159f3663 bellard
             * per the ARM Bible IE:
1613 159f3663 bellard
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
1614 159f3663 bellard
             */
1615 159f3663 bellard
            sh = (0xf << 20) | (0xf << 4);
1616 159f3663 bellard
            if (op1 == 0x7 && ((insn & sh) == sh))
1617 159f3663 bellard
            {
1618 159f3663 bellard
                goto illegal_op;
1619 159f3663 bellard
            }
1620 2c0262af bellard
            /* load/store byte/word */
1621 2c0262af bellard
            rn = (insn >> 16) & 0xf;
1622 2c0262af bellard
            rd = (insn >> 12) & 0xf;
1623 2c0262af bellard
            gen_movl_T1_reg(s, rn);
1624 b5ff1b31 bellard
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
1625 2c0262af bellard
            if (insn & (1 << 24))
1626 2c0262af bellard
                gen_add_data_offset(s, insn);
1627 2c0262af bellard
            if (insn & (1 << 20)) {
1628 2c0262af bellard
                /* load */
1629 6658ffb8 pbrook
                s->is_mem = 1;
1630 b5ff1b31 bellard
#if defined(CONFIG_USER_ONLY)
1631 2c0262af bellard
                if (insn & (1 << 22))
1632 b5ff1b31 bellard
                    gen_op_ldub_raw();
1633 2c0262af bellard
                else
1634 b5ff1b31 bellard
                    gen_op_ldl_raw();
1635 b5ff1b31 bellard
#else
1636 b5ff1b31 bellard
                if (insn & (1 << 22)) {
1637 b5ff1b31 bellard
                    if (i)
1638 b5ff1b31 bellard
                        gen_op_ldub_user();
1639 b5ff1b31 bellard
                    else
1640 b5ff1b31 bellard
                        gen_op_ldub_kernel();
1641 b5ff1b31 bellard
                } else {
1642 b5ff1b31 bellard
                    if (i)
1643 b5ff1b31 bellard
                        gen_op_ldl_user();
1644 b5ff1b31 bellard
                    else
1645 b5ff1b31 bellard
                        gen_op_ldl_kernel();
1646 b5ff1b31 bellard
                }
1647 b5ff1b31 bellard
#endif
1648 2c0262af bellard
            } else {
1649 2c0262af bellard
                /* store */
1650 2c0262af bellard
                gen_movl_T0_reg(s, rd);
1651 b5ff1b31 bellard
#if defined(CONFIG_USER_ONLY)
1652 2c0262af bellard
                if (insn & (1 << 22))
1653 b5ff1b31 bellard
                    gen_op_stb_raw();
1654 2c0262af bellard
                else
1655 b5ff1b31 bellard
                    gen_op_stl_raw();
1656 b5ff1b31 bellard
#else
1657 b5ff1b31 bellard
                if (insn & (1 << 22)) {
1658 b5ff1b31 bellard
                    if (i)
1659 b5ff1b31 bellard
                        gen_op_stb_user();
1660 b5ff1b31 bellard
                    else
1661 b5ff1b31 bellard
                        gen_op_stb_kernel();
1662 b5ff1b31 bellard
                } else {
1663 b5ff1b31 bellard
                    if (i)
1664 b5ff1b31 bellard
                        gen_op_stl_user();
1665 b5ff1b31 bellard
                    else
1666 b5ff1b31 bellard
                        gen_op_stl_kernel();
1667 b5ff1b31 bellard
                }
1668 b5ff1b31 bellard
#endif
1669 2c0262af bellard
            }
1670 2c0262af bellard
            if (!(insn & (1 << 24))) {
1671 2c0262af bellard
                gen_add_data_offset(s, insn);
1672 2c0262af bellard
                gen_movl_reg_T1(s, rn);
1673 2c0262af bellard
            } else if (insn & (1 << 21))
1674 2c0262af bellard
                gen_movl_reg_T1(s, rn); {
1675 2c0262af bellard
            }
1676 5fd46862 pbrook
            if (insn & (1 << 20)) {
1677 5fd46862 pbrook
                /* Complete the load.  */
1678 5fd46862 pbrook
                if (rd == 15)
1679 5fd46862 pbrook
                    gen_bx(s);
1680 5fd46862 pbrook
                else
1681 5fd46862 pbrook
                    gen_movl_reg_T0(s, rd);
1682 5fd46862 pbrook
            }
1683 2c0262af bellard
            break;
1684 2c0262af bellard
        case 0x08:
1685 2c0262af bellard
        case 0x09:
1686 2c0262af bellard
            {
1687 191abaa2 pbrook
                int j, n, user, loaded_base;
1688 2c0262af bellard
                /* load/store multiple words */
1689 2c0262af bellard
                /* XXX: store correct base if write back */
1690 b5ff1b31 bellard
                user = 0;
1691 b5ff1b31 bellard
                if (insn & (1 << 22)) {
1692 b5ff1b31 bellard
                    if (IS_USER(s))
1693 b5ff1b31 bellard
                        goto illegal_op; /* only usable in supervisor mode */
1694 b5ff1b31 bellard
1695 b5ff1b31 bellard
                    if ((insn & (1 << 15)) == 0)
1696 b5ff1b31 bellard
                        user = 1;
1697 b5ff1b31 bellard
                }
1698 2c0262af bellard
                rn = (insn >> 16) & 0xf;
1699 2c0262af bellard
                gen_movl_T1_reg(s, rn);
1700 2c0262af bellard
                
1701 2c0262af bellard
                /* compute total size */
1702 191abaa2 pbrook
                loaded_base = 0;
1703 2c0262af bellard
                n = 0;
1704 2c0262af bellard
                for(i=0;i<16;i++) {
1705 2c0262af bellard
                    if (insn & (1 << i))
1706 2c0262af bellard
                        n++;
1707 2c0262af bellard
                }
1708 2c0262af bellard
                /* XXX: test invalid n == 0 case ? */
1709 2c0262af bellard
                if (insn & (1 << 23)) {
1710 2c0262af bellard
                    if (insn & (1 << 24)) {
1711 2c0262af bellard
                        /* pre increment */
1712 2c0262af bellard
                        gen_op_addl_T1_im(4);
1713 2c0262af bellard
                    } else {
1714 2c0262af bellard
                        /* post increment */
1715 2c0262af bellard
                    }
1716 2c0262af bellard
                } else {
1717 2c0262af bellard
                    if (insn & (1 << 24)) {
1718 2c0262af bellard
                        /* pre decrement */
1719 2c0262af bellard
                        gen_op_addl_T1_im(-(n * 4));
1720 2c0262af bellard
                    } else {
1721 2c0262af bellard
                        /* post decrement */
1722 2c0262af bellard
                        if (n != 1)
1723 2c0262af bellard
                            gen_op_addl_T1_im(-((n - 1) * 4));
1724 2c0262af bellard
                    }
1725 2c0262af bellard
                }
1726 2c0262af bellard
                j = 0;
1727 2c0262af bellard
                for(i=0;i<16;i++) {
1728 2c0262af bellard
                    if (insn & (1 << i)) {
1729 2c0262af bellard
                        if (insn & (1 << 20)) {
1730 2c0262af bellard
                            /* load */
1731 b5ff1b31 bellard
                            gen_ldst(ldl, s);
1732 b5ff1b31 bellard
                            if (i == 15) {
1733 99c475ab bellard
                                gen_bx(s);
1734 b5ff1b31 bellard
                            } else if (user) {
1735 b5ff1b31 bellard
                                gen_op_movl_user_T0(i);
1736 191abaa2 pbrook
                            } else if (i == rn) {
1737 191abaa2 pbrook
                                gen_op_movl_T2_T0();
1738 191abaa2 pbrook
                                loaded_base = 1;
1739 b5ff1b31 bellard
                            } else {
1740 99c475ab bellard
                                gen_movl_reg_T0(s, i);
1741 b5ff1b31 bellard
                            }
1742 2c0262af bellard
                        } else {
1743 2c0262af bellard
                            /* store */
1744 2c0262af bellard
                            if (i == 15) {
1745 2c0262af bellard
                                /* special case: r15 = PC + 12 */
1746 2c0262af bellard
                                val = (long)s->pc + 8;
1747 2c0262af bellard
                                gen_op_movl_TN_im[0](val);
1748 b5ff1b31 bellard
                            } else if (user) {
1749 b5ff1b31 bellard
                                gen_op_movl_T0_user(i);
1750 2c0262af bellard
                            } else {
1751 2c0262af bellard
                                gen_movl_T0_reg(s, i);
1752 2c0262af bellard
                            }
1753 b5ff1b31 bellard
                            gen_ldst(stl, s);
1754 2c0262af bellard
                        }
1755 2c0262af bellard
                        j++;
1756 2c0262af bellard
                        /* no need to add after the last transfer */
1757 2c0262af bellard
                        if (j != n)
1758 2c0262af bellard
                            gen_op_addl_T1_im(4);
1759 2c0262af bellard
                    }
1760 2c0262af bellard
                }
1761 2c0262af bellard
                if (insn & (1 << 21)) {
1762 2c0262af bellard
                    /* write back */
1763 2c0262af bellard
                    if (insn & (1 << 23)) {
1764 2c0262af bellard
                        if (insn & (1 << 24)) {
1765 2c0262af bellard
                            /* pre increment */
1766 2c0262af bellard
                        } else {
1767 2c0262af bellard
                            /* post increment */
1768 2c0262af bellard
                            gen_op_addl_T1_im(4);
1769 2c0262af bellard
                        }
1770 2c0262af bellard
                    } else {
1771 2c0262af bellard
                        if (insn & (1 << 24)) {
1772 2c0262af bellard
                            /* pre decrement */
1773 2c0262af bellard
                            if (n != 1)
1774 2c0262af bellard
                                gen_op_addl_T1_im(-((n - 1) * 4));
1775 2c0262af bellard
                        } else {
1776 2c0262af bellard
                            /* post decrement */
1777 2c0262af bellard
                            gen_op_addl_T1_im(-(n * 4));
1778 2c0262af bellard
                        }
1779 2c0262af bellard
                    }
1780 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1781 2c0262af bellard
                }
1782 191abaa2 pbrook
                if (loaded_base) {
1783 191abaa2 pbrook
                    gen_op_movl_T0_T2();
1784 191abaa2 pbrook
                    gen_movl_reg_T0(s, rn);
1785 191abaa2 pbrook
                }
1786 b5ff1b31 bellard
                if ((insn & (1 << 22)) && !user) {
1787 b5ff1b31 bellard
                    /* Restore CPSR from SPSR.  */
1788 b5ff1b31 bellard
                    gen_op_movl_T0_spsr();
1789 b5ff1b31 bellard
                    gen_op_movl_cpsr_T0(0xffffffff);
1790 b5ff1b31 bellard
                    s->is_jmp = DISAS_UPDATE;
1791 b5ff1b31 bellard
                }
1792 2c0262af bellard
            }
1793 2c0262af bellard
            break;
1794 2c0262af bellard
        case 0xa:
1795 2c0262af bellard
        case 0xb:
1796 2c0262af bellard
            {
1797 99c475ab bellard
                int32_t offset;
1798 2c0262af bellard
                
1799 2c0262af bellard
                /* branch (and link) */
1800 99c475ab bellard
                val = (int32_t)s->pc;
1801 2c0262af bellard
                if (insn & (1 << 24)) {
1802 2c0262af bellard
                    gen_op_movl_T0_im(val);
1803 2c0262af bellard
                    gen_op_movl_reg_TN[0][14]();
1804 2c0262af bellard
                }
1805 99c475ab bellard
                offset = (((int32_t)insn << 8) >> 8);
1806 2c0262af bellard
                val += (offset << 2) + 4;
1807 8aaca4c0 bellard
                gen_jmp(s, val);
1808 2c0262af bellard
            }
1809 2c0262af bellard
            break;
1810 b7bcbe95 bellard
        case 0xc:
1811 b7bcbe95 bellard
        case 0xd:
1812 b7bcbe95 bellard
        case 0xe:
1813 b7bcbe95 bellard
            /* Coprocessor.  */
1814 b7bcbe95 bellard
            op1 = (insn >> 8) & 0xf;
1815 b7bcbe95 bellard
            switch (op1) {
1816 b7bcbe95 bellard
            case 10:
1817 b7bcbe95 bellard
            case 11:
1818 b7bcbe95 bellard
                if (disas_vfp_insn (env, s, insn))
1819 b7bcbe95 bellard
                    goto illegal_op;
1820 b7bcbe95 bellard
                break;
1821 b5ff1b31 bellard
            case 15:
1822 b5ff1b31 bellard
                if (disas_cp15_insn (s, insn))
1823 b5ff1b31 bellard
                    goto illegal_op;
1824 b5ff1b31 bellard
                break;
1825 b7bcbe95 bellard
            default:
1826 b7bcbe95 bellard
                /* unknown coprocessor.  */
1827 b7bcbe95 bellard
                goto illegal_op;
1828 b7bcbe95 bellard
            }
1829 b7bcbe95 bellard
            break;
1830 2c0262af bellard
        case 0xf:
1831 2c0262af bellard
            /* swi */
1832 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc);
1833 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
1834 2c0262af bellard
            gen_op_swi();
1835 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
1836 2c0262af bellard
            break;
1837 2c0262af bellard
        default:
1838 2c0262af bellard
        illegal_op:
1839 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc - 4);
1840 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
1841 2c0262af bellard
            gen_op_undef_insn();
1842 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
1843 2c0262af bellard
            break;
1844 2c0262af bellard
        }
1845 2c0262af bellard
    }
1846 2c0262af bellard
}
1847 2c0262af bellard
1848 99c475ab bellard
static void disas_thumb_insn(DisasContext *s)
1849 99c475ab bellard
{
1850 99c475ab bellard
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1851 99c475ab bellard
    int32_t offset;
1852 99c475ab bellard
    int i;
1853 99c475ab bellard
1854 b5ff1b31 bellard
    insn = lduw_code(s->pc);
1855 99c475ab bellard
    s->pc += 2;
1856 b5ff1b31 bellard
1857 99c475ab bellard
    switch (insn >> 12) {
1858 99c475ab bellard
    case 0: case 1:
1859 99c475ab bellard
        rd = insn & 7;
1860 99c475ab bellard
        op = (insn >> 11) & 3;
1861 99c475ab bellard
        if (op == 3) {
1862 99c475ab bellard
            /* add/subtract */
1863 99c475ab bellard
            rn = (insn >> 3) & 7;
1864 99c475ab bellard
            gen_movl_T0_reg(s, rn);
1865 99c475ab bellard
            if (insn & (1 << 10)) {
1866 99c475ab bellard
                /* immediate */
1867 99c475ab bellard
                gen_op_movl_T1_im((insn >> 6) & 7);
1868 99c475ab bellard
            } else {
1869 99c475ab bellard
                /* reg */
1870 99c475ab bellard
                rm = (insn >> 6) & 7;
1871 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1872 99c475ab bellard
            }
1873 99c475ab bellard
            if (insn & (1 << 9))
1874 5899f386 bellard
                gen_op_subl_T0_T1_cc();
1875 99c475ab bellard
            else
1876 99c475ab bellard
                gen_op_addl_T0_T1_cc();
1877 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1878 99c475ab bellard
        } else {
1879 99c475ab bellard
            /* shift immediate */
1880 99c475ab bellard
            rm = (insn >> 3) & 7;
1881 99c475ab bellard
            shift = (insn >> 6) & 0x1f;
1882 99c475ab bellard
            gen_movl_T0_reg(s, rm);
1883 99c475ab bellard
            gen_shift_T0_im_thumb[op](shift);
1884 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1885 99c475ab bellard
        }
1886 99c475ab bellard
        break;
1887 99c475ab bellard
    case 2: case 3:
1888 99c475ab bellard
        /* arithmetic large immediate */
1889 99c475ab bellard
        op = (insn >> 11) & 3;
1890 99c475ab bellard
        rd = (insn >> 8) & 0x7;
1891 99c475ab bellard
        if (op == 0) {
1892 99c475ab bellard
            gen_op_movl_T0_im(insn & 0xff);
1893 99c475ab bellard
        } else {
1894 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1895 99c475ab bellard
            gen_op_movl_T1_im(insn & 0xff);
1896 99c475ab bellard
        }
1897 99c475ab bellard
        switch (op) {
1898 99c475ab bellard
        case 0: /* mov */
1899 99c475ab bellard
            gen_op_logic_T0_cc();
1900 99c475ab bellard
            break;
1901 99c475ab bellard
        case 1: /* cmp */
1902 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1903 99c475ab bellard
            break;
1904 99c475ab bellard
        case 2: /* add */
1905 99c475ab bellard
            gen_op_addl_T0_T1_cc();
1906 99c475ab bellard
            break;
1907 99c475ab bellard
        case 3: /* sub */
1908 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1909 99c475ab bellard
            break;
1910 99c475ab bellard
        }
1911 99c475ab bellard
        if (op != 1)
1912 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1913 99c475ab bellard
        break;
1914 99c475ab bellard
    case 4:
1915 99c475ab bellard
        if (insn & (1 << 11)) {
1916 99c475ab bellard
            rd = (insn >> 8) & 7;
1917 5899f386 bellard
            /* load pc-relative.  Bit 1 of PC is ignored.  */
1918 5899f386 bellard
            val = s->pc + 2 + ((insn & 0xff) * 4);
1919 5899f386 bellard
            val &= ~(uint32_t)2;
1920 99c475ab bellard
            gen_op_movl_T1_im(val);
1921 b5ff1b31 bellard
            gen_ldst(ldl, s);
1922 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1923 99c475ab bellard
            break;
1924 99c475ab bellard
        }
1925 99c475ab bellard
        if (insn & (1 << 10)) {
1926 99c475ab bellard
            /* data processing extended or blx */
1927 99c475ab bellard
            rd = (insn & 7) | ((insn >> 4) & 8);
1928 99c475ab bellard
            rm = (insn >> 3) & 0xf;
1929 99c475ab bellard
            op = (insn >> 8) & 3;
1930 99c475ab bellard
            switch (op) {
1931 99c475ab bellard
            case 0: /* add */
1932 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1933 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1934 99c475ab bellard
                gen_op_addl_T0_T1();
1935 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1936 99c475ab bellard
                break;
1937 99c475ab bellard
            case 1: /* cmp */
1938 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1939 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1940 99c475ab bellard
                gen_op_subl_T0_T1_cc();
1941 99c475ab bellard
                break;
1942 99c475ab bellard
            case 2: /* mov/cpy */
1943 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1944 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1945 99c475ab bellard
                break;
1946 99c475ab bellard
            case 3:/* branch [and link] exchange thumb register */
1947 99c475ab bellard
                if (insn & (1 << 7)) {
1948 99c475ab bellard
                    val = (uint32_t)s->pc | 1;
1949 99c475ab bellard
                    gen_op_movl_T1_im(val);
1950 99c475ab bellard
                    gen_movl_reg_T1(s, 14);
1951 99c475ab bellard
                }
1952 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1953 99c475ab bellard
                gen_bx(s);
1954 99c475ab bellard
                break;
1955 99c475ab bellard
            }
1956 99c475ab bellard
            break;
1957 99c475ab bellard
        }
1958 99c475ab bellard
1959 99c475ab bellard
        /* data processing register */
1960 99c475ab bellard
        rd = insn & 7;
1961 99c475ab bellard
        rm = (insn >> 3) & 7;
1962 99c475ab bellard
        op = (insn >> 6) & 0xf;
1963 99c475ab bellard
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1964 99c475ab bellard
            /* the shift/rotate ops want the operands backwards */
1965 99c475ab bellard
            val = rm;
1966 99c475ab bellard
            rm = rd;
1967 99c475ab bellard
            rd = val;
1968 99c475ab bellard
            val = 1;
1969 99c475ab bellard
        } else {
1970 99c475ab bellard
            val = 0;
1971 99c475ab bellard
        }
1972 99c475ab bellard
1973 99c475ab bellard
        if (op == 9) /* neg */
1974 99c475ab bellard
            gen_op_movl_T0_im(0);
1975 99c475ab bellard
        else if (op != 0xf) /* mvn doesn't read its first operand */
1976 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1977 99c475ab bellard
1978 99c475ab bellard
        gen_movl_T1_reg(s, rm);
1979 5899f386 bellard
        switch (op) {
1980 99c475ab bellard
        case 0x0: /* and */
1981 99c475ab bellard
            gen_op_andl_T0_T1();
1982 99c475ab bellard
            gen_op_logic_T0_cc();
1983 99c475ab bellard
            break;
1984 99c475ab bellard
        case 0x1: /* eor */
1985 99c475ab bellard
            gen_op_xorl_T0_T1();
1986 99c475ab bellard
            gen_op_logic_T0_cc();
1987 99c475ab bellard
            break;
1988 99c475ab bellard
        case 0x2: /* lsl */
1989 99c475ab bellard
            gen_op_shll_T1_T0_cc();
1990 3aa22b4b pbrook
            gen_op_logic_T1_cc();
1991 99c475ab bellard
            break;
1992 99c475ab bellard
        case 0x3: /* lsr */
1993 99c475ab bellard
            gen_op_shrl_T1_T0_cc();
1994 3aa22b4b pbrook
            gen_op_logic_T1_cc();
1995 99c475ab bellard
            break;
1996 99c475ab bellard
        case 0x4: /* asr */
1997 99c475ab bellard
            gen_op_sarl_T1_T0_cc();
1998 3aa22b4b pbrook
            gen_op_logic_T1_cc();
1999 99c475ab bellard
            break;
2000 99c475ab bellard
        case 0x5: /* adc */
2001 99c475ab bellard
            gen_op_adcl_T0_T1_cc();
2002 99c475ab bellard
            break;
2003 99c475ab bellard
        case 0x6: /* sbc */
2004 99c475ab bellard
            gen_op_sbcl_T0_T1_cc();
2005 99c475ab bellard
            break;
2006 99c475ab bellard
        case 0x7: /* ror */
2007 99c475ab bellard
            gen_op_rorl_T1_T0_cc();
2008 3aa22b4b pbrook
            gen_op_logic_T1_cc();
2009 99c475ab bellard
            break;
2010 99c475ab bellard
        case 0x8: /* tst */
2011 99c475ab bellard
            gen_op_andl_T0_T1();
2012 99c475ab bellard
            gen_op_logic_T0_cc();
2013 99c475ab bellard
            rd = 16;
2014 5899f386 bellard
            break;
2015 99c475ab bellard
        case 0x9: /* neg */
2016 5899f386 bellard
            gen_op_subl_T0_T1_cc();
2017 99c475ab bellard
            break;
2018 99c475ab bellard
        case 0xa: /* cmp */
2019 99c475ab bellard
            gen_op_subl_T0_T1_cc();
2020 99c475ab bellard
            rd = 16;
2021 99c475ab bellard
            break;
2022 99c475ab bellard
        case 0xb: /* cmn */
2023 99c475ab bellard
            gen_op_addl_T0_T1_cc();
2024 99c475ab bellard
            rd = 16;
2025 99c475ab bellard
            break;
2026 99c475ab bellard
        case 0xc: /* orr */
2027 99c475ab bellard
            gen_op_orl_T0_T1();
2028 99c475ab bellard
            gen_op_logic_T0_cc();
2029 99c475ab bellard
            break;
2030 99c475ab bellard
        case 0xd: /* mul */
2031 99c475ab bellard
            gen_op_mull_T0_T1();
2032 99c475ab bellard
            gen_op_logic_T0_cc();
2033 99c475ab bellard
            break;
2034 99c475ab bellard
        case 0xe: /* bic */
2035 99c475ab bellard
            gen_op_bicl_T0_T1();
2036 99c475ab bellard
            gen_op_logic_T0_cc();
2037 99c475ab bellard
            break;
2038 99c475ab bellard
        case 0xf: /* mvn */
2039 99c475ab bellard
            gen_op_notl_T1();
2040 99c475ab bellard
            gen_op_logic_T1_cc();
2041 99c475ab bellard
            val = 1;
2042 5899f386 bellard
            rm = rd;
2043 99c475ab bellard
            break;
2044 99c475ab bellard
        }
2045 99c475ab bellard
        if (rd != 16) {
2046 99c475ab bellard
            if (val)
2047 5899f386 bellard
                gen_movl_reg_T1(s, rm);
2048 99c475ab bellard
            else
2049 99c475ab bellard
                gen_movl_reg_T0(s, rd);
2050 99c475ab bellard
        }
2051 99c475ab bellard
        break;
2052 99c475ab bellard
2053 99c475ab bellard
    case 5:
2054 99c475ab bellard
        /* load/store register offset.  */
2055 99c475ab bellard
        rd = insn & 7;
2056 99c475ab bellard
        rn = (insn >> 3) & 7;
2057 99c475ab bellard
        rm = (insn >> 6) & 7;
2058 99c475ab bellard
        op = (insn >> 9) & 7;
2059 99c475ab bellard
        gen_movl_T1_reg(s, rn);
2060 99c475ab bellard
        gen_movl_T2_reg(s, rm);
2061 99c475ab bellard
        gen_op_addl_T1_T2();
2062 99c475ab bellard
2063 99c475ab bellard
        if (op < 3) /* store */
2064 99c475ab bellard
            gen_movl_T0_reg(s, rd);
2065 99c475ab bellard
2066 99c475ab bellard
        switch (op) {
2067 99c475ab bellard
        case 0: /* str */
2068 b5ff1b31 bellard
            gen_ldst(stl, s);
2069 99c475ab bellard
            break;
2070 99c475ab bellard
        case 1: /* strh */
2071 b5ff1b31 bellard
            gen_ldst(stw, s);
2072 99c475ab bellard
            break;
2073 99c475ab bellard
        case 2: /* strb */
2074 b5ff1b31 bellard
            gen_ldst(stb, s);
2075 99c475ab bellard
            break;
2076 99c475ab bellard
        case 3: /* ldrsb */
2077 b5ff1b31 bellard
            gen_ldst(ldsb, s);
2078 99c475ab bellard
            break;
2079 99c475ab bellard
        case 4: /* ldr */
2080 b5ff1b31 bellard
            gen_ldst(ldl, s);
2081 99c475ab bellard
            break;
2082 99c475ab bellard
        case 5: /* ldrh */
2083 b5ff1b31 bellard
            gen_ldst(lduw, s);
2084 99c475ab bellard
            break;
2085 99c475ab bellard
        case 6: /* ldrb */
2086 b5ff1b31 bellard
            gen_ldst(ldub, s);
2087 99c475ab bellard
            break;
2088 99c475ab bellard
        case 7: /* ldrsh */
2089 b5ff1b31 bellard
            gen_ldst(ldsw, s);
2090 99c475ab bellard
            break;
2091 99c475ab bellard
        }
2092 99c475ab bellard
        if (op >= 3) /* load */
2093 99c475ab bellard
            gen_movl_reg_T0(s, rd);
2094 99c475ab bellard
        break;
2095 99c475ab bellard
2096 99c475ab bellard
    case 6:
2097 99c475ab bellard
        /* load/store word immediate offset */
2098 99c475ab bellard
        rd = insn & 7;
2099 99c475ab bellard
        rn = (insn >> 3) & 7;
2100 99c475ab bellard
        gen_movl_T1_reg(s, rn);
2101 99c475ab bellard
        val = (insn >> 4) & 0x7c;
2102 99c475ab bellard
        gen_op_movl_T2_im(val);
2103 99c475ab bellard
        gen_op_addl_T1_T2();
2104 99c475ab bellard
2105 99c475ab bellard
        if (insn & (1 << 11)) {
2106 99c475ab bellard
            /* load */
2107 b5ff1b31 bellard
            gen_ldst(ldl, s);
2108 99c475ab bellard
            gen_movl_reg_T0(s, rd);
2109 99c475ab bellard
        } else {
2110 99c475ab bellard
            /* store */
2111 99c475ab bellard
            gen_movl_T0_reg(s, rd);
2112 b5ff1b31 bellard
            gen_ldst(stl, s);
2113 99c475ab bellard
        }
2114 99c475ab bellard
        break;
2115 99c475ab bellard
2116 99c475ab bellard
    case 7:
2117 99c475ab bellard
        /* load/store byte immediate offset */
2118 99c475ab bellard
        rd = insn & 7;
2119 99c475ab bellard
        rn = (insn >> 3) & 7;
2120 99c475ab bellard
        gen_movl_T1_reg(s, rn);
2121 99c475ab bellard
        val = (insn >> 6) & 0x1f;
2122 99c475ab bellard
        gen_op_movl_T2_im(val);
2123 99c475ab bellard
        gen_op_addl_T1_T2();
2124 99c475ab bellard
2125 99c475ab bellard
        if (insn & (1 << 11)) {
2126 99c475ab bellard
            /* load */
2127 b5ff1b31 bellard
            gen_ldst(ldub, s);
2128 99c475ab bellard
            gen_movl_reg_T0(s, rd);
2129 99c475ab bellard
        } else {
2130 99c475ab bellard
            /* store */
2131 99c475ab bellard
            gen_movl_T0_reg(s, rd);
2132 b5ff1b31 bellard
            gen_ldst(stb, s);
2133 99c475ab bellard
        }
2134 99c475ab bellard
        break;
2135 99c475ab bellard
2136 99c475ab bellard
    case 8:
2137 99c475ab bellard
        /* load/store halfword immediate offset */
2138 99c475ab bellard
        rd = insn & 7;
2139 99c475ab bellard
        rn = (insn >> 3) & 7;
2140 99c475ab bellard
        gen_movl_T1_reg(s, rn);
2141 99c475ab bellard
        val = (insn >> 5) & 0x3e;
2142 99c475ab bellard
        gen_op_movl_T2_im(val);
2143 99c475ab bellard
        gen_op_addl_T1_T2();
2144 99c475ab bellard
2145 99c475ab bellard
        if (insn & (1 << 11)) {
2146 99c475ab bellard
            /* load */
2147 b5ff1b31 bellard
            gen_ldst(lduw, s);
2148 99c475ab bellard
            gen_movl_reg_T0(s, rd);
2149 99c475ab bellard
        } else {
2150 99c475ab bellard
            /* store */
2151 99c475ab bellard
            gen_movl_T0_reg(s, rd);
2152 b5ff1b31 bellard
            gen_ldst(stw, s);
2153 99c475ab bellard
        }
2154 99c475ab bellard
        break;
2155 99c475ab bellard
2156 99c475ab bellard
    case 9:
2157 99c475ab bellard
        /* load/store from stack */
2158 99c475ab bellard
        rd = (insn >> 8) & 7;
2159 99c475ab bellard
        gen_movl_T1_reg(s, 13);
2160 99c475ab bellard
        val = (insn & 0xff) * 4;
2161 99c475ab bellard
        gen_op_movl_T2_im(val);
2162 99c475ab bellard
        gen_op_addl_T1_T2();
2163 99c475ab bellard
2164 99c475ab bellard
        if (insn & (1 << 11)) {
2165 99c475ab bellard
            /* load */
2166 b5ff1b31 bellard
            gen_ldst(ldl, s);
2167 99c475ab bellard
            gen_movl_reg_T0(s, rd);
2168 99c475ab bellard
        } else {
2169 99c475ab bellard
            /* store */
2170 99c475ab bellard
            gen_movl_T0_reg(s, rd);
2171 b5ff1b31 bellard
            gen_ldst(stl, s);
2172 99c475ab bellard
        }
2173 99c475ab bellard
        break;
2174 99c475ab bellard
2175 99c475ab bellard
    case 10:
2176 99c475ab bellard
        /* add to high reg */
2177 99c475ab bellard
        rd = (insn >> 8) & 7;
2178 5899f386 bellard
        if (insn & (1 << 11)) {
2179 5899f386 bellard
            /* SP */
2180 5899f386 bellard
            gen_movl_T0_reg(s, 13);
2181 5899f386 bellard
        } else {
2182 5899f386 bellard
            /* PC. bit 1 is ignored.  */
2183 5899f386 bellard
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
2184 5899f386 bellard
        }
2185 99c475ab bellard
        val = (insn & 0xff) * 4;
2186 99c475ab bellard
        gen_op_movl_T1_im(val);
2187 99c475ab bellard
        gen_op_addl_T0_T1();
2188 99c475ab bellard
        gen_movl_reg_T0(s, rd);
2189 99c475ab bellard
        break;
2190 99c475ab bellard
2191 99c475ab bellard
    case 11:
2192 99c475ab bellard
        /* misc */
2193 99c475ab bellard
        op = (insn >> 8) & 0xf;
2194 99c475ab bellard
        switch (op) {
2195 99c475ab bellard
        case 0:
2196 99c475ab bellard
            /* adjust stack pointer */
2197 99c475ab bellard
            gen_movl_T1_reg(s, 13);
2198 99c475ab bellard
            val = (insn & 0x7f) * 4;
2199 99c475ab bellard
            if (insn & (1 << 7))
2200 99c475ab bellard
              val = -(int32_t)val;
2201 99c475ab bellard
            gen_op_movl_T2_im(val);
2202 99c475ab bellard
            gen_op_addl_T1_T2();
2203 99c475ab bellard
            gen_movl_reg_T1(s, 13);
2204 99c475ab bellard
            break;
2205 99c475ab bellard
2206 99c475ab bellard
        case 4: case 5: case 0xc: case 0xd:
2207 99c475ab bellard
            /* push/pop */
2208 99c475ab bellard
            gen_movl_T1_reg(s, 13);
2209 5899f386 bellard
            if (insn & (1 << 8))
2210 5899f386 bellard
                offset = 4;
2211 99c475ab bellard
            else
2212 5899f386 bellard
                offset = 0;
2213 5899f386 bellard
            for (i = 0; i < 8; i++) {
2214 5899f386 bellard
                if (insn & (1 << i))
2215 5899f386 bellard
                    offset += 4;
2216 5899f386 bellard
            }
2217 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
2218 5899f386 bellard
                gen_op_movl_T2_im(-offset);
2219 5899f386 bellard
                gen_op_addl_T1_T2();
2220 5899f386 bellard
            }
2221 5899f386 bellard
            gen_op_movl_T2_im(4);
2222 99c475ab bellard
            for (i = 0; i < 8; i++) {
2223 99c475ab bellard
                if (insn & (1 << i)) {
2224 99c475ab bellard
                    if (insn & (1 << 11)) {
2225 99c475ab bellard
                        /* pop */
2226 b5ff1b31 bellard
                        gen_ldst(ldl, s);
2227 99c475ab bellard
                        gen_movl_reg_T0(s, i);
2228 99c475ab bellard
                    } else {
2229 99c475ab bellard
                        /* push */
2230 99c475ab bellard
                        gen_movl_T0_reg(s, i);
2231 b5ff1b31 bellard
                        gen_ldst(stl, s);
2232 99c475ab bellard
                    }
2233 5899f386 bellard
                    /* advance to the next address.  */
2234 99c475ab bellard
                    gen_op_addl_T1_T2();
2235 99c475ab bellard
                }
2236 99c475ab bellard
            }
2237 99c475ab bellard
            if (insn & (1 << 8)) {
2238 99c475ab bellard
                if (insn & (1 << 11)) {
2239 99c475ab bellard
                    /* pop pc */
2240 b5ff1b31 bellard
                    gen_ldst(ldl, s);
2241 99c475ab bellard
                    /* don't set the pc until the rest of the instruction
2242 99c475ab bellard
                       has completed */
2243 99c475ab bellard
                } else {
2244 99c475ab bellard
                    /* push lr */
2245 99c475ab bellard
                    gen_movl_T0_reg(s, 14);
2246 b5ff1b31 bellard
                    gen_ldst(stl, s);
2247 99c475ab bellard
                }
2248 99c475ab bellard
                gen_op_addl_T1_T2();
2249 99c475ab bellard
            }
2250 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
2251 5899f386 bellard
                gen_op_movl_T2_im(-offset);
2252 5899f386 bellard
                gen_op_addl_T1_T2();
2253 5899f386 bellard
            }
2254 99c475ab bellard
            /* write back the new stack pointer */
2255 99c475ab bellard
            gen_movl_reg_T1(s, 13);
2256 99c475ab bellard
            /* set the new PC value */
2257 99c475ab bellard
            if ((insn & 0x0900) == 0x0900)
2258 99c475ab bellard
                gen_bx(s);
2259 99c475ab bellard
            break;
2260 99c475ab bellard
2261 06c949e6 pbrook
        case 0xe: /* bkpt */
2262 06c949e6 pbrook
            gen_op_movl_T0_im((long)s->pc - 2);
2263 06c949e6 pbrook
            gen_op_movl_reg_TN[0][15]();
2264 06c949e6 pbrook
            gen_op_bkpt();
2265 06c949e6 pbrook
            s->is_jmp = DISAS_JUMP;
2266 06c949e6 pbrook
            break;
2267 06c949e6 pbrook
2268 99c475ab bellard
        default:
2269 99c475ab bellard
            goto undef;
2270 99c475ab bellard
        }
2271 99c475ab bellard
        break;
2272 99c475ab bellard
2273 99c475ab bellard
    case 12:
2274 99c475ab bellard
        /* load/store multiple */
2275 99c475ab bellard
        rn = (insn >> 8) & 0x7;
2276 99c475ab bellard
        gen_movl_T1_reg(s, rn);
2277 99c475ab bellard
        gen_op_movl_T2_im(4);
2278 99c475ab bellard
        for (i = 0; i < 8; i++) {
2279 99c475ab bellard
            if (insn & (1 << i)) {
2280 99c475ab bellard
                if (insn & (1 << 11)) {
2281 99c475ab bellard
                    /* load */
2282 b5ff1b31 bellard
                    gen_ldst(ldl, s);
2283 99c475ab bellard
                    gen_movl_reg_T0(s, i);
2284 99c475ab bellard
                } else {
2285 99c475ab bellard
                    /* store */
2286 99c475ab bellard
                    gen_movl_T0_reg(s, i);
2287 b5ff1b31 bellard
                    gen_ldst(stl, s);
2288 99c475ab bellard
                }
2289 5899f386 bellard
                /* advance to the next address */
2290 5899f386 bellard
                gen_op_addl_T1_T2();
2291 99c475ab bellard
            }
2292 99c475ab bellard
        }
2293 5899f386 bellard
        /* Base register writeback.  */
2294 b5ff1b31 bellard
        if ((insn & (1 << rn)) == 0)
2295 b5ff1b31 bellard
            gen_movl_reg_T1(s, rn);
2296 99c475ab bellard
        break;
2297 99c475ab bellard
2298 99c475ab bellard
    case 13:
2299 99c475ab bellard
        /* conditional branch or swi */
2300 99c475ab bellard
        cond = (insn >> 8) & 0xf;
2301 99c475ab bellard
        if (cond == 0xe)
2302 99c475ab bellard
            goto undef;
2303 99c475ab bellard
2304 99c475ab bellard
        if (cond == 0xf) {
2305 99c475ab bellard
            /* swi */
2306 99c475ab bellard
            gen_op_movl_T0_im((long)s->pc | 1);
2307 99c475ab bellard
            /* Don't set r15.  */
2308 99c475ab bellard
            gen_op_movl_reg_TN[0][15]();
2309 99c475ab bellard
            gen_op_swi();
2310 99c475ab bellard
            s->is_jmp = DISAS_JUMP;
2311 99c475ab bellard
            break;
2312 99c475ab bellard
        }
2313 99c475ab bellard
        /* generate a conditional jump to next instruction */
2314 e50e6a20 bellard
        s->condlabel = gen_new_label();
2315 e50e6a20 bellard
        gen_test_cc[cond ^ 1](s->condlabel);
2316 e50e6a20 bellard
        s->condjmp = 1;
2317 e50e6a20 bellard
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2318 e50e6a20 bellard
        //s->is_jmp = DISAS_JUMP_NEXT;
2319 99c475ab bellard
        gen_movl_T1_reg(s, 15);
2320 99c475ab bellard
2321 99c475ab bellard
        /* jump to the offset */
2322 5899f386 bellard
        val = (uint32_t)s->pc + 2;
2323 99c475ab bellard
        offset = ((int32_t)insn << 24) >> 24;
2324 5899f386 bellard
        val += offset << 1;
2325 8aaca4c0 bellard
        gen_jmp(s, val);
2326 99c475ab bellard
        break;
2327 99c475ab bellard
2328 99c475ab bellard
    case 14:
2329 99c475ab bellard
        /* unconditional branch */
2330 358bf29e pbrook
        if (insn & (1 << 11)) {
2331 358bf29e pbrook
            /* Second half of blx.  */
2332 358bf29e pbrook
            offset = ((insn & 0x7ff) << 1);
2333 358bf29e pbrook
            gen_movl_T0_reg(s, 14);
2334 358bf29e pbrook
            gen_op_movl_T1_im(offset);
2335 358bf29e pbrook
            gen_op_addl_T0_T1();
2336 358bf29e pbrook
            gen_op_movl_T1_im(0xfffffffc);
2337 358bf29e pbrook
            gen_op_andl_T0_T1();
2338 358bf29e pbrook
2339 358bf29e pbrook
            val = (uint32_t)s->pc;
2340 358bf29e pbrook
            gen_op_movl_T1_im(val | 1);
2341 358bf29e pbrook
            gen_movl_reg_T1(s, 14);
2342 358bf29e pbrook
            gen_bx(s);
2343 358bf29e pbrook
            break;
2344 358bf29e pbrook
        }
2345 99c475ab bellard
        val = (uint32_t)s->pc;
2346 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 21;
2347 99c475ab bellard
        val += (offset << 1) + 2;
2348 8aaca4c0 bellard
        gen_jmp(s, val);
2349 99c475ab bellard
        break;
2350 99c475ab bellard
2351 99c475ab bellard
    case 15:
2352 99c475ab bellard
        /* branch and link [and switch to arm] */
2353 358bf29e pbrook
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
2354 358bf29e pbrook
            /* Instruction spans a page boundary.  Implement it as two
2355 358bf29e pbrook
               16-bit instructions in case the second half causes an
2356 358bf29e pbrook
               prefetch abort.  */
2357 358bf29e pbrook
            offset = ((int32_t)insn << 21) >> 9;
2358 358bf29e pbrook
            val = s->pc + 2 + offset;
2359 358bf29e pbrook
            gen_op_movl_T0_im(val);
2360 358bf29e pbrook
            gen_movl_reg_T0(s, 14);
2361 358bf29e pbrook
            break;
2362 358bf29e pbrook
        }
2363 358bf29e pbrook
        if (insn & (1 << 11)) {
2364 358bf29e pbrook
            /* Second half of bl.  */
2365 358bf29e pbrook
            offset = ((insn & 0x7ff) << 1) | 1;
2366 358bf29e pbrook
            gen_movl_T0_reg(s, 14);
2367 358bf29e pbrook
            gen_op_movl_T1_im(offset);
2368 358bf29e pbrook
            gen_op_addl_T0_T1();
2369 358bf29e pbrook
2370 358bf29e pbrook
            val = (uint32_t)s->pc;
2371 358bf29e pbrook
            gen_op_movl_T1_im(val | 1);
2372 358bf29e pbrook
            gen_movl_reg_T1(s, 14);
2373 358bf29e pbrook
            gen_bx(s);
2374 358bf29e pbrook
            break;
2375 358bf29e pbrook
        }
2376 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 10;
2377 b5ff1b31 bellard
        insn = lduw_code(s->pc);
2378 99c475ab bellard
        offset |= insn & 0x7ff;
2379 99c475ab bellard
2380 99c475ab bellard
        val = (uint32_t)s->pc + 2;
2381 99c475ab bellard
        gen_op_movl_T1_im(val | 1);
2382 99c475ab bellard
        gen_movl_reg_T1(s, 14);
2383 99c475ab bellard
        
2384 5899f386 bellard
        val += offset << 1;
2385 2531fc7b bellard
        if (insn & (1 << 12)) {
2386 99c475ab bellard
            /* bl */
2387 8aaca4c0 bellard
            gen_jmp(s, val);
2388 99c475ab bellard
        } else {
2389 99c475ab bellard
            /* blx */
2390 5899f386 bellard
            val &= ~(uint32_t)2;
2391 99c475ab bellard
            gen_op_movl_T0_im(val);
2392 99c475ab bellard
            gen_bx(s);
2393 99c475ab bellard
        }
2394 99c475ab bellard
    }
2395 99c475ab bellard
    return;
2396 99c475ab bellard
undef:
2397 5899f386 bellard
    gen_op_movl_T0_im((long)s->pc - 2);
2398 99c475ab bellard
    gen_op_movl_reg_TN[0][15]();
2399 99c475ab bellard
    gen_op_undef_insn();
2400 99c475ab bellard
    s->is_jmp = DISAS_JUMP;
2401 99c475ab bellard
}
2402 99c475ab bellard
2403 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2404 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
2405 2c0262af bellard
   information for each intermediate instruction. */
2406 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env, 
2407 2c0262af bellard
                                                 TranslationBlock *tb, 
2408 2c0262af bellard
                                                 int search_pc)
2409 2c0262af bellard
{
2410 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
2411 2c0262af bellard
    uint16_t *gen_opc_end;
2412 2c0262af bellard
    int j, lj;
2413 0fa85d43 bellard
    target_ulong pc_start;
2414 b5ff1b31 bellard
    uint32_t next_page_start;
2415 2c0262af bellard
    
2416 2c0262af bellard
    /* generate intermediate code */
2417 0fa85d43 bellard
    pc_start = tb->pc;
2418 2c0262af bellard
       
2419 2c0262af bellard
    dc->tb = tb;
2420 2c0262af bellard
2421 2c0262af bellard
    gen_opc_ptr = gen_opc_buf;
2422 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2423 2c0262af bellard
    gen_opparam_ptr = gen_opparam_buf;
2424 2c0262af bellard
2425 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
2426 2c0262af bellard
    dc->pc = pc_start;
2427 8aaca4c0 bellard
    dc->singlestep_enabled = env->singlestep_enabled;
2428 e50e6a20 bellard
    dc->condjmp = 0;
2429 5899f386 bellard
    dc->thumb = env->thumb;
2430 6658ffb8 pbrook
    dc->is_mem = 0;
2431 b5ff1b31 bellard
#if !defined(CONFIG_USER_ONLY)
2432 b5ff1b31 bellard
    dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
2433 b5ff1b31 bellard
#endif
2434 b5ff1b31 bellard
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2435 e50e6a20 bellard
    nb_gen_labels = 0;
2436 2c0262af bellard
    lj = -1;
2437 2c0262af bellard
    do {
2438 1fddef4b bellard
        if (env->nb_breakpoints > 0) {
2439 1fddef4b bellard
            for(j = 0; j < env->nb_breakpoints; j++) {
2440 1fddef4b bellard
                if (env->breakpoints[j] == dc->pc) {
2441 1fddef4b bellard
                    gen_op_movl_T0_im((long)dc->pc);
2442 1fddef4b bellard
                    gen_op_movl_reg_TN[0][15]();
2443 1fddef4b bellard
                    gen_op_debug();
2444 1fddef4b bellard
                    dc->is_jmp = DISAS_JUMP;
2445 1fddef4b bellard
                    break;
2446 1fddef4b bellard
                }
2447 1fddef4b bellard
            }
2448 1fddef4b bellard
        }
2449 2c0262af bellard
        if (search_pc) {
2450 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
2451 2c0262af bellard
            if (lj < j) {
2452 2c0262af bellard
                lj++;
2453 2c0262af bellard
                while (lj < j)
2454 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
2455 2c0262af bellard
            }
2456 0fa85d43 bellard
            gen_opc_pc[lj] = dc->pc;
2457 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
2458 2c0262af bellard
        }
2459 e50e6a20 bellard
2460 99c475ab bellard
        if (env->thumb)
2461 99c475ab bellard
          disas_thumb_insn(dc);
2462 99c475ab bellard
        else
2463 b7bcbe95 bellard
          disas_arm_insn(env, dc);
2464 e50e6a20 bellard
2465 e50e6a20 bellard
        if (dc->condjmp && !dc->is_jmp) {
2466 e50e6a20 bellard
            gen_set_label(dc->condlabel);
2467 e50e6a20 bellard
            dc->condjmp = 0;
2468 e50e6a20 bellard
        }
2469 6658ffb8 pbrook
        /* Terminate the TB on memory ops if watchpoints are present.  */
2470 6658ffb8 pbrook
        /* FIXME: This should be replacd by the deterministic execution
2471 6658ffb8 pbrook
         * IRQ raising bits.  */
2472 6658ffb8 pbrook
        if (dc->is_mem && env->nb_watchpoints)
2473 6658ffb8 pbrook
            break;
2474 6658ffb8 pbrook
2475 e50e6a20 bellard
        /* Translation stops when a conditional branch is enoutered.
2476 e50e6a20 bellard
         * Otherwise the subsequent code could get translated several times.
2477 b5ff1b31 bellard
         * Also stop translation when a page boundary is reached.  This
2478 b5ff1b31 bellard
         * ensures prefech aborts occur at the right place.  */
2479 1fddef4b bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2480 1fddef4b bellard
             !env->singlestep_enabled &&
2481 b5ff1b31 bellard
             dc->pc < next_page_start);
2482 b5ff1b31 bellard
    /* At this stage dc->condjmp will only be set when the skipped
2483 b5ff1b31 bellard
     * instruction was a conditional branch, and the PC has already been
2484 e50e6a20 bellard
     * written.  */
2485 8aaca4c0 bellard
    if (__builtin_expect(env->singlestep_enabled, 0)) {
2486 8aaca4c0 bellard
        /* Make sure the pc is updated, and raise a debug exception.  */
2487 e50e6a20 bellard
        if (dc->condjmp) {
2488 e50e6a20 bellard
            gen_op_debug();
2489 e50e6a20 bellard
            gen_set_label(dc->condlabel);
2490 e50e6a20 bellard
        }
2491 e50e6a20 bellard
        if (dc->condjmp || !dc->is_jmp) {
2492 8aaca4c0 bellard
            gen_op_movl_T0_im((long)dc->pc);
2493 8aaca4c0 bellard
            gen_op_movl_reg_TN[0][15]();
2494 e50e6a20 bellard
            dc->condjmp = 0;
2495 8aaca4c0 bellard
        }
2496 8aaca4c0 bellard
        gen_op_debug();
2497 8aaca4c0 bellard
    } else {
2498 8aaca4c0 bellard
        switch(dc->is_jmp) {
2499 8aaca4c0 bellard
        case DISAS_NEXT:
2500 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
2501 8aaca4c0 bellard
            break;
2502 8aaca4c0 bellard
        default:
2503 8aaca4c0 bellard
        case DISAS_JUMP:
2504 8aaca4c0 bellard
        case DISAS_UPDATE:
2505 8aaca4c0 bellard
            /* indicate that the hash table must be used to find the next TB */
2506 8aaca4c0 bellard
            gen_op_movl_T0_0();
2507 8aaca4c0 bellard
            gen_op_exit_tb();
2508 8aaca4c0 bellard
            break;
2509 8aaca4c0 bellard
        case DISAS_TB_JUMP:
2510 8aaca4c0 bellard
            /* nothing more to generate */
2511 8aaca4c0 bellard
            break;
2512 8aaca4c0 bellard
        }
2513 e50e6a20 bellard
        if (dc->condjmp) {
2514 e50e6a20 bellard
            gen_set_label(dc->condlabel);
2515 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
2516 e50e6a20 bellard
            dc->condjmp = 0;
2517 e50e6a20 bellard
        }
2518 2c0262af bellard
    }
2519 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
2520 2c0262af bellard
2521 2c0262af bellard
#ifdef DEBUG_DISAS
2522 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2523 2c0262af bellard
        fprintf(logfile, "----------------\n");
2524 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2525 5899f386 bellard
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2526 2c0262af bellard
        fprintf(logfile, "\n");
2527 e19e89a5 bellard
        if (loglevel & (CPU_LOG_TB_OP)) {
2528 e19e89a5 bellard
            fprintf(logfile, "OP:\n");
2529 e19e89a5 bellard
            dump_ops(gen_opc_buf, gen_opparam_buf);
2530 e19e89a5 bellard
            fprintf(logfile, "\n");
2531 e19e89a5 bellard
        }
2532 2c0262af bellard
    }
2533 2c0262af bellard
#endif
2534 b5ff1b31 bellard
    if (search_pc) {
2535 b5ff1b31 bellard
        j = gen_opc_ptr - gen_opc_buf;
2536 b5ff1b31 bellard
        lj++;
2537 b5ff1b31 bellard
        while (lj <= j)
2538 b5ff1b31 bellard
            gen_opc_instr_start[lj++] = 0;
2539 b5ff1b31 bellard
        tb->size = 0;
2540 b5ff1b31 bellard
    } else {
2541 2c0262af bellard
        tb->size = dc->pc - pc_start;
2542 b5ff1b31 bellard
    }
2543 2c0262af bellard
    return 0;
2544 2c0262af bellard
}
2545 2c0262af bellard
2546 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2547 2c0262af bellard
{
2548 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
2549 2c0262af bellard
}
2550 2c0262af bellard
2551 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2552 2c0262af bellard
{
2553 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
2554 2c0262af bellard
}
2555 2c0262af bellard
2556 b5ff1b31 bellard
static const char *cpu_mode_names[16] = {
2557 b5ff1b31 bellard
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
2558 b5ff1b31 bellard
  "???", "???", "???", "und", "???", "???", "???", "sys"
2559 b5ff1b31 bellard
};
2560 7fe48483 bellard
void cpu_dump_state(CPUState *env, FILE *f, 
2561 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2562 7fe48483 bellard
                    int flags)
2563 2c0262af bellard
{
2564 2c0262af bellard
    int i;
2565 bc380d17 bellard
    union {
2566 b7bcbe95 bellard
        uint32_t i;
2567 b7bcbe95 bellard
        float s;
2568 b7bcbe95 bellard
    } s0, s1;
2569 b7bcbe95 bellard
    CPU_DoubleU d;
2570 a94a6abf pbrook
    /* ??? This assumes float64 and double have the same layout.
2571 a94a6abf pbrook
       Oh well, it's only debug dumps.  */
2572 a94a6abf pbrook
    union {
2573 a94a6abf pbrook
        float64 f64;
2574 a94a6abf pbrook
        double d;
2575 a94a6abf pbrook
    } d0;
2576 b5ff1b31 bellard
    uint32_t psr;
2577 2c0262af bellard
2578 2c0262af bellard
    for(i=0;i<16;i++) {
2579 7fe48483 bellard
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2580 2c0262af bellard
        if ((i % 4) == 3)
2581 7fe48483 bellard
            cpu_fprintf(f, "\n");
2582 2c0262af bellard
        else
2583 7fe48483 bellard
            cpu_fprintf(f, " ");
2584 2c0262af bellard
    }
2585 b5ff1b31 bellard
    psr = cpsr_read(env);
2586 b5ff1b31 bellard
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n", 
2587 b5ff1b31 bellard
                psr, 
2588 b5ff1b31 bellard
                psr & (1 << 31) ? 'N' : '-',
2589 b5ff1b31 bellard
                psr & (1 << 30) ? 'Z' : '-',
2590 b5ff1b31 bellard
                psr & (1 << 29) ? 'C' : '-',
2591 b5ff1b31 bellard
                psr & (1 << 28) ? 'V' : '-',
2592 b5ff1b31 bellard
                psr & CPSR_T ? 'T' : 'A', 
2593 b5ff1b31 bellard
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
2594 b7bcbe95 bellard
2595 b7bcbe95 bellard
    for (i = 0; i < 16; i++) {
2596 8e96005d bellard
        d.d = env->vfp.regs[i];
2597 8e96005d bellard
        s0.i = d.l.lower;
2598 8e96005d bellard
        s1.i = d.l.upper;
2599 a94a6abf pbrook
        d0.f64 = d.d;
2600 a94a6abf pbrook
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
2601 b7bcbe95 bellard
                    i * 2, (int)s0.i, s0.s,
2602 a94a6abf pbrook
                    i * 2 + 1, (int)s1.i, s1.s,
2603 b7bcbe95 bellard
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2604 a94a6abf pbrook
                    d0.d);
2605 b7bcbe95 bellard
    }
2606 40f137e1 pbrook
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
2607 2c0262af bellard
}