Statistics
| Branch: | Revision:

root / target-arm / translate.c @ b7bcbe95

History | View | Annotate | Download (63.7 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 2c0262af bellard
/* internal defines */
32 2c0262af bellard
typedef struct DisasContext {
33 0fa85d43 bellard
    target_ulong pc;
34 2c0262af bellard
    int is_jmp;
35 2c0262af bellard
    struct TranslationBlock *tb;
36 2c0262af bellard
} DisasContext;
37 2c0262af bellard
38 2c0262af bellard
#define DISAS_JUMP_NEXT 4
39 2c0262af bellard
40 2c0262af bellard
/* XXX: move that elsewhere */
41 2c0262af bellard
static uint16_t *gen_opc_ptr;
42 2c0262af bellard
static uint32_t *gen_opparam_ptr;
43 2c0262af bellard
extern FILE *logfile;
44 2c0262af bellard
extern int loglevel;
45 2c0262af bellard
46 2c0262af bellard
enum {
47 2c0262af bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
48 2c0262af bellard
#include "opc.h"
49 2c0262af bellard
#undef DEF
50 2c0262af bellard
    NB_OPS,
51 2c0262af bellard
};
52 2c0262af bellard
53 2c0262af bellard
#include "gen-op.h"
54 2c0262af bellard
55 2c0262af bellard
static GenOpFunc2 *gen_test_cc[14] = {
56 2c0262af bellard
    gen_op_test_eq,
57 2c0262af bellard
    gen_op_test_ne,
58 2c0262af bellard
    gen_op_test_cs,
59 2c0262af bellard
    gen_op_test_cc,
60 2c0262af bellard
    gen_op_test_mi,
61 2c0262af bellard
    gen_op_test_pl,
62 2c0262af bellard
    gen_op_test_vs,
63 2c0262af bellard
    gen_op_test_vc,
64 2c0262af bellard
    gen_op_test_hi,
65 2c0262af bellard
    gen_op_test_ls,
66 2c0262af bellard
    gen_op_test_ge,
67 2c0262af bellard
    gen_op_test_lt,
68 2c0262af bellard
    gen_op_test_gt,
69 2c0262af bellard
    gen_op_test_le,
70 2c0262af bellard
};
71 2c0262af bellard
72 2c0262af bellard
const uint8_t table_logic_cc[16] = {
73 2c0262af bellard
    1, /* and */
74 2c0262af bellard
    1, /* xor */
75 2c0262af bellard
    0, /* sub */
76 2c0262af bellard
    0, /* rsb */
77 2c0262af bellard
    0, /* add */
78 2c0262af bellard
    0, /* adc */
79 2c0262af bellard
    0, /* sbc */
80 2c0262af bellard
    0, /* rsc */
81 2c0262af bellard
    1, /* andl */
82 2c0262af bellard
    1, /* xorl */
83 2c0262af bellard
    0, /* cmp */
84 2c0262af bellard
    0, /* cmn */
85 2c0262af bellard
    1, /* orr */
86 2c0262af bellard
    1, /* mov */
87 2c0262af bellard
    1, /* bic */
88 2c0262af bellard
    1, /* mvn */
89 2c0262af bellard
};
90 2c0262af bellard
    
91 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im[4] = {
92 2c0262af bellard
    gen_op_shll_T1_im,
93 2c0262af bellard
    gen_op_shrl_T1_im,
94 2c0262af bellard
    gen_op_sarl_T1_im,
95 2c0262af bellard
    gen_op_rorl_T1_im,
96 2c0262af bellard
};
97 2c0262af bellard
98 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0[4] = {
99 1e8d4eec bellard
    NULL,
100 1e8d4eec bellard
    gen_op_shrl_T1_0,
101 1e8d4eec bellard
    gen_op_sarl_T1_0,
102 1e8d4eec bellard
    gen_op_rrxl_T1,
103 1e8d4eec bellard
};
104 1e8d4eec bellard
105 2c0262af bellard
static GenOpFunc1 *gen_shift_T2_im[4] = {
106 2c0262af bellard
    gen_op_shll_T2_im,
107 2c0262af bellard
    gen_op_shrl_T2_im,
108 2c0262af bellard
    gen_op_sarl_T2_im,
109 2c0262af bellard
    gen_op_rorl_T2_im,
110 2c0262af bellard
};
111 2c0262af bellard
112 1e8d4eec bellard
static GenOpFunc *gen_shift_T2_0[4] = {
113 1e8d4eec bellard
    NULL,
114 1e8d4eec bellard
    gen_op_shrl_T2_0,
115 1e8d4eec bellard
    gen_op_sarl_T2_0,
116 1e8d4eec bellard
    gen_op_rrxl_T2,
117 1e8d4eec bellard
};
118 1e8d4eec bellard
119 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
120 2c0262af bellard
    gen_op_shll_T1_im_cc,
121 2c0262af bellard
    gen_op_shrl_T1_im_cc,
122 2c0262af bellard
    gen_op_sarl_T1_im_cc,
123 2c0262af bellard
    gen_op_rorl_T1_im_cc,
124 2c0262af bellard
};
125 2c0262af bellard
126 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0_cc[4] = {
127 1e8d4eec bellard
    NULL,
128 1e8d4eec bellard
    gen_op_shrl_T1_0_cc,
129 1e8d4eec bellard
    gen_op_sarl_T1_0_cc,
130 1e8d4eec bellard
    gen_op_rrxl_T1_cc,
131 1e8d4eec bellard
};
132 1e8d4eec bellard
133 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0[4] = {
134 2c0262af bellard
    gen_op_shll_T1_T0,
135 2c0262af bellard
    gen_op_shrl_T1_T0,
136 2c0262af bellard
    gen_op_sarl_T1_T0,
137 2c0262af bellard
    gen_op_rorl_T1_T0,
138 2c0262af bellard
};
139 2c0262af bellard
140 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
141 2c0262af bellard
    gen_op_shll_T1_T0_cc,
142 2c0262af bellard
    gen_op_shrl_T1_T0_cc,
143 2c0262af bellard
    gen_op_sarl_T1_T0_cc,
144 2c0262af bellard
    gen_op_rorl_T1_T0_cc,
145 2c0262af bellard
};
146 2c0262af bellard
147 2c0262af bellard
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
148 2c0262af bellard
    {
149 2c0262af bellard
        gen_op_movl_T0_r0,
150 2c0262af bellard
        gen_op_movl_T0_r1,
151 2c0262af bellard
        gen_op_movl_T0_r2,
152 2c0262af bellard
        gen_op_movl_T0_r3,
153 2c0262af bellard
        gen_op_movl_T0_r4,
154 2c0262af bellard
        gen_op_movl_T0_r5,
155 2c0262af bellard
        gen_op_movl_T0_r6,
156 2c0262af bellard
        gen_op_movl_T0_r7,
157 2c0262af bellard
        gen_op_movl_T0_r8,
158 2c0262af bellard
        gen_op_movl_T0_r9,
159 2c0262af bellard
        gen_op_movl_T0_r10,
160 2c0262af bellard
        gen_op_movl_T0_r11,
161 2c0262af bellard
        gen_op_movl_T0_r12,
162 2c0262af bellard
        gen_op_movl_T0_r13,
163 2c0262af bellard
        gen_op_movl_T0_r14,
164 2c0262af bellard
        gen_op_movl_T0_r15,
165 2c0262af bellard
    },
166 2c0262af bellard
    {
167 2c0262af bellard
        gen_op_movl_T1_r0,
168 2c0262af bellard
        gen_op_movl_T1_r1,
169 2c0262af bellard
        gen_op_movl_T1_r2,
170 2c0262af bellard
        gen_op_movl_T1_r3,
171 2c0262af bellard
        gen_op_movl_T1_r4,
172 2c0262af bellard
        gen_op_movl_T1_r5,
173 2c0262af bellard
        gen_op_movl_T1_r6,
174 2c0262af bellard
        gen_op_movl_T1_r7,
175 2c0262af bellard
        gen_op_movl_T1_r8,
176 2c0262af bellard
        gen_op_movl_T1_r9,
177 2c0262af bellard
        gen_op_movl_T1_r10,
178 2c0262af bellard
        gen_op_movl_T1_r11,
179 2c0262af bellard
        gen_op_movl_T1_r12,
180 2c0262af bellard
        gen_op_movl_T1_r13,
181 2c0262af bellard
        gen_op_movl_T1_r14,
182 2c0262af bellard
        gen_op_movl_T1_r15,
183 2c0262af bellard
    },
184 2c0262af bellard
    {
185 2c0262af bellard
        gen_op_movl_T2_r0,
186 2c0262af bellard
        gen_op_movl_T2_r1,
187 2c0262af bellard
        gen_op_movl_T2_r2,
188 2c0262af bellard
        gen_op_movl_T2_r3,
189 2c0262af bellard
        gen_op_movl_T2_r4,
190 2c0262af bellard
        gen_op_movl_T2_r5,
191 2c0262af bellard
        gen_op_movl_T2_r6,
192 2c0262af bellard
        gen_op_movl_T2_r7,
193 2c0262af bellard
        gen_op_movl_T2_r8,
194 2c0262af bellard
        gen_op_movl_T2_r9,
195 2c0262af bellard
        gen_op_movl_T2_r10,
196 2c0262af bellard
        gen_op_movl_T2_r11,
197 2c0262af bellard
        gen_op_movl_T2_r12,
198 2c0262af bellard
        gen_op_movl_T2_r13,
199 2c0262af bellard
        gen_op_movl_T2_r14,
200 2c0262af bellard
        gen_op_movl_T2_r15,
201 2c0262af bellard
    },
202 2c0262af bellard
};
203 2c0262af bellard
204 2c0262af bellard
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
205 2c0262af bellard
    {
206 2c0262af bellard
        gen_op_movl_r0_T0,
207 2c0262af bellard
        gen_op_movl_r1_T0,
208 2c0262af bellard
        gen_op_movl_r2_T0,
209 2c0262af bellard
        gen_op_movl_r3_T0,
210 2c0262af bellard
        gen_op_movl_r4_T0,
211 2c0262af bellard
        gen_op_movl_r5_T0,
212 2c0262af bellard
        gen_op_movl_r6_T0,
213 2c0262af bellard
        gen_op_movl_r7_T0,
214 2c0262af bellard
        gen_op_movl_r8_T0,
215 2c0262af bellard
        gen_op_movl_r9_T0,
216 2c0262af bellard
        gen_op_movl_r10_T0,
217 2c0262af bellard
        gen_op_movl_r11_T0,
218 2c0262af bellard
        gen_op_movl_r12_T0,
219 2c0262af bellard
        gen_op_movl_r13_T0,
220 2c0262af bellard
        gen_op_movl_r14_T0,
221 2c0262af bellard
        gen_op_movl_r15_T0,
222 2c0262af bellard
    },
223 2c0262af bellard
    {
224 2c0262af bellard
        gen_op_movl_r0_T1,
225 2c0262af bellard
        gen_op_movl_r1_T1,
226 2c0262af bellard
        gen_op_movl_r2_T1,
227 2c0262af bellard
        gen_op_movl_r3_T1,
228 2c0262af bellard
        gen_op_movl_r4_T1,
229 2c0262af bellard
        gen_op_movl_r5_T1,
230 2c0262af bellard
        gen_op_movl_r6_T1,
231 2c0262af bellard
        gen_op_movl_r7_T1,
232 2c0262af bellard
        gen_op_movl_r8_T1,
233 2c0262af bellard
        gen_op_movl_r9_T1,
234 2c0262af bellard
        gen_op_movl_r10_T1,
235 2c0262af bellard
        gen_op_movl_r11_T1,
236 2c0262af bellard
        gen_op_movl_r12_T1,
237 2c0262af bellard
        gen_op_movl_r13_T1,
238 2c0262af bellard
        gen_op_movl_r14_T1,
239 2c0262af bellard
        gen_op_movl_r15_T1,
240 2c0262af bellard
    },
241 2c0262af bellard
};
242 2c0262af bellard
243 2c0262af bellard
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
244 2c0262af bellard
    gen_op_movl_T0_im,
245 2c0262af bellard
    gen_op_movl_T1_im,
246 2c0262af bellard
    gen_op_movl_T2_im,
247 2c0262af bellard
};
248 2c0262af bellard
249 99c475ab bellard
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
250 99c475ab bellard
    gen_op_shll_T0_im_thumb,
251 99c475ab bellard
    gen_op_shrl_T0_im_thumb,
252 99c475ab bellard
    gen_op_sarl_T0_im_thumb,
