Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 3aa22b4b

History | View | Annotate | Download (74.5 kB)

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