Statistics
| Branch: | Revision:

root / target-arm / translate.c @ ea785922

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