253 99c475ab bellard
};
254 99c475ab bellard
255 99c475ab bellard
static inline void gen_bx(DisasContext *s)
256 99c475ab bellard
{
257 99c475ab bellard
  s->is_jmp = DISAS_UPDATE;
258 99c475ab bellard
  gen_op_bx_T0();
259 99c475ab bellard
}
260 99c475ab bellard
261 2c0262af bellard
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
262 2c0262af bellard
{
263 2c0262af bellard
    int val;
264 2c0262af bellard
265 2c0262af bellard
    if (reg == 15) {
266 2c0262af bellard
        /* normaly, since we updated PC, we need only to add 4 */
267 2c0262af bellard
        val = (long)s->pc + 4;
268 2c0262af bellard
        gen_op_movl_TN_im[t](val);
269 2c0262af bellard
    } else {
270 2c0262af bellard
        gen_op_movl_TN_reg[t][reg]();
271 2c0262af bellard
    }
272 2c0262af bellard
}
273 2c0262af bellard
274 2c0262af bellard
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
275 2c0262af bellard
{
276 2c0262af bellard
    gen_movl_TN_reg(s, reg, 0);
277 2c0262af bellard
}
278 2c0262af bellard
279 2c0262af bellard
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
280 2c0262af bellard
{
281 2c0262af bellard
    gen_movl_TN_reg(s, reg, 1);
282 2c0262af bellard
}
283 2c0262af bellard
284 2c0262af bellard
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
285 2c0262af bellard
{
286 2c0262af bellard
    gen_movl_TN_reg(s, reg, 2);
287 2c0262af bellard
}
288 2c0262af bellard
289 2c0262af bellard
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
290 2c0262af bellard
{
291 2c0262af bellard
    gen_op_movl_reg_TN[t][reg]();
292 2c0262af bellard
    if (reg == 15) {
293 2c0262af bellard
        s->is_jmp = DISAS_JUMP;
294 2c0262af bellard
    }
295 2c0262af bellard
}
296 2c0262af bellard
297 2c0262af bellard
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
298 2c0262af bellard
{
299 2c0262af bellard
    gen_movl_reg_TN(s, reg, 0);
300 2c0262af bellard
}
301 2c0262af bellard
302 2c0262af bellard
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
303 2c0262af bellard
{
304 2c0262af bellard
    gen_movl_reg_TN(s, reg, 1);
305 2c0262af bellard
}
306 2c0262af bellard
307 2c0262af bellard
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
308 2c0262af bellard
{
309 1e8d4eec bellard
    int val, rm, shift, shiftop;
310 2c0262af bellard
311 2c0262af bellard
    if (!(insn & (1 << 25))) {
312 2c0262af bellard
        /* immediate */
313 2c0262af bellard
        val = insn & 0xfff;
314 2c0262af bellard
        if (!(insn & (1 << 23)))
315 2c0262af bellard
            val = -val;
316 537730b9 bellard
        if (val != 0)
317 537730b9 bellard
            gen_op_addl_T1_im(val);
318 2c0262af bellard
    } else {
319 2c0262af bellard
        /* shift/register */
320 2c0262af bellard
        rm = (insn) & 0xf;
321 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
322 2c0262af bellard
        gen_movl_T2_reg(s, rm);
323 1e8d4eec bellard
        shiftop = (insn >> 5) & 3;
324 2c0262af bellard
        if (shift != 0) {
325 1e8d4eec bellard
            gen_shift_T2_im[shiftop](shift);
326 1e8d4eec bellard
        } else if (shiftop != 0) {
327 1e8d4eec bellard
            gen_shift_T2_0[shiftop]();
328 2c0262af bellard
        }
329 2c0262af bellard
        if (!(insn & (1 << 23)))
330 2c0262af bellard
            gen_op_subl_T1_T2();
331 2c0262af bellard
        else
332 2c0262af bellard
            gen_op_addl_T1_T2();
333 2c0262af bellard
    }
334 2c0262af bellard
}
335 2c0262af bellard
336 2c0262af bellard
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
337 2c0262af bellard
{
338 2c0262af bellard
    int val, rm;
339 2c0262af bellard
    
340 2c0262af bellard
    if (insn & (1 << 22)) {
341 2c0262af bellard
        /* immediate */
342 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
343 2c0262af bellard
        if (!(insn & (1 << 23)))
344 2c0262af bellard
            val = -val;
345 537730b9 bellard
        if (val != 0)
346 537730b9 bellard
            gen_op_addl_T1_im(val);
347 2c0262af bellard
    } else {
348 2c0262af bellard
        /* register */
349 2c0262af bellard
        rm = (insn) & 0xf;
350 2c0262af bellard
        gen_movl_T2_reg(s, rm);
351 2c0262af bellard
        if (!(insn & (1 << 23)))
352 2c0262af bellard
            gen_op_subl_T1_T2();
353 2c0262af bellard
        else
354 2c0262af bellard
            gen_op_addl_T1_T2();
355 2c0262af bellard
    }
356 2c0262af bellard
}
357 2c0262af bellard
358 b7bcbe95 bellard
#define VFP_OP(name)                      \
359 b7bcbe95 bellard
static inline void gen_vfp_##name(int dp) \
360 b7bcbe95 bellard
{                                         \
361 b7bcbe95 bellard
    if (dp)                               \
362 b7bcbe95 bellard
        gen_op_vfp_##name##d();           \
363 b7bcbe95 bellard
    else                                  \
364 b7bcbe95 bellard
        gen_op_vfp_##name##s();           \
365 b7bcbe95 bellard
}
366 b7bcbe95 bellard
367 b7bcbe95 bellard
VFP_OP(add)
368 b7bcbe95 bellard
VFP_OP(sub)
369 b7bcbe95 bellard
VFP_OP(mul)
370 b7bcbe95 bellard
VFP_OP(div)
371 b7bcbe95 bellard
VFP_OP(neg)
372 b7bcbe95 bellard
VFP_OP(abs)
373 b7bcbe95 bellard
VFP_OP(sqrt)
374 b7bcbe95 bellard
VFP_OP(cmp)
375 b7bcbe95 bellard
VFP_OP(cmpe)
376 b7bcbe95 bellard
VFP_OP(F1_ld0)
377 b7bcbe95 bellard
VFP_OP(uito)
378 b7bcbe95 bellard
VFP_OP(sito)
379 b7bcbe95 bellard
VFP_OP(toui)
380 b7bcbe95 bellard
VFP_OP(touiz)
381 b7bcbe95 bellard
VFP_OP(tosi)
382 b7bcbe95 bellard
VFP_OP(tosiz)
383 b7bcbe95 bellard
VFP_OP(ld)
384 b7bcbe95 bellard
VFP_OP(st)
385 b7bcbe95 bellard
386 b7bcbe95 bellard
#undef VFP_OP
387 b7bcbe95 bellard
388 b7bcbe95 bellard
static inline void gen_mov_F0_vreg(int dp, int reg)
389 b7bcbe95 bellard
{
390 b7bcbe95 bellard
    if (dp)
391 b7bcbe95 bellard
        gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
392 b7bcbe95 bellard
    else
393 b7bcbe95 bellard
        gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
394 b7bcbe95 bellard
}
395 b7bcbe95 bellard
396 b7bcbe95 bellard
static inline void gen_mov_F1_vreg(int dp, int reg)
397 b7bcbe95 bellard
{
398 b7bcbe95 bellard
    if (dp)
399 b7bcbe95 bellard
        gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
400 b7bcbe95 bellard
    else
401 b7bcbe95 bellard
        gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
402 b7bcbe95 bellard
}
403 b7bcbe95 bellard
404 b7bcbe95 bellard
static inline void gen_mov_vreg_F0(int dp, int reg)
405 b7bcbe95 bellard
{
406 b7bcbe95 bellard
    if (dp)
407 b7bcbe95 bellard
        gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
408 b7bcbe95 bellard
    else
409 b7bcbe95 bellard
        gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
410 b7bcbe95 bellard
}
411 b7bcbe95 bellard
412 b7bcbe95 bellard
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
413 b7bcbe95 bellard
   (ie. an undefined instruction).  */
414 b7bcbe95 bellard
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
415 b7bcbe95 bellard
{
416 b7bcbe95 bellard
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
417 b7bcbe95 bellard
    int dp, veclen;
418 b7bcbe95 bellard
419 b7bcbe95 bellard
    dp = ((insn & 0xf00) == 0xb00);
420 b7bcbe95 bellard
    switch ((insn >> 24) & 0xf) {
421 b7bcbe95 bellard
    case 0xe:
422 b7bcbe95 bellard
        if (insn & (1 << 4)) {
423 b7bcbe95 bellard
            /* single register transfer */
424 b7bcbe95 bellard
            if ((insn & 0x6f) != 0x00)
425 b7bcbe95 bellard
                return 1;
426 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
427 b7bcbe95 bellard
            if (dp) {
428 b7bcbe95 bellard
                if (insn & 0x80)
429 b7bcbe95 bellard
                    return 1;
430 b7bcbe95 bellard
                rn = (insn >> 16) & 0xf;
431 b7bcbe95 bellard
                /* Get the existing value even for arm->vfp moves because
432 b7bcbe95 bellard
                   we only set half the register.  */
433 b7bcbe95 bellard
                gen_mov_F0_vreg(1, rn);
434 b7bcbe95 bellard
                gen_op_vfp_mrrd();
435 b7bcbe95 bellard
                if (insn & (1 << 20)) {
436 b7bcbe95 bellard
                    /* vfp->arm */
437 b7bcbe95 bellard
                    if (insn & (1 << 21))
438 b7bcbe95 bellard
                        gen_movl_reg_T1(s, rd);
439 b7bcbe95 bellard
                    else
440 b7bcbe95 bellard
                        gen_movl_reg_T0(s, rd);
441 b7bcbe95 bellard
                } else {
442 b7bcbe95 bellard
                    /* arm->vfp */
443 b7bcbe95 bellard
                    if (insn & (1 << 21))
444 b7bcbe95 bellard
                        gen_movl_T1_reg(s, rd);
445 b7bcbe95 bellard
                    else
446 b7bcbe95 bellard
                        gen_movl_T0_reg(s, rd);
447 b7bcbe95 bellard
                    gen_op_vfp_mdrr();
448 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rn);
449 b7bcbe95 bellard
                }
450 b7bcbe95 bellard
            } else {
451 b7bcbe95 bellard
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
452 b7bcbe95 bellard
                if (insn & (1 << 20)) {
453 b7bcbe95 bellard
                    /* vfp->arm */
454 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
455 b7bcbe95 bellard
                        /* system register */
456 b7bcbe95 bellard
                        switch (rn) {
457 b7bcbe95 bellard
                        case 0: /* fpsid */
458 b7bcbe95 bellard
                            n = 0x0091A0000;
459 b7bcbe95 bellard
                            break;
460 b7bcbe95 bellard
                        case 2: /* fpscr */
461 b7bcbe95 bellard
                            if (rd == 15)
462 b7bcbe95 bellard
                                gen_op_vfp_movl_T0_fpscr_flags();
463 b7bcbe95 bellard
                            else
464 b7bcbe95 bellard
                                gen_op_vfp_movl_T0_fpscr();
465 b7bcbe95 bellard
                            break;
466 b7bcbe95 bellard
                        default:
467 b7bcbe95 bellard
                            return 1;
468 b7bcbe95 bellard
                        }
469 b7bcbe95 bellard
                    } else {
470 b7bcbe95 bellard
                        gen_mov_F0_vreg(0, rn);
471 b7bcbe95 bellard
                        gen_op_vfp_mrs();
472 b7bcbe95 bellard
                    }
473 b7bcbe95 bellard
                    if (rd == 15) {
474 b7bcbe95 bellard
                        /* This will only set the 4 flag bits */
475 b7bcbe95 bellard
                        gen_op_movl_psr_T0();
476 b7bcbe95 bellard
                    } else
477 b7bcbe95 bellard
                        gen_movl_reg_T0(s, rd);
478 b7bcbe95 bellard
                } else {
479 b7bcbe95 bellard
                    /* arm->vfp */
480 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
481 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
482 b7bcbe95 bellard
                        /* system register */
483 b7bcbe95 bellard
                        switch (rn) {
484 b7bcbe95 bellard
                        case 0: /* fpsid */
485 b7bcbe95 bellard
                            /* Writes are ignored.  */
486 b7bcbe95 bellard
                            break;
487 b7bcbe95 bellard
                        case 2: /* fpscr */
488 b7bcbe95 bellard
                            gen_op_vfp_movl_fpscr_T0();
489 b7bcbe95 bellard
                            /* This could change vector settings, so jump to
490 b7bcbe95 bellard
                               the next instuction.  */
491 b7bcbe95 bellard
                            gen_op_movl_T0_im(s->pc);
492 b7bcbe95 bellard
                            gen_movl_reg_T0(s, 15);
493 b7bcbe95 bellard
                            s->is_jmp = DISAS_UPDATE;
494 b7bcbe95 bellard
                            break;
495 b7bcbe95 bellard
                        default:
496 b7bcbe95 bellard
                            return 1;
497 b7bcbe95 bellard
                        }
498 b7bcbe95 bellard
                    } else {
499 b7bcbe95 bellard
                        gen_op_vfp_msr();
500 b7bcbe95 bellard
                        gen_mov_vreg_F0(0, rn);
501 b7bcbe95 bellard
                    }
502 b7bcbe95 bellard
                }
503 b7bcbe95 bellard
            }
504 b7bcbe95 bellard
        } else {
505 b7bcbe95 bellard
            /* data processing */
506 b7bcbe95 bellard
            /* The opcode is in bits 23, 21, 20 and 6.  */
507 b7bcbe95 bellard
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
508 b7bcbe95 bellard
            if (dp) {
509 b7bcbe95 bellard
                if (op == 15) {
510 b7bcbe95 bellard
                    /* rn is opcode */
511 b7bcbe95 bellard
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
512 b7bcbe95 bellard
                } else {
513 b7bcbe95 bellard
                    /* rn is register number */
514 b7bcbe95 bellard
                    if (insn & (1 << 7))
515 b7bcbe95 bellard
                        return 1;
516 b7bcbe95 bellard
                    rn = (insn >> 16) & 0xf;
517 b7bcbe95 bellard
                }
518 b7bcbe95 bellard
519 b7bcbe95 bellard
                if (op == 15 && (rn == 15 || rn > 17)) {
520 b7bcbe95 bellard
                    /* Integer or single precision destination.  */
521 b7bcbe95 bellard
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
522 b7bcbe95 bellard
                } else {
523 b7bcbe95 bellard
                    if (insn & (1 << 22))
524 b7bcbe95 bellard
                        return 1;
525 b7bcbe95 bellard
                    rd = (insn >> 12) & 0xf;
526 b7bcbe95 bellard
                }
527 b7bcbe95 bellard
528 b7bcbe95 bellard
                if (op == 15 && (rn == 16 || rn == 17)) {
529 b7bcbe95 bellard
                    /* Integer source.  */
530 b7bcbe95 bellard
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
531 b7bcbe95 bellard
                } else {
532 b7bcbe95 bellard
                    if (insn & (1 << 5))
533 b7bcbe95 bellard
                        return 1;
534 b7bcbe95 bellard
                    rm = insn & 0xf;
535 b7bcbe95 bellard
                }
536 b7bcbe95 bellard
            } else {
537 b7bcbe95 bellard
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
538 b7bcbe95 bellard
                if (op == 15 && rn == 15) {
539 b7bcbe95 bellard
                    /* Double precision destination.  */
540 b7bcbe95 bellard
                    if (insn & (1 << 22))
541 b7bcbe95 bellard
                        return 1;
542 b7bcbe95 bellard
                    rd = (insn >> 12) & 0xf;
543 b7bcbe95 bellard
                } else
544 b7bcbe95 bellard
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
545 b7bcbe95 bellard
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
546 b7bcbe95 bellard
            }
547 b7bcbe95 bellard
548 b7bcbe95 bellard
            veclen = env->vfp.vec_len;
549 b7bcbe95 bellard
            if (op == 15 && rn > 3)
550 b7bcbe95 bellard
                veclen = 0;
551 b7bcbe95 bellard
552 b7bcbe95 bellard
            /* Shut up compiler warnings.  */
553 b7bcbe95 bellard
            delta_m = 0;
554 b7bcbe95 bellard
            delta_d = 0;
555 b7bcbe95 bellard
            bank_mask = 0;
556 b7bcbe95 bellard
            
557 b7bcbe95 bellard
            if (veclen > 0) {
558 b7bcbe95 bellard
                if (dp)
559 b7bcbe95 bellard
                    bank_mask = 0xc;
560 b7bcbe95 bellard
                else
561 b7bcbe95 bellard
                    bank_mask = 0x18;
562 b7bcbe95 bellard
563 b7bcbe95 bellard
                /* Figure out what type of vector operation this is.  */
564 b7bcbe95 bellard
                if ((rd & bank_mask) == 0) {
565 b7bcbe95 bellard
                    /* scalar */
566 b7bcbe95 bellard
                    veclen = 0;
567 b7bcbe95 bellard
                } else {
568 b7bcbe95 bellard
                    if (dp)
569 b7bcbe95 bellard
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
570 b7bcbe95 bellard
                    else
571 b7bcbe95 bellard
                        delta_d = env->vfp.vec_stride + 1;
572 b7bcbe95 bellard
573 b7bcbe95 bellard
                    if ((rm & bank_mask) == 0) {
574 b7bcbe95 bellard
                        /* mixed scalar/vector */
575 b7bcbe95 bellard
                        delta_m = 0;
576 b7bcbe95 bellard
                    } else {
577 b7bcbe95 bellard
                        /* vector */
578 b7bcbe95 bellard
                        delta_m = delta_d;
579 b7bcbe95 bellard
                    }
580 b7bcbe95 bellard
                }
581 b7bcbe95 bellard
            }
582 b7bcbe95 bellard
583 b7bcbe95 bellard
            /* Load the initial operands.  */
584 b7bcbe95 bellard
            if (op == 15) {
585 b7bcbe95 bellard
                switch (rn) {
586 b7bcbe95 bellard
                case 16:
587 b7bcbe95 bellard
                case 17:
588 b7bcbe95 bellard
                    /* Integer source */
589 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
590 b7bcbe95 bellard
                    break;
591 b7bcbe95 bellard
                case 8:
592 b7bcbe95 bellard
                case 9:
593 b7bcbe95 bellard
                    /* Compare */
594 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
595 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rm);
596 b7bcbe95 bellard
                    break;
597 b7bcbe95 bellard
                case 10:
598 b7bcbe95 bellard
                case 11:
599 b7bcbe95 bellard
                    /* Compare with zero */
600 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
601 b7bcbe95 bellard
                    gen_vfp_F1_ld0(dp);
602 b7bcbe95 bellard
                    break;
603 b7bcbe95 bellard
                default:
604 b7bcbe95 bellard
                    /* One source operand.  */
605 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
606 b7bcbe95 bellard
                }
607 b7bcbe95 bellard
            } else {
608 b7bcbe95 bellard
                /* Two source operands.  */
609 b7bcbe95 bellard
                gen_mov_F0_vreg(dp, rn);
610 b7bcbe95 bellard
                gen_mov_F1_vreg(dp, rm);
611 b7bcbe95 bellard
            }
