Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 173d6cfe

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