612 b7bcbe95 bellard
613 b7bcbe95 bellard
            for (;;) {
614 b7bcbe95 bellard
                /* Perform the calculation.  */
615 b7bcbe95 bellard
                switch (op) {
616 b7bcbe95 bellard
                case 0: /* mac: fd + (fn * fm) */
617 b7bcbe95 bellard
                    gen_vfp_mul(dp);
618 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
619 b7bcbe95 bellard
                    gen_vfp_add(dp);
620 b7bcbe95 bellard
                    break;
621 b7bcbe95 bellard
                case 1: /* nmac: fd - (fn * fm) */
622 b7bcbe95 bellard
                    gen_vfp_mul(dp);
623 b7bcbe95 bellard
                    gen_vfp_neg(dp);
624 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
625 b7bcbe95 bellard
                    gen_vfp_add(dp);
626 b7bcbe95 bellard
                    break;
627 b7bcbe95 bellard
                case 2: /* msc: -fd + (fn * fm) */
628 b7bcbe95 bellard
                    gen_vfp_mul(dp);
629 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
630 b7bcbe95 bellard
                    gen_vfp_sub(dp);
631 b7bcbe95 bellard
                    break;
632 b7bcbe95 bellard
                case 3: /* nmsc: -fd - (fn * fm)  */
633 b7bcbe95 bellard
                    gen_vfp_mul(dp);
634 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
635 b7bcbe95 bellard
                    gen_vfp_add(dp);
636 b7bcbe95 bellard
                    gen_vfp_neg(dp);
637 b7bcbe95 bellard
                    break;
638 b7bcbe95 bellard
                case 4: /* mul: fn * fm */
639 b7bcbe95 bellard
                    gen_vfp_mul(dp);
640 b7bcbe95 bellard
                    break;
641 b7bcbe95 bellard
                case 5: /* nmul: -(fn * fm) */
642 b7bcbe95 bellard
                    gen_vfp_mul(dp);
643 b7bcbe95 bellard
                    gen_vfp_neg(dp);
644 b7bcbe95 bellard
                    break;
645 b7bcbe95 bellard
                case 6: /* add: fn + fm */
646 b7bcbe95 bellard
                    gen_vfp_add(dp);
647 b7bcbe95 bellard
                    break;
648 b7bcbe95 bellard
                case 7: /* sub: fn - fm */
649 b7bcbe95 bellard
                    gen_vfp_sub(dp);
650 b7bcbe95 bellard
                    break;
651 b7bcbe95 bellard
                case 8: /* div: fn / fm */
652 b7bcbe95 bellard
                    gen_vfp_div(dp);
653 b7bcbe95 bellard
                    break;
654 b7bcbe95 bellard
                case 15: /* extension space */
655 b7bcbe95 bellard
                    switch (rn) {
656 b7bcbe95 bellard
                    case 0: /* cpy */
657 b7bcbe95 bellard
                        /* no-op */
658 b7bcbe95 bellard
                        break;
659 b7bcbe95 bellard
                    case 1: /* abs */
660 b7bcbe95 bellard
                        gen_vfp_abs(dp);
661 b7bcbe95 bellard
                        break;
662 b7bcbe95 bellard
                    case 2: /* neg */
663 b7bcbe95 bellard
                        gen_vfp_neg(dp);
664 b7bcbe95 bellard
                        break;
665 b7bcbe95 bellard
                    case 3: /* sqrt */
666 b7bcbe95 bellard
                        gen_vfp_sqrt(dp);
667 b7bcbe95 bellard
                        break;
668 b7bcbe95 bellard
                    case 8: /* cmp */
669 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
670 b7bcbe95 bellard
                        break;
671 b7bcbe95 bellard
                    case 9: /* cmpe */
672 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
673 b7bcbe95 bellard
                        break;
674 b7bcbe95 bellard
                    case 10: /* cmpz */
675 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
676 b7bcbe95 bellard
                        break;
677 b7bcbe95 bellard
                    case 11: /* cmpez */
678 b7bcbe95 bellard
                        gen_vfp_F1_ld0(dp);
679 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
680 b7bcbe95 bellard
                        break;
681 b7bcbe95 bellard
                    case 15: /* single<->double conversion */
682 b7bcbe95 bellard
                        if (dp)
683 b7bcbe95 bellard
                            gen_op_vfp_fcvtsd();
684 b7bcbe95 bellard
                        else
685 b7bcbe95 bellard
                            gen_op_vfp_fcvtds();
686 b7bcbe95 bellard
                        break;
687 b7bcbe95 bellard
                    case 16: /* fuito */
688 b7bcbe95 bellard
                        gen_vfp_uito(dp);
689 b7bcbe95 bellard
                        break;
690 b7bcbe95 bellard
                    case 17: /* fsito */
691 b7bcbe95 bellard
                        gen_vfp_sito(dp);
692 b7bcbe95 bellard
                        break;
693 b7bcbe95 bellard
                    case 24: /* ftoui */
694 b7bcbe95 bellard
                        gen_vfp_toui(dp);
695 b7bcbe95 bellard
                        break;
696 b7bcbe95 bellard
                    case 25: /* ftouiz */
697 b7bcbe95 bellard
                        gen_vfp_touiz(dp);
698 b7bcbe95 bellard
                        break;
699 b7bcbe95 bellard
                    case 26: /* ftosi */
700 b7bcbe95 bellard
                        gen_vfp_tosi(dp);
701 b7bcbe95 bellard
                        break;
702 b7bcbe95 bellard
                    case 27: /* ftosiz */
703 b7bcbe95 bellard
                        gen_vfp_tosiz(dp);
704 b7bcbe95 bellard
                        break;
705 b7bcbe95 bellard
                    default: /* undefined */
706 b7bcbe95 bellard
                        printf ("rn:%d\n", rn);
707 b7bcbe95 bellard
                        return 1;
708 b7bcbe95 bellard
                    }
709 b7bcbe95 bellard
                    break;
710 b7bcbe95 bellard
                default: /* undefined */
711 b7bcbe95 bellard
                    printf ("op:%d\n", op);
712 b7bcbe95 bellard
                    return 1;
713 b7bcbe95 bellard
                }
714 b7bcbe95 bellard
715 b7bcbe95 bellard
                /* Write back the result.  */
716 b7bcbe95 bellard
                if (op == 15 && (rn >= 8 && rn <= 11))
717 b7bcbe95 bellard
                    ; /* Comparison, do nothing.  */
718 b7bcbe95 bellard
                else if (op == 15 && rn > 17)
719 b7bcbe95 bellard
                    /* Integer result.  */
720 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rd);
721 b7bcbe95 bellard
                else if (op == 15 && rn == 15)
722 b7bcbe95 bellard
                    /* conversion */
723 b7bcbe95 bellard
                    gen_mov_vreg_F0(!dp, rd);
724 b7bcbe95 bellard
                else
725 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
726 b7bcbe95 bellard
727 b7bcbe95 bellard
                /* break out of the loop if we have finished  */
728 b7bcbe95 bellard
                if (veclen == 0)
729 b7bcbe95 bellard
                    break;
730 b7bcbe95 bellard
731 b7bcbe95 bellard
                if (op == 15 && delta_m == 0) {
732 b7bcbe95 bellard
                    /* single source one-many */
733 b7bcbe95 bellard
                    while (veclen--) {
734 b7bcbe95 bellard
                        rd = ((rd + delta_d) & (bank_mask - 1))
735 b7bcbe95 bellard
                             | (rd & bank_mask);
736 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd);
737 b7bcbe95 bellard
                    }
738 b7bcbe95 bellard
                    break;
739 b7bcbe95 bellard
                }
740 b7bcbe95 bellard
                /* Setup the next operands.  */
741 b7bcbe95 bellard
                veclen--;
742 b7bcbe95 bellard
                rd = ((rd + delta_d) & (bank_mask - 1))
743 b7bcbe95 bellard
                     | (rd & bank_mask);
744 b7bcbe95 bellard
745 b7bcbe95 bellard
                if (op == 15) {
746 b7bcbe95 bellard
                    /* One source operand.  */
747 b7bcbe95 bellard
                    rm = ((rm + delta_m) & (bank_mask - 1))
748 b7bcbe95 bellard
                         | (rm & bank_mask);
749 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
750 b7bcbe95 bellard
                } else {
751 b7bcbe95 bellard
                    /* Two source operands.  */
752 b7bcbe95 bellard
                    rn = ((rn + delta_d) & (bank_mask - 1))
753 b7bcbe95 bellard
                         | (rn & bank_mask);
754 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rn);
755 b7bcbe95 bellard
                    if (delta_m) {
756 b7bcbe95 bellard
                        rm = ((rm + delta_m) & (bank_mask - 1))
757 b7bcbe95 bellard
                             | (rm & bank_mask);
758 b7bcbe95 bellard
                        gen_mov_F1_vreg(dp, rm);
759 b7bcbe95 bellard
                    }
760 b7bcbe95 bellard
                }
761 b7bcbe95 bellard
            }
762 b7bcbe95 bellard
        }
763 b7bcbe95 bellard
        break;
764 b7bcbe95 bellard
    case 0xc:
765 b7bcbe95 bellard
    case 0xd:
766 b7bcbe95 bellard
        if (dp && (insn & (1 << 22))) {
767 b7bcbe95 bellard
            /* two-register transfer */
768 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
769 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
770 b7bcbe95 bellard
            if (dp) {
771 b7bcbe95 bellard
                if (insn & (1 << 5))
772 b7bcbe95 bellard
                    return 1;
773 b7bcbe95 bellard
                rm = insn & 0xf;
774 b7bcbe95 bellard
            } else
775 b7bcbe95 bellard
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
776 b7bcbe95 bellard
777 b7bcbe95 bellard
            if (insn & (1 << 20)) {
778 b7bcbe95 bellard
                /* vfp->arm */
779 b7bcbe95 bellard
                if (dp) {
780 b7bcbe95 bellard
                    gen_mov_F0_vreg(1, rm);
781 b7bcbe95 bellard
                    gen_op_vfp_mrrd();
782 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rd);
783 b7bcbe95 bellard
                    gen_movl_reg_T1(s, rn);
784 b7bcbe95 bellard
                } else {
785 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
786 b7bcbe95 bellard
                    gen_op_vfp_mrs();
787 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rn);
788 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm + 1);
789 b7bcbe95 bellard
                    gen_op_vfp_mrs();
790 b7bcbe95 bellard
                    gen_movl_reg_T0(s, rd);
791 b7bcbe95 bellard
                }
792 b7bcbe95 bellard
            } else {
793 b7bcbe95 bellard
                /* arm->vfp */
794 b7bcbe95 bellard
                if (dp) {
795 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
796 b7bcbe95 bellard
                    gen_movl_T1_reg(s, rn);
797 b7bcbe95 bellard
                    gen_op_vfp_mdrr();
798 b7bcbe95 bellard
                    gen_mov_vreg_F0(1, rm);
799 b7bcbe95 bellard
                } else {
800 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rn);
801 b7bcbe95 bellard
                    gen_op_vfp_msr();
802 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm);
803 b7bcbe95 bellard
                    gen_movl_T0_reg(s, rd);
804 b7bcbe95 bellard
                    gen_op_vfp_msr();
805 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm + 1);
806 b7bcbe95 bellard
                }
807 b7bcbe95 bellard
            }
808 b7bcbe95 bellard
        } else {
809 b7bcbe95 bellard
            /* Load/store */
810 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
811 b7bcbe95 bellard
            if (dp)
812 b7bcbe95 bellard
                rd = (insn >> 12) & 0xf;
813 b7bcbe95 bellard
            else
814 b7bcbe95 bellard
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
815 b7bcbe95 bellard
            gen_movl_T1_reg(s, rn);
816 b7bcbe95 bellard
            if ((insn & 0x01200000) == 0x01000000) {
817 b7bcbe95 bellard
                /* Single load/store */
818 b7bcbe95 bellard
                offset = (insn & 0xff) << 2;
819 b7bcbe95 bellard
                if ((insn & (1 << 23)) == 0)
820 b7bcbe95 bellard
                    offset = -offset;
821 b7bcbe95 bellard
                gen_op_addl_T1_im(offset);
822 b7bcbe95 bellard
                if (insn & (1 << 20)) {
823 b7bcbe95 bellard
                    gen_vfp_ld(dp);
824 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
825 b7bcbe95 bellard
                } else {
826 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
827 b7bcbe95 bellard
                    gen_vfp_st(dp);
828 b7bcbe95 bellard
                }
829 b7bcbe95 bellard
            } else {
830 b7bcbe95 bellard
                /* load/store multiple */
831 b7bcbe95 bellard
                if (dp)
832 b7bcbe95 bellard
                    n = (insn >> 1) & 0x7f;
833 b7bcbe95 bellard
                else
834 b7bcbe95 bellard
                    n = insn & 0xff;
835 b7bcbe95 bellard
836 b7bcbe95 bellard
                if (insn & (1 << 24)) /* pre-decrement */
837 b7bcbe95 bellard
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
838 b7bcbe95 bellard
839 b7bcbe95 bellard
                if (dp)
840 b7bcbe95 bellard
                    offset = 8;
841 b7bcbe95 bellard
                else
842 b7bcbe95 bellard
                    offset = 4;
843 b7bcbe95 bellard
                for (i = 0; i < n; i++) {
844 b7bcbe95 bellard
                    if (insn & (1 << 20)) {
845 b7bcbe95 bellard
                        /* load */
846 b7bcbe95 bellard
                        gen_vfp_ld(dp);
847 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd + i);
848 b7bcbe95 bellard
                    } else {
849 b7bcbe95 bellard
                        /* store */
850 b7bcbe95 bellard
                        gen_mov_F0_vreg(dp, rd + i);
851 b7bcbe95 bellard
                        gen_vfp_st(dp);
852 b7bcbe95 bellard
                    }
853 b7bcbe95 bellard
                    gen_op_addl_T1_im(offset);
854 b7bcbe95 bellard
                }
855 b7bcbe95 bellard
                if (insn & (1 << 21)) {
856 b7bcbe95 bellard
                    /* writeback */
857 b7bcbe95 bellard
                    if (insn & (1 << 24))
858 b7bcbe95 bellard
                        offset = -offset * n;
859 b7bcbe95 bellard
                    else if (dp && (insn & 1))
860 b7bcbe95 bellard
                        offset = 4;
861 b7bcbe95 bellard
                    else
862 b7bcbe95 bellard
                        offset = 0;
863 b7bcbe95 bellard
864 b7bcbe95 bellard
                    if (offset != 0)
865 b7bcbe95 bellard
                        gen_op_addl_T1_im(offset);
866 b7bcbe95 bellard
                    gen_movl_reg_T1(s, rn);
867 b7bcbe95 bellard
                }
868 b7bcbe95 bellard
            }
869 b7bcbe95 bellard
        }
870 b7bcbe95 bellard
        break;
871 b7bcbe95 bellard
    default:
872 b7bcbe95 bellard
        /* Should never happen.  */
873 b7bcbe95 bellard
        return 1;
874 b7bcbe95 bellard
    }
875 b7bcbe95 bellard
    return 0;
876 b7bcbe95 bellard
}
877 b7bcbe95 bellard
878 b7bcbe95 bellard
static void disas_arm_insn(CPUState * env, DisasContext *s)
879 2c0262af bellard
{
880 2c0262af bellard
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
881 2c0262af bellard
    
882 2c0262af bellard
    insn = ldl(s->pc);
883 2c0262af bellard
    s->pc += 4;
884 2c0262af bellard
    
885 2c0262af bellard
    cond = insn >> 28;
886 99c475ab bellard
    if (cond == 0xf){
887 b7bcbe95 bellard
        /* Unconditional instructions.  */
888 99c475ab bellard
        if ((insn & 0x0d70f000) == 0x0550f000)
889 99c475ab bellard
            return; /* PLD */
890 99c475ab bellard
        else if ((insn & 0x0e000000) == 0x0a000000) {
891 99c475ab bellard
            /* branch link and change to thumb (blx <offset>) */
892 99c475ab bellard
            int32_t offset;
893 99c475ab bellard
894 99c475ab bellard
            val = (uint32_t)s->pc;
895 99c475ab bellard
            gen_op_movl_T0_im(val);
896 99c475ab bellard
            gen_movl_reg_T0(s, 14);
897 99c475ab bellard
            /* Sign-extend the 24-bit offset */
898 99c475ab bellard
            offset = (((int32_t)insn) << 8) >> 8;
899 99c475ab bellard
            /* offset * 4 + bit24 * 2 + (thumb bit) */
900 99c475ab bellard
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
901 99c475ab bellard
            /* pipeline offset */
902 99c475ab bellard
            val += 4;
903 99c475ab bellard
            gen_op_movl_T0_im(val);
904 99c475ab bellard
            gen_bx(s);
905 99c475ab bellard
            return;
906 b7bcbe95 bellard
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
907 b7bcbe95 bellard
            /* Coprocessor double register transfer.  */
908 b7bcbe95 bellard
        } else if ((insn & 0x0f000010) == 0x0e000010) {
909 b7bcbe95 bellard
            /* Additional coprocessor register transfer.  */
910 99c475ab bellard
        }
911 2c0262af bellard
        goto illegal_op;
912 99c475ab bellard
    }
913 2c0262af bellard
    if (cond != 0xe) {
914 2c0262af bellard
        /* if not always execute, we generate a conditional jump to
915 2c0262af bellard
           next instruction */
916 2c0262af bellard
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
917 2c0262af bellard
        s->is_jmp = DISAS_JUMP_NEXT;
918 2c0262af bellard
    }
919 99c475ab bellard
    if ((insn & 0x0f900000) == 0x03000000) {
920 99c475ab bellard
        if ((insn & 0x0ff0f000) != 0x0360f000)
921 99c475ab bellard
            goto illegal_op;
922 99c475ab bellard
        /* CPSR = immediate */
923 99c475ab bellard
        val = insn & 0xff;
924 99c475ab bellard
        shift = ((insn >> 8) & 0xf) * 2;
925 99c475ab bellard
        if (shift)
926 99c475ab bellard
            val = (val >> shift) | (val << (32 - shift));
927 99c475ab bellard
        gen_op_movl_T0_im(val);
928 99c475ab bellard
        if (insn & (1 << 19))
929 99c475ab bellard
            gen_op_movl_psr_T0();
930 99c475ab bellard
    } else if ((insn & 0x0f900000) == 0x01000000
931 99c475ab bellard
               && (insn & 0x00000090) != 0x00000090) {
932 99c475ab bellard
        /* miscellaneous instructions */
933 99c475ab bellard
        op1 = (insn >> 21) & 3;
934 99c475ab bellard
        sh = (insn >> 4) & 0xf;
935 99c475ab bellard
        rm = insn & 0xf;
936 99c475ab bellard
        switch (sh) {
937 99c475ab bellard
        case 0x0: /* move program status register */
938 99c475ab bellard
            if (op1 & 2) {
939 99c475ab bellard
                /* SPSR not accessible in user mode */
940 99c475ab bellard
                goto illegal_op;
941 99c475ab bellard
            }
942 99c475ab bellard
            if (op1 & 1) {
943 99c475ab bellard
                /* CPSR = reg */
944 99c475ab bellard
                gen_movl_T0_reg(s, rm);
945 99c475ab bellard
                if (insn & (1 << 19))
946 99c475ab bellard
                    gen_op_movl_psr_T0();
947 99c475ab bellard
            } else {
948 99c475ab bellard
                /* reg = CPSR */
949 99c475ab bellard
                rd = (insn >> 12) & 0xf;
950 99c475ab bellard
                gen_op_movl_T0_psr();
951 99c475ab bellard
                gen_movl_reg_T0(s, rd);
952 99c475ab bellard
            }
953 b8a9e8f1 bellard
            break;
954 99c475ab bellard
        case 0x1:
955 99c475ab bellard
            if (op1 == 1) {
956 99c475ab bellard
                /* branch/exchange thumb (bx).  */
957 99c475ab bellard
                gen_movl_T0_reg(s, rm);
958 99c475ab bellard
                gen_bx(s);
959 99c475ab bellard
            } else if (op1 == 3) {
960 99c475ab bellard
                /* clz */
961 99c475ab bellard
                rd = (insn >> 12) & 0xf;
962 99c475ab bellard
                gen_movl_T0_reg(s, rm);
963 99c475ab bellard
                gen_op_clz_T0();
964 99c475ab bellard
                gen_movl_reg_T0(s, rd);
965 99c475ab bellard
            } else {
966 99c475ab bellard
                goto illegal_op;
967 99c475ab bellard
            }
968 99c475ab bellard
            break;
969 99c475ab bellard
        case 0x3:
970 99c475ab bellard
            if (op1 != 1)
971 99c475ab bellard
              goto illegal_op;
972 99c475ab bellard
973 99c475ab bellard
            /* branch link/exchange thumb (blx) */
974 99c475ab bellard
            val = (uint32_t)s->pc;
975 99c475ab bellard
            gen_op_movl_T0_im(val);
976 99c475ab bellard
            gen_movl_reg_T0(s, 14);
977 99c475ab bellard
            gen_movl_T0_reg(s, rm);
978 99c475ab bellard
            gen_bx(s);
979 99c475ab bellard
            break;
980 99c475ab bellard
        case 0x5: /* saturating add/subtract */
981 99c475ab bellard
            rd = (insn >> 12) & 0xf;
982 99c475ab bellard
            rn = (insn >> 16) & 0xf;
983 99c475ab bellard
            gen_movl_T0_reg(s, rn);
984 99c475ab bellard
            if (op1 & 2) {
985 99c475ab bellard
                gen_movl_T1_reg(s, rn);
986 99c475ab bellard
                if (op1 & 1) 
987 99c475ab bellard
                    gen_op_subl_T0_T1_saturate();
988 99c475ab bellard
                else
989 99c475ab bellard
                    gen_op_addl_T0_T1_saturate();
990 99c475ab bellard
            }
991 99c475ab bellard
            gen_movl_T1_reg(s, rm);
992 99c475ab bellard
            if (op1 & 1)
993 99c475ab bellard
                gen_op_subl_T0_T1_saturate();
994 99c475ab bellard
            else
995 99c475ab bellard
                gen_op_addl_T0_T1_saturate();
996 99c475ab bellard
            gen_movl_reg_T0(s, rn);
997 99c475ab bellard
            break;
998 99c475ab bellard
        case 0x8: /* signed multiply */
999 99c475ab bellard
        case 0xa:
1000 99c475ab bellard
        case 0xc:
1001 99c475ab bellard
        case 0xe:
1002 99c475ab bellard
            rs = (insn >> 8) & 0xf;
1003 99c475ab bellard
            rn = (insn >> 12) & 0xf;
1004 99c475ab bellard
            rd = (insn >> 16) & 0xf;
1005 99c475ab bellard
            if (op1 == 1) {
1006 99c475ab bellard
                /* (32 * 16) >> 16 */
1007 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1008 99c475ab bellard
                gen_movl_T1_reg(s, rs);
1009 99c475ab bellard
                if (sh & 4)
1010 99c475ab bellard
                    gen_op_sarl_T1_im(16);
1011 99c475ab bellard
                else
1012 99c475ab bellard
                    gen_op_sxl_T1();
1013 99c475ab bellard
                gen_op_imulw_T0_T1();
1014 99c475ab bellard
                if ((sh & 2) == 0) {
1015 99c475ab bellard
                    gen_movl_T1_reg(s, rn);
1016 99c475ab bellard
                    gen_op_addl_T0_T1_setq();
1017 99c475ab bellard
                }
1018 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1019 99c475ab bellard
            } else {
1020 99c475ab bellard
                /* 16 * 16 */
1021 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1022 99c475ab bellard
                if (sh & 2)
1023 99c475ab bellard
                    gen_op_sarl_T0_im(16);
1024 99c475ab bellard
                else
1025 99c475ab bellard
                    gen_op_sxl_T0();
1026 99c475ab bellard
                gen_movl_T1_reg(s, rs);
1027 99c475ab bellard
                if (sh & 4)
1028 99c475ab bellard
                    gen_op_sarl_T1_im(16);
1029 99c475ab bellard
                else
1030 99c475ab bellard
                    gen_op_sxl_T1();
1031 99c475ab bellard
                if (op1 == 2) {
1032 99c475ab bellard
                    gen_op_imull_T0_T1();
1033 99c475ab bellard
                    gen_op_addq_T0_T1(rn, rd);
1034 99c475ab bellard
                    gen_movl_reg_T0(s, rn);
1035 99c475ab bellard
                    gen_movl_reg_T1(s, rd);
1036 99c475ab bellard
                } else {
1037 99c475ab bellard
                    gen_op_mul_T0_T1();
1038 99c475ab bellard
                    if (op1 == 0) {
1039 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
1040 99c475ab bellard
                        gen_op_addl_T0_T1_setq();
1041 99c475ab bellard
                    }
1042 99c475ab bellard
                    gen_movl_reg_T0(s, rd);
1043 99c475ab bellard
                }
1044 99c475ab bellard
            }
1045 99c475ab bellard
            break;
1046 99c475ab bellard
        default:
1047 99c475ab bellard
            goto illegal_op;
1048 99c475ab bellard
        }
1049 99c475ab bellard
    } else if (((insn & 0x0e000000) == 0 &&
1050 99c475ab bellard
                (insn & 0x00000090) != 0x90) ||
1051 99c475ab bellard
               ((insn & 0x0e000000) == (1 << 25))) {
1052 2c0262af bellard
        int set_cc, logic_cc, shiftop;
1053 2c0262af bellard
        
1054 2c0262af bellard
        op1 = (insn >> 21) & 0xf;
1055 2c0262af bellard
        set_cc = (insn >> 20) & 1;
1056 2c0262af bellard
        logic_cc = table_logic_cc[op1] & set_cc;
1057 2c0262af bellard
1058 2c0262af bellard
        /* data processing instruction */
1059 2c0262af bellard
        if (insn & (1 << 25)) {
1060 2c0262af bellard
            /* immediate operand */
1061 2c0262af bellard
            val = insn & 0xff;
1062 2c0262af bellard
            shift = ((insn >> 8) & 0xf) * 2;
1063 2c0262af bellard
            if (shift)
1064 2c0262af bellard
                val = (val >> shift) | (val << (32 - shift));
1065 2c0262af bellard
            gen_op_movl_T1_im(val);
1066 7ff4d218 bellard
            if (logic_cc && shift)
1067 7ff4d218 bellard
                gen_op_mov_CF_T1();
1068 2c0262af bellard
        } else {
1069 2c0262af bellard
            /* register */
1070 2c0262af bellard
            rm = (insn) & 0xf;
1071 2c0262af bellard
            gen_movl_T1_reg(s, rm);
1072 2c0262af bellard
            shiftop = (insn >> 5) & 3;
1073 2c0262af bellard
            if (!(insn & (1 << 4))) {
1074 2c0262af bellard
                shift = (insn >> 7) & 0x1f;
1075 2c0262af bellard
                if (shift != 0) {
1076 2c0262af bellard
                    if (logic_cc) {
1077 2c0262af bellard
                        gen_shift_T1_im_cc[shiftop](shift);
1078 2c0262af bellard
                    } else {
1079 2c0262af bellard
                        gen_shift_T1_im[shiftop](shift);
1080 2c0262af bellard
                    }
1081 1e8d4eec bellard
                } else if (shiftop != 0) {
1082 1e8d4eec bellard
                    if (logic_cc) {
1083 1e8d4eec bellard
                        gen_shift_T1_0_cc[shiftop]();
1084 1e8d4eec bellard
                    } else {
1085 1e8d4eec bellard
                        gen_shift_T1_0[shiftop]();
1086 1e8d4eec bellard
                    }
1087 2c0262af bellard
                }
1088 2c0262af bellard
            } else {
1089 2c0262af bellard
                rs = (insn >> 8) & 0xf;
1090 2c0262af bellard
                gen_movl_T0_reg(s, rs);
1091 2c0262af bellard
                if (logic_cc) {
1092 2c0262af bellard
                    gen_shift_T1_T0_cc[shiftop]();
1093 2c0262af bellard
                } else {
1094 2c0262af bellard
                    gen_shift_T1_T0[shiftop]();
1095 2c0262af bellard
                }
1096 2c0262af bellard
            }
1097 2c0262af bellard
        }
1098 2c0262af bellard
        if (op1 != 0x0f && op1 != 0x0d) {
1099 2c0262af bellard
            rn = (insn >> 16) & 0xf;
1100 2c0262af bellard
            gen_movl_T0_reg(s, rn);
1101 2c0262af bellard
        }
1102 2c0262af bellard
        rd = (insn >> 12) & 0xf;
1103 2c0262af bellard
        switch(op1) {
1104 2c0262af bellard
        case 0x00:
1105 2c0262af bellard
            gen_op_andl_T0_T1();
1106 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1107 2c0262af bellard
            if (logic_cc)
1108 2c0262af bellard
                gen_op_logic_T0_cc();
1109 2c0262af bellard
            break;
1110 2c0262af bellard
        case 0x01:
1111 2c0262af bellard
            gen_op_xorl_T0_T1();
1112 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1113 2c0262af bellard
            if (logic_cc)
1114 2c0262af bellard
                gen_op_logic_T0_cc();
1115 2c0262af bellard
            break;
1116 2c0262af bellard
        case 0x02:
1117 2c0262af bellard
            if (set_cc)
1118 2c0262af bellard
                gen_op_subl_T0_T1_cc();
1119 2c0262af bellard
            else
1120 2c0262af bellard
                gen_op_subl_T0_T1();
1121 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1122 2c0262af bellard
            break;
1123 2c0262af bellard
        case 0x03:
1124 2c0262af bellard
            if (set_cc)
1125 2c0262af bellard
                gen_op_rsbl_T0_T1_cc();
1126 2c0262af bellard
            else
1127 2c0262af bellard
                gen_op_rsbl_T0_T1();
1128 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1129 2c0262af bellard
            break;
1130 2c0262af bellard
        case 0x04:
1131 2c0262af bellard
            if (set_cc)
1132 2c0262af bellard
                gen_op_addl_T0_T1_cc();
1133 2c0262af bellard
            else
1134 2c0262af bellard
                gen_op_addl_T0_T1();
1135 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1136 2c0262af bellard
            break;
1137 2c0262af bellard
        case 0x05:
1138 2c0262af bellard
            if (set_cc)
1139 2c0262af bellard
                gen_op_adcl_T0_T1_cc();
1140 2c0262af bellard
            else
1141 2c0262af bellard
                gen_op_adcl_T0_T1();
1142 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1143 2c0262af bellard
            break;
1144 2c0262af bellard
        case 0x06:
1145 2c0262af bellard
            if (set_cc)
1146 2c0262af bellard
                gen_op_sbcl_T0_T1_cc();
1147 2c0262af bellard
            else
1148 2c0262af bellard
                gen_op_sbcl_T0_T1();
1149 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1150 2c0262af bellard
            break;
1151 2c0262af bellard
        case 0x07:
1152 2c0262af bellard
            if (set_cc)
1153 2c0262af bellard
                gen_op_rscl_T0_T1_cc();
1154 2c0262af bellard
            else
1155 2c0262af bellard
                gen_op_rscl_T0_T1();
1156 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1157 2c0262af bellard
            break;
1158 2c0262af bellard
        case 0x08:
1159 2c0262af bellard
            if (set_cc) {
1160 2c0262af bellard
                gen_op_andl_T0_T1();
1161 2c0262af bellard
                gen_op_logic_T0_cc();
1162 2c0262af bellard
            }
1163 2c0262af bellard
            break;
1164 2c0262af bellard
        case 0x09:
1165 2c0262af bellard
            if (set_cc) {
1166 2c0262af bellard
                gen_op_xorl_T0_T1();
1167 2c0262af bellard
                gen_op_logic_T0_cc();
1168 2c0262af bellard
            }
1169 2c0262af bellard
            break;
1170 2c0262af bellard
        case 0x0a:
1171 2c0262af bellard
            if (set_cc) {
1172 2c0262af bellard
                gen_op_subl_T0_T1_cc();
1173 2c0262af bellard
            }
1174 2c0262af bellard
            break;
1175 2c0262af bellard
        case 0x0b:
1176 2c0262af bellard
            if (set_cc) {
1177 2c0262af bellard
                gen_op_addl_T0_T1_cc();
1178 2c0262af bellard
            }
1179 2c0262af bellard
            break;
1180 2c0262af bellard
        case 0x0c:
1181 2c0262af bellard
            gen_op_orl_T0_T1();
1182 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1183 2c0262af bellard
            if (logic_cc)
1184 2c0262af bellard
                gen_op_logic_T0_cc();
1185 2c0262af bellard
            break;
1186 2c0262af bellard
        case 0x0d:
1187 2c0262af bellard
            gen_movl_reg_T1(s, rd);
1188 2c0262af bellard
            if (logic_cc)
1189 2c0262af bellard
                gen_op_logic_T1_cc();
1190 2c0262af bellard
            break;
1191 2c0262af bellard
        case 0x0e:
1192 2c0262af bellard
            gen_op_bicl_T0_T1();
1193 2c0262af bellard
            gen_movl_reg_T0(s, rd);
1194 2c0262af bellard
            if (logic_cc)
1195 2c0262af bellard
                gen_op_logic_T0_cc();
1196 2c0262af bellard
            break;
1197 2c0262af bellard
        default:
1198 2c0262af bellard
        case 0x0f:
1199 2c0262af bellard
            gen_op_notl_T1();
1200 2c0262af bellard
            gen_movl_reg_T1(s, rd);
1201 2c0262af bellard
            if (logic_cc)
1202 2c0262af bellard
                gen_op_logic_T1_cc();
1203 2c0262af bellard
            break;
1204 2c0262af bellard
        }
1205 2c0262af bellard
    } else {
1206 2c0262af bellard
        /* other instructions */
1207 2c0262af bellard
        op1 = (insn >> 24) & 0xf;
1208 2c0262af bellard
        switch(op1) {
1209 2c0262af bellard
        case 0x0:
1210 2c0262af bellard
        case 0x1:
1211 99c475ab bellard
            /* multiplies, extra load/stores */
1212 2c0262af bellard
            sh = (insn >> 5) & 3;
1213 2c0262af bellard
            if (sh == 0) {
1214 2c0262af bellard
                if (op1 == 0x0) {
1215 2c0262af bellard
                    rd = (insn >> 16) & 0xf;
1216 2c0262af bellard
                    rn = (insn >> 12) & 0xf;
1217 2c0262af bellard
                    rs = (insn >> 8) & 0xf;
1218 2c0262af bellard
                    rm = (insn) & 0xf;
1219 99c475ab bellard
                    if (((insn >> 22) & 3) == 0) {
1220 2c0262af bellard
                        /* 32 bit mul */
1221 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
1222 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
1223 2c0262af bellard
                        gen_op_mul_T0_T1();
1224 2c0262af bellard
                        if (insn & (1 << 21)) {
1225 2c0262af bellard
                            gen_movl_T1_reg(s, rn);
1226 2c0262af bellard
                            gen_op_addl_T0_T1();
1227 2c0262af bellard
                        }
1228 2c0262af bellard
                        if (insn & (1 << 20)) 
1229 2c0262af bellard
                            gen_op_logic_T0_cc();
1230 2c0262af bellard
                        gen_movl_reg_T0(s, rd);
1231 2c0262af bellard
                    } else {
1232 2c0262af bellard
                        /* 64 bit mul */
1233 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
1234 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
1235 2c0262af bellard
                        if (insn & (1 << 22)) 
1236 2c0262af bellard
                            gen_op_imull_T0_T1();
1237 2e134c9c bellard
                        else
1238 2e134c9c bellard
                            gen_op_mull_T0_T1();
1239 99c475ab bellard
                        if (insn & (1 << 21)) /* mult accumulate */
1240 2c0262af bellard
                            gen_op_addq_T0_T1(rn, rd);
1241 99c475ab bellard
                        if (!(insn & (1 << 23))) { /* double accumulate */
1242 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rn);
1243 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rd);
1244 99c475ab bellard
                        }
1245 2c0262af bellard
                        if (insn & (1 << 20)) 
1246 2c0262af bellard
                            gen_op_logicq_cc();
1247 2c0262af bellard
                        gen_movl_reg_T0(s, rn);
1248 2c0262af bellard
                        gen_movl_reg_T1(s, rd);
1249 2c0262af bellard
                    }
1250 2c0262af bellard
                } else {
1251 2c0262af bellard
                    rn = (insn >> 16) & 0xf;
1252 2c0262af bellard
                    rd = (insn >> 12) & 0xf;
1253 99c475ab bellard
                    if (insn & (1 << 23)) {
1254 99c475ab bellard
                        /* load/store exclusive */
1255 99c475ab bellard
                        goto illegal_op;
1256 2c0262af bellard
                    } else {
1257 99c475ab bellard
                        /* SWP instruction */
1258 99c475ab bellard
                        rm = (insn) & 0xf;
1259 99c475ab bellard
                        
1260 99c475ab bellard
                        gen_movl_T0_reg(s, rm);
1261 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
1262 99c475ab bellard
                        if (insn & (1 << 22)) {
1263 99c475ab bellard
                            gen_op_swpb_T0_T1();
1264 99c475ab bellard
                        } else {
1265 99c475ab bellard
                            gen_op_swpl_T0_T1();
1266 99c475ab bellard
                        }
1267 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
1268 2c0262af bellard
                    }
1269 2c0262af bellard
                }
1270 2c0262af bellard
            } else {
1271 99c475ab bellard
                /* Misc load/store */
1272 2c0262af bellard
                rn = (insn >> 16) & 0xf;
1273 2c0262af bellard
                rd = (insn >> 12) & 0xf;
1274 2c0262af bellard
                gen_movl_T1_reg(s, rn);
1275 beddab75 bellard
                if (insn & (1 << 24))
1276 beddab75 bellard
                    gen_add_datah_offset(s, insn);
1277 2c0262af bellard
                if (insn & (1 << 20)) {
1278 2c0262af bellard
                    /* load */
1279 2c0262af bellard
                    switch(sh) {
1280 2c0262af bellard
                    case 1:
1281 2c0262af bellard
                        gen_op_lduw_T0_T1();
1282 2c0262af bellard
                        break;
1283 2c0262af bellard
                    case 2:
1284 2c0262af bellard
                        gen_op_ldsb_T0_T1();
1285 2c0262af bellard
                        break;
1286 2c0262af bellard
                    default:
1287 2c0262af bellard
                    case 3:
1288 2c0262af bellard
                        gen_op_ldsw_T0_T1();
1289 2c0262af bellard
                        break;
1290 2c0262af bellard
                    }
1291 e748ba4f bellard
                    gen_movl_reg_T0(s, rd);
1292 99c475ab bellard
                } else if (sh & 2) {
1293 99c475ab bellard
                    /* doubleword */
1294 99c475ab bellard
                    if (sh & 1) {
1295 99c475ab bellard
                        /* store */
1296 99c475ab bellard
                        gen_movl_T0_reg(s, rd);
1297 99c475ab bellard
                        gen_op_stl_T0_T1();
1298 99c475ab bellard
                        gen_op_addl_T1_im(4);
1299 99c475ab bellard
                        gen_movl_T0_reg(s, rd + 1);
1300 99c475ab bellard
                        gen_op_stl_T0_T1();
1301 99c475ab bellard
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1302 99c475ab bellard
                            gen_op_addl_T1_im(-4);
1303 99c475ab bellard
                    } else {
1304 99c475ab bellard
                        /* load */
1305 99c475ab bellard
                        gen_op_ldl_T0_T1();
1306 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
1307 99c475ab bellard
                        gen_op_addl_T1_im(4);
1308 99c475ab bellard
                        gen_op_ldl_T0_T1();
1309 99c475ab bellard
                        gen_movl_reg_T0(s, rd + 1);
1310 99c475ab bellard
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1311 99c475ab bellard
                            gen_op_addl_T1_im(-4);
1312 99c475ab bellard
                    }
1313 2c0262af bellard
                } else {
1314 2c0262af bellard
                    /* store */
1315 e748ba4f bellard
                    gen_movl_T0_reg(s, rd);
1316 2c0262af bellard
                    gen_op_stw_T0_T1();
1317 2c0262af bellard
                }
1318 2c0262af bellard
                if (!(insn & (1 << 24))) {
1319 2c0262af bellard
                    gen_add_datah_offset(s, insn);
1320 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1321 2c0262af bellard
                } else if (insn & (1 << 21)) {
1322 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1323 2c0262af bellard
                }
1324 2c0262af bellard
            }
1325 2c0262af bellard
            break;
1326 2c0262af bellard
        case 0x4:
1327 2c0262af bellard
        case 0x5:
1328 2c0262af bellard
        case 0x6:
1329 2c0262af bellard
        case 0x7:
1330 2c0262af bellard
            /* load/store byte/word */
1331 2c0262af bellard
            rn = (insn >> 16) & 0xf;
1332 2c0262af bellard
            rd = (insn >> 12) & 0xf;
1333 2c0262af bellard
            gen_movl_T1_reg(s, rn);
1334 2c0262af bellard
            if (insn & (1 << 24))
1335 2c0262af bellard
                gen_add_data_offset(s, insn);
1336 2c0262af bellard
            if (insn & (1 << 20)) {
1337 2c0262af bellard
                /* load */
1338 2c0262af bellard
                if (insn & (1 << 22))
1339 2c0262af bellard
                    gen_op_ldub_T0_T1();
1340 2c0262af bellard
                else
1341 2c0262af bellard
                    gen_op_ldl_T0_T1();
1342 99c475ab bellard
                if (rd == 15)
1343 99c475ab bellard
                    gen_bx(s);
1344 99c475ab bellard
                else
1345 99c475ab bellard
                    gen_movl_reg_T0(s, rd);
1346 2c0262af bellard
            } else {
1347 2c0262af bellard
                /* store */
1348 2c0262af bellard
                gen_movl_T0_reg(s, rd);
1349 2c0262af bellard
                if (insn & (1 << 22))
1350 2c0262af bellard
                    gen_op_stb_T0_T1();
1351 2c0262af bellard
                else
1352 2c0262af bellard
                    gen_op_stl_T0_T1();
1353 2c0262af bellard
            }
1354 2c0262af bellard
            if (!(insn & (1 << 24))) {
1355 2c0262af bellard
                gen_add_data_offset(s, insn);
1356 2c0262af bellard
                gen_movl_reg_T1(s, rn);
1357 2c0262af bellard
            } else if (insn & (1 << 21))
1358 2c0262af bellard
                gen_movl_reg_T1(s, rn); {
1359 2c0262af bellard
            }
1360 2c0262af bellard
            break;
1361 2c0262af bellard
        case 0x08:
1362 2c0262af bellard
        case 0x09:
1363 2c0262af bellard
            {
1364 2c0262af bellard
                int j, n;
1365 2c0262af bellard
                /* load/store multiple words */
1366 2c0262af bellard
                /* XXX: store correct base if write back */
1367 2c0262af bellard
                if (insn & (1 << 22))
1368 2c0262af bellard
                    goto illegal_op; /* only usable in supervisor mode */
1369 2c0262af bellard
                rn = (insn >> 16) & 0xf;
1370 2c0262af bellard
                gen_movl_T1_reg(s, rn);
1371 2c0262af bellard
                
1372 2c0262af bellard
                /* compute total size */
1373 2c0262af bellard
                n = 0;
1374 2c0262af bellard
                for(i=0;i<16;i++) {
1375 2c0262af bellard
                    if (insn & (1 << i))
1376 2c0262af bellard
                        n++;
1377 2c0262af bellard
                }
1378 2c0262af bellard
                /* XXX: test invalid n == 0 case ? */
1379 2c0262af bellard
                if (insn & (1 << 23)) {
1380 2c0262af bellard
                    if (insn & (1 << 24)) {
1381 2c0262af bellard
                        /* pre increment */
1382 2c0262af bellard
                        gen_op_addl_T1_im(4);
1383 2c0262af bellard
                    } else {
1384 2c0262af bellard
                        /* post increment */
1385 2c0262af bellard
                    }
1386 2c0262af bellard
                } else {
1387 2c0262af bellard
                    if (insn & (1 << 24)) {
1388 2c0262af bellard
                        /* pre decrement */
1389 2c0262af bellard
                        gen_op_addl_T1_im(-(n * 4));
1390 2c0262af bellard
                    } else {
1391 2c0262af bellard
                        /* post decrement */
1392 2c0262af bellard
                        if (n != 1)
1393 2c0262af bellard
                            gen_op_addl_T1_im(-((n - 1) * 4));
1394 2c0262af bellard
                    }
1395 2c0262af bellard
                }
1396 2c0262af bellard
                j = 0;
1397 2c0262af bellard
                for(i=0;i<16;i++) {
1398 2c0262af bellard
                    if (insn & (1 << i)) {
1399 2c0262af bellard
                        if (insn & (1 << 20)) {
1400 2c0262af bellard
                            /* load */
1401 2c0262af bellard
                            gen_op_ldl_T0_T1();
1402 99c475ab bellard
                            if (i == 15)
1403 99c475ab bellard
                                gen_bx(s);
1404 99c475ab bellard
                            else
1405 99c475ab bellard
                                gen_movl_reg_T0(s, i);
1406 2c0262af bellard
                        } else {
1407 2c0262af bellard
                            /* store */
1408 2c0262af bellard
                            if (i == 15) {
1409 2c0262af bellard
                                /* special case: r15 = PC + 12 */
1410 2c0262af bellard
                                val = (long)s->pc + 8;
1411 2c0262af bellard
                                gen_op_movl_TN_im[0](val);
1412 2c0262af bellard
                            } else {
1413 2c0262af bellard
                                gen_movl_T0_reg(s, i);
1414 2c0262af bellard
                            }
1415 2c0262af bellard
                            gen_op_stl_T0_T1();
1416 2c0262af bellard
                        }
1417 2c0262af bellard
                        j++;
1418 2c0262af bellard
                        /* no need to add after the last transfer */
1419 2c0262af bellard
                        if (j != n)
1420 2c0262af bellard
                            gen_op_addl_T1_im(4);
1421 2c0262af bellard
                    }
1422 2c0262af bellard
                }
1423 2c0262af bellard
                if (insn & (1 << 21)) {
1424 2c0262af bellard
                    /* write back */
1425 2c0262af bellard
                    if (insn & (1 << 23)) {
1426 2c0262af bellard
                        if (insn & (1 << 24)) {
1427 2c0262af bellard
                            /* pre increment */
1428 2c0262af bellard
                        } else {
1429 2c0262af bellard
                            /* post increment */
1430 2c0262af bellard
                            gen_op_addl_T1_im(4);
1431 2c0262af bellard
                        }
1432 2c0262af bellard
                    } else {
1433 2c0262af bellard
                        if (insn & (1 << 24)) {
1434 2c0262af bellard
                            /* pre decrement */
1435 2c0262af bellard
                            if (n != 1)
1436 2c0262af bellard
                                gen_op_addl_T1_im(-((n - 1) * 4));
1437 2c0262af bellard
                        } else {
1438 2c0262af bellard
                            /* post decrement */
1439 2c0262af bellard
                            gen_op_addl_T1_im(-(n * 4));
1440 2c0262af bellard
                        }
1441 2c0262af bellard
                    }
1442 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
1443 2c0262af bellard
                }
1444 2c0262af bellard
            }
1445 2c0262af bellard
            break;
1446 2c0262af bellard
        case 0xa:
1447 2c0262af bellard
        case 0xb:
1448 2c0262af bellard
            {
1449 99c475ab bellard
                int32_t offset;
1450 2c0262af bellard
                
1451 2c0262af bellard
                /* branch (and link) */
1452 99c475ab bellard
                val = (int32_t)s->pc;
1453 2c0262af bellard
                if (insn & (1 << 24)) {
1454 2c0262af bellard
                    gen_op_movl_T0_im(val);
1455 2c0262af bellard
                    gen_op_movl_reg_TN[0][14]();
1456 2c0262af bellard
                }
1457 99c475ab bellard
                offset = (((int32_t)insn << 8) >> 8);
1458 2c0262af bellard
                val += (offset << 2) + 4;
1459 2c0262af bellard
                gen_op_jmp((long)s->tb, val);
1460 2c0262af bellard
                s->is_jmp = DISAS_TB_JUMP;
1461 2c0262af bellard
            }
1462 2c0262af bellard
            break;
1463 b7bcbe95 bellard
        case 0xc:
1464 b7bcbe95 bellard
        case 0xd:
1465 b7bcbe95 bellard
        case 0xe:
1466 b7bcbe95 bellard
            /* Coprocessor.  */
1467 b7bcbe95 bellard
            op1 = (insn >> 8) & 0xf;
1468 b7bcbe95 bellard
            switch (op1) {
1469 b7bcbe95 bellard
            case 10:
1470 b7bcbe95 bellard
            case 11:
1471 b7bcbe95 bellard
                if (disas_vfp_insn (env, s, insn))
1472 b7bcbe95 bellard
                    goto illegal_op;
1473 b7bcbe95 bellard
                break;
1474 b7bcbe95 bellard
            default:
1475 b7bcbe95 bellard
                /* unknown coprocessor.  */
1476 b7bcbe95 bellard
                goto illegal_op;
1477 b7bcbe95 bellard
            }
1478 b7bcbe95 bellard
            break;
1479 2c0262af bellard
        case 0xf:
1480 2c0262af bellard
            /* swi */
1481 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc);
1482 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
1483 2c0262af bellard
            gen_op_swi();
1484 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
1485 2c0262af bellard
            break;
1486 2c0262af bellard
        default:
1487 2c0262af bellard
        illegal_op:
1488 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc - 4);
1489 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
1490 2c0262af bellard
            gen_op_undef_insn();
1491 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
1492 2c0262af bellard
            break;
1493 2c0262af bellard
        }
1494 2c0262af bellard
    }
1495 2c0262af bellard
}
1496 2c0262af bellard
1497 99c475ab bellard
static void disas_thumb_insn(DisasContext *s)
1498 99c475ab bellard
{
1499 99c475ab bellard
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1500 99c475ab bellard
    int32_t offset;
1501 99c475ab bellard
    int i;
1502 99c475ab bellard
1503 99c475ab bellard
    insn = lduw(s->pc);
1504 99c475ab bellard
    s->pc += 2;
1505 99c475ab bellard
    
1506 99c475ab bellard
    switch (insn >> 12) {
1507 99c475ab bellard
    case 0: case 1:
1508 99c475ab bellard
        rd = insn & 7;
1509 99c475ab bellard
        op = (insn >> 11) & 3;
1510 99c475ab bellard
        if (op == 3) {
1511 99c475ab bellard
            /* add/subtract */
1512 99c475ab bellard
            rn = (insn >> 3) & 7;
1513 99c475ab bellard
            gen_movl_T0_reg(s, rn);
1514 99c475ab bellard
            if (insn & (1 << 10)) {
1515 99c475ab bellard
                /* immediate */
1516 99c475ab bellard
                gen_op_movl_T1_im((insn >> 6) & 7);
1517 99c475ab bellard
            } else {
1518 99c475ab bellard
                /* reg */
1519 99c475ab bellard
                rm = (insn >> 6) & 7;
1520 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1521 99c475ab bellard
            }
1522 99c475ab bellard
            if (insn & (1 << 9))
1523 99c475ab bellard
                gen_op_addl_T0_T1_cc();
1524 99c475ab bellard
            else
1525 99c475ab bellard
                gen_op_addl_T0_T1_cc();
1526 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1527 99c475ab bellard
        } else {
1528 99c475ab bellard
            /* shift immediate */
1529 99c475ab bellard
            rm = (insn >> 3) & 7;
1530 99c475ab bellard
            shift = (insn >> 6) & 0x1f;
1531 99c475ab bellard
            gen_movl_T0_reg(s, rm);
1532 99c475ab bellard
            gen_shift_T0_im_thumb[op](shift);
1533 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1534 99c475ab bellard
        }
1535 99c475ab bellard
        break;
1536 99c475ab bellard
    case 2: case 3:
1537 99c475ab bellard
        /* arithmetic large immediate */
1538 99c475ab bellard
        op = (insn >> 11) & 3;
1539 99c475ab bellard
        rd = (insn >> 8) & 0x7;
1540 99c475ab bellard
        if (op == 0) {
1541 99c475ab bellard
            gen_op_movl_T0_im(insn & 0xff);
1542 99c475ab bellard
        } else {
1543 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1544 99c475ab bellard
            gen_op_movl_T1_im(insn & 0xff);
1545 99c475ab bellard
        }
1546 99c475ab bellard
        switch (op) {
1547 99c475ab bellard
        case 0: /* mov */
1548 99c475ab bellard
            gen_op_logic_T0_cc();
1549 99c475ab bellard
            break;
1550 99c475ab bellard
        case 1: /* cmp */
1551 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1552 99c475ab bellard
            break;
1553 99c475ab bellard
        case 2: /* add */
1554 99c475ab bellard
            gen_op_addl_T0_T1_cc();
1555 99c475ab bellard
            break;
1556 99c475ab bellard
        case 3: /* sub */
1557 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1558 99c475ab bellard
            break;
1559 99c475ab bellard
        }
1560 99c475ab bellard
        if (op != 1)
1561 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1562 99c475ab bellard
        break;
1563 99c475ab bellard
    case 4:
1564 99c475ab bellard
        if (insn & (1 << 11)) {
1565 99c475ab bellard
            rd = (insn >> 8) & 7;
1566 99c475ab bellard
            /* load pc-relative */
1567 99c475ab bellard
            val = (insn & 0xff) * 4;
1568 99c475ab bellard
            gen_op_movl_T1_im(val);
1569 99c475ab bellard
            gen_movl_T2_reg(s, 15);
1570 99c475ab bellard
            gen_op_addl_T1_T2();
1571 99c475ab bellard
            gen_op_ldl_T0_T1();
1572 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1573 99c475ab bellard
            break;
1574 99c475ab bellard
        }
1575 99c475ab bellard
        if (insn & (1 << 10)) {
1576 99c475ab bellard
            /* data processing extended or blx */
1577 99c475ab bellard
            rd = (insn & 7) | ((insn >> 4) & 8);
1578 99c475ab bellard
            rm = (insn >> 3) & 0xf;
1579 99c475ab bellard
            op = (insn >> 8) & 3;
1580 99c475ab bellard
            switch (op) {
1581 99c475ab bellard
            case 0: /* add */
1582 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1583 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1584 99c475ab bellard
                gen_op_addl_T0_T1();
1585 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1586 99c475ab bellard
                break;
1587 99c475ab bellard
            case 1: /* cmp */
1588 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1589 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1590 99c475ab bellard
                gen_op_subl_T0_T1_cc();
1591 99c475ab bellard
                break;
1592 99c475ab bellard
            case 2: /* mov/cpy */
1593 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1594 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1595 99c475ab bellard
                break;
1596 99c475ab bellard
            case 3:/* branch [and link] exchange thumb register */
1597 99c475ab bellard
                if (insn & (1 << 7)) {
1598 99c475ab bellard
                    val = (uint32_t)s->pc | 1;
1599 99c475ab bellard
                    gen_op_movl_T1_im(val);
1600 99c475ab bellard
                    gen_movl_reg_T1(s, 14);
1601 99c475ab bellard
                }
1602 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1603 99c475ab bellard
                gen_bx(s);
1604 99c475ab bellard
                break;
1605 99c475ab bellard
            }
1606 99c475ab bellard
            break;
1607 99c475ab bellard
        }
1608 99c475ab bellard
1609 99c475ab bellard
        /* data processing register */
1610 99c475ab bellard
        rd = insn & 7;
1611 99c475ab bellard
        rm = (insn >> 3) & 7;
1612 99c475ab bellard
        op = (insn >> 6) & 0xf;
1613 99c475ab bellard
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1614 99c475ab bellard
            /* the shift/rotate ops want the operands backwards */
1615 99c475ab bellard
            val = rm;
1616 99c475ab bellard
            rm = rd;
1617 99c475ab bellard
            rd = val;
1618 99c475ab bellard
            val = 1;
1619 99c475ab bellard
        } else {
1620 99c475ab bellard
            val = 0;
1621 99c475ab bellard
        }
1622 99c475ab bellard
1623 99c475ab bellard
        if (op == 9) /* neg */
1624 99c475ab bellard
            gen_op_movl_T0_im(0);
1625 99c475ab bellard
        else if (op != 0xf) /* mvn doesn't read its first operand */
1626 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1627 99c475ab bellard
1628 99c475ab bellard
        gen_movl_T1_reg(s, rm);
1629 99c475ab bellard
        switch (insn >> 6) {
1630 99c475ab bellard
        case 0x0: /* and */
1631 99c475ab bellard
            gen_op_andl_T0_T1();
1632 99c475ab bellard
            gen_op_logic_T0_cc();
1633 99c475ab bellard
            break;
1634 99c475ab bellard
        case 0x1: /* eor */
1635 99c475ab bellard
            gen_op_xorl_T0_T1();
1636 99c475ab bellard
            gen_op_logic_T0_cc();
1637 99c475ab bellard
            break;
1638 99c475ab bellard
        case 0x2: /* lsl */
1639 99c475ab bellard
            gen_op_shll_T1_T0_cc();
1640 99c475ab bellard
            break;
1641 99c475ab bellard
        case 0x3: /* lsr */
1642 99c475ab bellard
            gen_op_shrl_T1_T0_cc();
1643 99c475ab bellard
            break;
1644 99c475ab bellard
        case 0x4: /* asr */
1645 99c475ab bellard
            gen_op_sarl_T1_T0_cc();
1646 99c475ab bellard
            break;
1647 99c475ab bellard
        case 0x5: /* adc */
1648 99c475ab bellard
            gen_op_adcl_T0_T1_cc();
1649 99c475ab bellard
            break;
1650 99c475ab bellard
        case 0x6: /* sbc */
1651 99c475ab bellard
            gen_op_sbcl_T0_T1_cc();
1652 99c475ab bellard
            break;
1653 99c475ab bellard
        case 0x7: /* ror */
1654 99c475ab bellard
            gen_op_rorl_T1_T0_cc();
1655 99c475ab bellard
            break;
1656 99c475ab bellard
        case 0x8: /* tst */
1657 99c475ab bellard
            gen_op_andl_T0_T1();
1658 99c475ab bellard
            gen_op_logic_T0_cc();
1659 99c475ab bellard
            rd = 16;
1660 99c475ab bellard
        case 0x9: /* neg */
1661 99c475ab bellard
            gen_op_rsbl_T0_T1_cc();
1662 99c475ab bellard
            break;
1663 99c475ab bellard
        case 0xa: /* cmp */
1664 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1665 99c475ab bellard
            rd = 16;
1666 99c475ab bellard
            break;
1667 99c475ab bellard
        case 0xb: /* cmn */
1668 99c475ab bellard
            gen_op_addl_T0_T1_cc();
1669 99c475ab bellard
            rd = 16;
1670 99c475ab bellard
            break;
1671 99c475ab bellard
        case 0xc: /* orr */
1672 99c475ab bellard
            gen_op_orl_T0_T1();
1673 99c475ab bellard
            gen_op_logic_T0_cc();
1674 99c475ab bellard
            break;
1675 99c475ab bellard
        case 0xd: /* mul */
1676 99c475ab bellard
            gen_op_mull_T0_T1();
1677 99c475ab bellard
            gen_op_logic_T0_cc();
1678 99c475ab bellard
            break;
1679 99c475ab bellard
        case 0xe: /* bic */
1680 99c475ab bellard
            gen_op_bicl_T0_T1();
1681 99c475ab bellard
            gen_op_logic_T0_cc();
1682 99c475ab bellard
            break;
1683 99c475ab bellard
        case 0xf: /* mvn */
1684 99c475ab bellard
            gen_op_notl_T1();
1685 99c475ab bellard
            gen_op_logic_T1_cc();
1686 99c475ab bellard
            val = 1;
1687 99c475ab bellard
            break;
1688 99c475ab bellard
        }
1689 99c475ab bellard
        if (rd != 16) {
1690 99c475ab bellard
            if (val)
1691 99c475ab bellard
                gen_movl_reg_T1(s, rd);
1692 99c475ab bellard
            else
1693 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1694 99c475ab bellard
        }
1695 99c475ab bellard
        break;
1696 99c475ab bellard
1697 99c475ab bellard
    case 5:
1698 99c475ab bellard
        /* load/store register offset.  */
1699 99c475ab bellard
        rd = insn & 7;
1700 99c475ab bellard
        rn = (insn >> 3) & 7;
1701 99c475ab bellard
        rm = (insn >> 6) & 7;
1702 99c475ab bellard
        op = (insn >> 9) & 7;
1703 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1704 99c475ab bellard
        gen_movl_T2_reg(s, rm);
1705 99c475ab bellard
        gen_op_addl_T1_T2();
1706 99c475ab bellard
1707 99c475ab bellard
        if (op < 3) /* store */
1708 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1709 99c475ab bellard
1710 99c475ab bellard
        switch (op) {
1711 99c475ab bellard
        case 0: /* str */
1712 99c475ab bellard
            gen_op_stl_T0_T1();
1713 99c475ab bellard
            break;
1714 99c475ab bellard
        case 1: /* strh */
1715 99c475ab bellard
            gen_op_stw_T0_T1();
1716 99c475ab bellard
            break;
1717 99c475ab bellard
        case 2: /* strb */
1718 99c475ab bellard
            gen_op_stb_T0_T1();
1719 99c475ab bellard
            break;
1720 99c475ab bellard
        case 3: /* ldrsb */
1721 99c475ab bellard
            gen_op_ldsb_T0_T1();
1722 99c475ab bellard
            break;
1723 99c475ab bellard
        case 4: /* ldr */
1724 99c475ab bellard
            gen_op_ldl_T0_T1();
1725 99c475ab bellard
            break;
1726 99c475ab bellard
        case 5: /* ldrh */
1727 99c475ab bellard
            gen_op_ldsw_T0_T1();
1728 99c475ab bellard
            break;
1729 99c475ab bellard
        case 6: /* ldrb */
1730 99c475ab bellard
            gen_op_ldub_T0_T1();
1731 99c475ab bellard
            break;
1732 99c475ab bellard
        case 7: /* ldrsh */
1733 99c475ab bellard
            gen_op_ldsw_T0_T1();
1734 99c475ab bellard
            break;
1735 99c475ab bellard
        }
1736 99c475ab bellard
        if (op >= 3) /* load */
1737 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1738 99c475ab bellard
        break;
1739 99c475ab bellard
1740 99c475ab bellard
    case 6:
1741 99c475ab bellard
        /* load/store word immediate offset */
1742 99c475ab bellard
        rd = insn & 7;
1743 99c475ab bellard
        rn = (insn >> 3) & 7;
1744 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1745 99c475ab bellard
        val = (insn >> 4) & 0x7c;
1746 99c475ab bellard
        gen_op_movl_T2_im(val);
1747 99c475ab bellard
        gen_op_addl_T1_T2();
1748 99c475ab bellard
1749 99c475ab bellard
        if (insn & (1 << 11)) {
1750 99c475ab bellard
            /* load */
1751 99c475ab bellard
            gen_op_ldl_T0_T1();
1752 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1753 99c475ab bellard
        } else {
1754 99c475ab bellard
            /* store */
1755 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1756 99c475ab bellard
            gen_op_stl_T0_T1();
1757 99c475ab bellard
        }
1758 99c475ab bellard
        break;
1759 99c475ab bellard
1760 99c475ab bellard
    case 7:
1761 99c475ab bellard
        /* load/store byte immediate offset */
1762 99c475ab bellard
        rd = insn & 7;
1763 99c475ab bellard
        rn = (insn >> 3) & 7;
1764 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1765 99c475ab bellard
        val = (insn >> 6) & 0x1f;
1766 99c475ab bellard
        gen_op_movl_T2_im(val);
1767 99c475ab bellard
        gen_op_addl_T1_T2();
1768 99c475ab bellard
1769 99c475ab bellard
        if (insn & (1 << 11)) {
1770 99c475ab bellard
            /* load */
1771 99c475ab bellard
            gen_op_ldub_T0_T1();
1772 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1773 99c475ab bellard
        } else {
1774 99c475ab bellard
            /* store */
1775 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1776 99c475ab bellard
            gen_op_stb_T0_T1();
1777 99c475ab bellard
        }
1778 99c475ab bellard
        break;
1779 99c475ab bellard
1780 99c475ab bellard
    case 8:
1781 99c475ab bellard
        /* load/store halfword immediate offset */
1782 99c475ab bellard
        rd = insn & 7;
1783 99c475ab bellard
        rn = (insn >> 3) & 7;
1784 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1785 99c475ab bellard
        val = (insn >> 5) & 0x3e;
1786 99c475ab bellard
        gen_op_movl_T2_im(val);
1787 99c475ab bellard
        gen_op_addl_T1_T2();
1788 99c475ab bellard
1789 99c475ab bellard
        if (insn & (1 << 11)) {
1790 99c475ab bellard
            /* load */
1791 99c475ab bellard
            gen_op_lduw_T0_T1();
1792 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1793 99c475ab bellard
        } else {
1794 99c475ab bellard
            /* store */
1795 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1796 99c475ab bellard
            gen_op_stw_T0_T1();
1797 99c475ab bellard
        }
1798 99c475ab bellard
        break;
1799 99c475ab bellard
1800 99c475ab bellard
    case 9:
1801 99c475ab bellard
        /* load/store from stack */
1802 99c475ab bellard
        rd = (insn >> 8) & 7;
1803 99c475ab bellard
        gen_movl_T1_reg(s, 13);
1804 99c475ab bellard
        val = (insn & 0xff) * 4;
1805 99c475ab bellard
        gen_op_movl_T2_im(val);
1806 99c475ab bellard
        gen_op_addl_T1_T2();
1807 99c475ab bellard
1808 99c475ab bellard
        if (insn & (1 << 11)) {
1809 99c475ab bellard
            /* load */
1810 99c475ab bellard
            gen_op_ldl_T0_T1();
1811 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1812 99c475ab bellard
        } else {
1813 99c475ab bellard
            /* store */
1814 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1815 99c475ab bellard
            gen_op_stl_T0_T1();
1816 99c475ab bellard
        }
1817 99c475ab bellard
        break;
1818 99c475ab bellard
1819 99c475ab bellard
    case 10:
1820 99c475ab bellard
        /* add to high reg */
1821 99c475ab bellard
        rd = (insn >> 8) & 7;
1822 99c475ab bellard
        if (insn & (1 << 11))
1823 99c475ab bellard
            rm = 13; /* sp */
1824 99c475ab bellard
        else
1825 99c475ab bellard
            rm = 15; /* pc */
1826 99c475ab bellard
        gen_movl_T0_reg(s, rm);
1827 99c475ab bellard
        val = (insn & 0xff) * 4;
1828 99c475ab bellard
        gen_op_movl_T1_im(val);
1829 99c475ab bellard
        gen_op_addl_T0_T1();
1830 99c475ab bellard
        gen_movl_reg_T0(s, rd);
1831 99c475ab bellard
        break;
1832 99c475ab bellard
1833 99c475ab bellard
    case 11:
1834 99c475ab bellard
        /* misc */
1835 99c475ab bellard
        op = (insn >> 8) & 0xf;
1836 99c475ab bellard
        switch (op) {
1837 99c475ab bellard
        case 0:
1838 99c475ab bellard
            /* adjust stack pointer */
1839 99c475ab bellard
            gen_movl_T1_reg(s, 13);
1840 99c475ab bellard
            val = (insn & 0x7f) * 4;
1841 99c475ab bellard
            if (insn & (1 << 7))
1842 99c475ab bellard
              val = -(int32_t)val;
1843 99c475ab bellard
            gen_op_movl_T2_im(val);
1844 99c475ab bellard
            gen_op_addl_T1_T2();
1845 99c475ab bellard
            gen_movl_reg_T1(s, 13);
1846 99c475ab bellard
            break;
1847 99c475ab bellard
1848 99c475ab bellard
        case 4: case 5: case 0xc: case 0xd:
1849 99c475ab bellard
            /* push/pop */
1850 99c475ab bellard
            gen_movl_T1_reg(s, 13);
1851 99c475ab bellard
            if (insn & (1 << 11))
1852 99c475ab bellard
                val = 4;
1853 99c475ab bellard
            else
1854 99c475ab bellard
                val = -4;
1855 99c475ab bellard
            gen_op_movl_T2_im(val);
1856 99c475ab bellard
            for (i = 0; i < 8; i++) {
1857 99c475ab bellard
                if (insn & (1 << i)) {
1858 99c475ab bellard
                    if (insn & (1 << 11)) {
1859 99c475ab bellard
                        /* pop */
1860 99c475ab bellard
                        gen_op_ldl_T0_T1();
1861 99c475ab bellard
                        gen_movl_reg_T0(s, i);
1862 99c475ab bellard
                    } else {
1863 99c475ab bellard
                        /* push */
1864 99c475ab bellard
                        gen_movl_T0_reg(s, i);
1865 99c475ab bellard
                        gen_op_stl_T0_T1();
1866 99c475ab bellard
                    }
1867 99c475ab bellard
                    /* move to the next address */
1868 99c475ab bellard
                    gen_op_addl_T1_T2();
1869 99c475ab bellard
                }
1870 99c475ab bellard
            }
1871 99c475ab bellard
            if (insn & (1 << 8)) {
1872 99c475ab bellard
                if (insn & (1 << 11)) {
1873 99c475ab bellard
                    /* pop pc */
1874 99c475ab bellard
                    gen_op_ldl_T0_T1();
1875 99c475ab bellard
                    /* don't set the pc until the rest of the instruction
1876 99c475ab bellard
                       has completed */
1877 99c475ab bellard
                } else {
1878 99c475ab bellard
                    /* push lr */
1879 99c475ab bellard
                    gen_movl_T0_reg(s, 14);
1880 99c475ab bellard
                    gen_op_stl_T0_T1();
1881 99c475ab bellard
                }
1882 99c475ab bellard
                gen_op_addl_T1_T2();
1883 99c475ab bellard
            }
1884 99c475ab bellard
1885 99c475ab bellard
            /* write back the new stack pointer */
1886 99c475ab bellard
            gen_movl_reg_T1(s, 13);
1887 99c475ab bellard
            /* set the new PC value */
1888 99c475ab bellard
            if ((insn & 0x0900) == 0x0900)
1889 99c475ab bellard
                gen_bx(s);
1890 99c475ab bellard
            break;
1891 99c475ab bellard
1892 99c475ab bellard
        default:
1893 99c475ab bellard
            goto undef;
1894 99c475ab bellard
        }
1895 99c475ab bellard
        break;
1896 99c475ab bellard
1897 99c475ab bellard
    case 12:
1898 99c475ab bellard
        /* load/store multiple */
1899 99c475ab bellard
        rn = (insn >> 8) & 0x7;
1900 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1901 99c475ab bellard
        gen_op_movl_T2_im(4);
1902 99c475ab bellard
        val = 0;
1903 99c475ab bellard
        for (i = 0; i < 8; i++) {
1904 99c475ab bellard
            if (insn & (1 << i)) {
1905 99c475ab bellard
                /* advance to the next address */
1906 99c475ab bellard
                if (val)
1907 99c475ab bellard
                    gen_op_addl_T1_T2();
1908 99c475ab bellard
                else
1909 99c475ab bellard
                    val = 1;
1910 99c475ab bellard
                if (insn & (1 << 11)) {
1911 99c475ab bellard
                    /* load */
1912 99c475ab bellard
                    gen_op_ldl_T0_T1();
1913 99c475ab bellard
                    gen_movl_reg_T0(s, i);
1914 99c475ab bellard
                } else {
1915 99c475ab bellard
                    /* store */
1916 99c475ab bellard
                    gen_movl_T0_reg(s, i);
1917 99c475ab bellard
                    gen_op_stl_T0_T1();
1918 99c475ab bellard
                }
1919 99c475ab bellard
            }
1920 99c475ab bellard
        }
1921 99c475ab bellard
        break;
1922 99c475ab bellard
1923 99c475ab bellard
    case 13:
1924 99c475ab bellard
        /* conditional branch or swi */
1925 99c475ab bellard
        cond = (insn >> 8) & 0xf;
1926 99c475ab bellard
        if (cond == 0xe)
1927 99c475ab bellard
            goto undef;
1928 99c475ab bellard
1929 99c475ab bellard
        if (cond == 0xf) {
1930 99c475ab bellard
            /* swi */
1931 99c475ab bellard
            gen_op_movl_T0_im((long)s->pc | 1);
1932 99c475ab bellard
            /* Don't set r15.  */
1933 99c475ab bellard
            gen_op_movl_reg_TN[0][15]();
1934 99c475ab bellard
            gen_op_swi();
1935 99c475ab bellard
            s->is_jmp = DISAS_JUMP;
1936 99c475ab bellard
            break;
1937 99c475ab bellard
        }
1938 99c475ab bellard
        /* generate a conditional jump to next instruction */
1939 99c475ab bellard
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1940 99c475ab bellard
        s->is_jmp = DISAS_JUMP_NEXT;
1941 99c475ab bellard
        gen_movl_T1_reg(s, 15);
1942 99c475ab bellard
1943 99c475ab bellard
        /* jump to the offset */
1944 99c475ab bellard
        val = (uint32_t)s->pc;
1945 99c475ab bellard
        offset = ((int32_t)insn << 24) >> 24;
1946 99c475ab bellard
        val += (offset << 1) + 2;
1947 99c475ab bellard
        gen_op_jmp((long)s->tb, val);
1948 99c475ab bellard
        s->is_jmp = DISAS_TB_JUMP;
1949 99c475ab bellard
        break;
1950 99c475ab bellard
1951 99c475ab bellard
    case 14:
1952 99c475ab bellard
        /* unconditional branch */
1953 99c475ab bellard
        if (insn & (1 << 11))
1954 99c475ab bellard
            goto undef; /* Second half of a blx */
1955 99c475ab bellard
        val = (uint32_t)s->pc;
1956 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 21;
1957 99c475ab bellard
        val += (offset << 1) + 2;
1958 99c475ab bellard
        gen_op_jmp((long)s->tb, val);
1959 99c475ab bellard
        s->is_jmp = DISAS_TB_JUMP;
1960 99c475ab bellard
        break;
1961 99c475ab bellard
1962 99c475ab bellard
    case 15:
1963 99c475ab bellard
        /* branch and link [and switch to arm] */
1964 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 10;
1965 99c475ab bellard
        insn = lduw(s->pc);
1966 99c475ab bellard
        offset |= insn & 0x7ff;
1967 99c475ab bellard
1968 99c475ab bellard
        val = (uint32_t)s->pc + 2;
1969 99c475ab bellard
        gen_op_movl_T1_im(val | 1);
1970 99c475ab bellard
        gen_movl_reg_T1(s, 14);
1971 99c475ab bellard
        
1972 99c475ab bellard
        val += offset;
1973 99c475ab bellard
        if (insn & (1 << 11)) {
1974 99c475ab bellard
            /* bl */
1975 99c475ab bellard
            gen_op_jmp((long)s->tb, val);
1976 99c475ab bellard
            s->is_jmp = DISAS_TB_JUMP;
1977 99c475ab bellard
        } else {
1978 99c475ab bellard
            /* blx */
1979 99c475ab bellard
            gen_op_movl_T0_im(val);
1980 99c475ab bellard
            gen_bx(s);
1981 99c475ab bellard
        }
1982 99c475ab bellard
    }
1983 99c475ab bellard
    return;
1984 99c475ab bellard
undef:
1985 99c475ab bellard
    gen_op_movl_T0_im((long)s->pc - 4);
1986 99c475ab bellard
    gen_op_movl_reg_TN[0][15]();
1987 99c475ab bellard
    gen_op_undef_insn();
1988 99c475ab bellard
    s->is_jmp = DISAS_JUMP;
1989 99c475ab bellard
}
1990 99c475ab bellard
1991 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1992 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
1993 2c0262af bellard
   information for each intermediate instruction. */
1994 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env, 
1995 2c0262af bellard
                                                 TranslationBlock *tb, 
1996 2c0262af bellard
                                                 int search_pc)
1997 2c0262af bellard
{
1998 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
1999 2c0262af bellard
    uint16_t *gen_opc_end;
2000 2c0262af bellard
    int j, lj;
2001 0fa85d43 bellard
    target_ulong pc_start;
2002 2c0262af bellard
    
2003 2c0262af bellard
    /* generate intermediate code */
2004 0fa85d43 bellard
    pc_start = tb->pc;
2005 2c0262af bellard
       
2006 2c0262af bellard
    dc->tb = tb;
2007 2c0262af bellard
2008 2c0262af bellard
    gen_opc_ptr = gen_opc_buf;
2009 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2010 2c0262af bellard
    gen_opparam_ptr = gen_opparam_buf;
2011 2c0262af bellard
2012 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
2013 2c0262af bellard
    dc->pc = pc_start;
2014 2c0262af bellard
    lj = -1;
2015 2c0262af bellard
    do {
2016 2c0262af bellard
        if (search_pc) {
2017 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
2018 2c0262af bellard
            if (lj < j) {
2019 2c0262af bellard
                lj++;
2020 2c0262af bellard
                while (lj < j)
2021 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
2022 2c0262af bellard
            }
2023 0fa85d43 bellard
            gen_opc_pc[lj] = dc->pc;
2024 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
2025 2c0262af bellard
        }
2026 99c475ab bellard
        if (env->thumb)
2027 99c475ab bellard
          disas_thumb_insn(dc);
2028 99c475ab bellard
        else
2029 b7bcbe95 bellard
          disas_arm_insn(env, dc);
2030 2c0262af bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
2031 2c0262af bellard
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2032 2c0262af bellard
    switch(dc->is_jmp) {
2033 2c0262af bellard
    case DISAS_JUMP_NEXT:
2034 2c0262af bellard
    case DISAS_NEXT:
2035 2c0262af bellard
        gen_op_jmp((long)dc->tb, (long)dc->pc);
2036 2c0262af bellard
        break;
2037 2c0262af bellard
    default:
2038 2c0262af bellard
    case DISAS_JUMP:
2039 99c475ab bellard
    case DISAS_UPDATE:
2040 2c0262af bellard
        /* indicate that the hash table must be used to find the next TB */
2041 2c0262af bellard
        gen_op_movl_T0_0();
2042 2c0262af bellard
        gen_op_exit_tb();
2043 2c0262af bellard
        break;
2044 2c0262af bellard
    case DISAS_TB_JUMP:
2045 2c0262af bellard
        /* nothing more to generate */
2046 2c0262af bellard
        break;
2047 2c0262af bellard
    }
2048 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
2049 2c0262af bellard
2050 2c0262af bellard
#ifdef DEBUG_DISAS
2051 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2052 2c0262af bellard
        fprintf(logfile, "----------------\n");
2053 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2054 0fa85d43 bellard
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2055 2c0262af bellard
        fprintf(logfile, "\n");
2056 e19e89a5 bellard
        if (loglevel & (CPU_LOG_TB_OP)) {
2057 e19e89a5 bellard
            fprintf(logfile, "OP:\n");
2058 e19e89a5 bellard
            dump_ops(gen_opc_buf, gen_opparam_buf);
2059 e19e89a5 bellard
            fprintf(logfile, "\n");
2060 e19e89a5 bellard
        }
2061 2c0262af bellard
    }
2062 2c0262af bellard
#endif
2063 2c0262af bellard
    if (!search_pc)
2064 2c0262af bellard
        tb->size = dc->pc - pc_start;
2065 2c0262af bellard
    return 0;
2066 2c0262af bellard
}
2067 2c0262af bellard
2068 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2069 2c0262af bellard
{
2070 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
2071 2c0262af bellard
}
2072 2c0262af bellard
2073 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2074 2c0262af bellard
{
2075 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
2076 2c0262af bellard
}
2077 2c0262af bellard
2078 2c0262af bellard
CPUARMState *cpu_arm_init(void)
2079 2c0262af bellard
{
2080 2c0262af bellard
    CPUARMState *env;
2081 2c0262af bellard
2082 2c0262af bellard
    cpu_exec_init();
2083 2c0262af bellard
2084 2c0262af bellard
    env = malloc(sizeof(CPUARMState));
2085 2c0262af bellard
    if (!env)
2086 2c0262af bellard
        return NULL;
2087 2c0262af bellard
    memset(env, 0, sizeof(CPUARMState));
2088 7496f526 bellard
    cpu_single_env = env;
2089 2c0262af bellard
    return env;
2090 2c0262af bellard
}
2091 2c0262af bellard
2092 2c0262af bellard
void cpu_arm_close(CPUARMState *env)
2093 2c0262af bellard
{
2094 2c0262af bellard
    free(env);
2095 2c0262af bellard
}
2096 2c0262af bellard
2097 7fe48483 bellard
void cpu_dump_state(CPUState *env, FILE *f, 
2098 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2099 7fe48483 bellard
                    int flags)
2100 2c0262af bellard
{
2101 2c0262af bellard
    int i;
2102 b7bcbe95 bellard
    struct {
2103 b7bcbe95 bellard
        uint32_t i;
2104 b7bcbe95 bellard
        float s;
2105 b7bcbe95 bellard
    } s0, s1;
2106 b7bcbe95 bellard
    CPU_DoubleU d;
2107 2c0262af bellard
2108 2c0262af bellard
    for(i=0;i<16;i++) {
2109 7fe48483 bellard
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2110 2c0262af bellard
        if ((i % 4) == 3)
2111 7fe48483 bellard
            cpu_fprintf(f, "\n");
2112 2c0262af bellard
        else
2113 7fe48483 bellard
            cpu_fprintf(f, " ");
2114 2c0262af bellard
    }
2115 7fe48483 bellard
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
2116 b7bcbe95 bellard
             env->cpsr, 
2117 2c0262af bellard
            env->cpsr & (1 << 31) ? 'N' : '-',
2118 2c0262af bellard
            env->cpsr & (1 << 30) ? 'Z' : '-',
2119 2c0262af bellard
            env->cpsr & (1 << 29) ? 'C' : '-',
2120 2c0262af bellard
            env->cpsr & (1 << 28) ? 'V' : '-');
2121 b7bcbe95 bellard
2122 b7bcbe95 bellard
    for (i = 0; i < 16; i++) {
2123 b7bcbe95 bellard
        s0.s = env->vfp.regs.s[i * 2];
2124 b7bcbe95 bellard
        s1.s = env->vfp.regs.s[i * 2 + 1];
2125 b7bcbe95 bellard
        d.d = env->vfp.regs.d[i];
2126 b7bcbe95 bellard
        cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2127 b7bcbe95 bellard
                    i * 2, (int)s0.i, s0.s,
2128 b7bcbe95 bellard
                    i * 2 + 1, (int)s0.i, s0.s,
2129 b7bcbe95 bellard
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2130 b7bcbe95 bellard
                    d.d);
2131 b7bcbe95 bellard
        cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2132 b7bcbe95 bellard
    }
2133 2c0262af bellard
}
2134 a6b025d3 bellard
2135 a6b025d3 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2136 a6b025d3 bellard
{
2137 a6b025d3 bellard
    return addr;
2138 a6b025d3 bellard
}
2139 b8a9e8f1 bellard
2140 b8a9e8f1 bellard
#if defined(CONFIG_USER_ONLY) 
2141 b8a9e8f1 bellard
2142 b8a9e8f1 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2143 b8a9e8f1 bellard
                              int is_user, int is_softmmu)
2144 b8a9e8f1 bellard
{
2145 b8a9e8f1 bellard
    env->cp15_6 = address;
2146 b8a9e8f1 bellard
    if (rw == 2) {
2147 b8a9e8f1 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
2148 b8a9e8f1 bellard
    } else {
2149 b8a9e8f1 bellard
        env->exception_index = EXCP_DATA_ABORT;
2150 b8a9e8f1 bellard
    }
2151 b8a9e8f1 bellard
    return 1;
2152 b8a9e8f1 bellard
}
2153 b8a9e8f1 bellard
2154 b8a9e8f1 bellard
#else
2155 b8a9e8f1 bellard
2156 b8a9e8f1 bellard
#error not implemented
2157 b8a9e8f1 bellard
2158 b8a9e8f1 bellard
#endif