Statistics
| Branch: | Revision:

root / target-arm / translate.c @ afc7df11

History | View | Annotate | Download (44.8 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  ARM translation
3 2c0262af bellard
 * 
4 2c0262af bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 2c0262af bellard
 *
6 2c0262af bellard
 * This library is free software; you can redistribute it and/or
7 2c0262af bellard
 * modify it under the terms of the GNU Lesser General Public
8 2c0262af bellard
 * License as published by the Free Software Foundation; either
9 2c0262af bellard
 * version 2 of the License, or (at your option) any later version.
10 2c0262af bellard
 *
11 2c0262af bellard
 * This library is distributed in the hope that it will be useful,
12 2c0262af bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 2c0262af bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 2c0262af bellard
 * Lesser General Public License for more details.
15 2c0262af bellard
 *
16 2c0262af bellard
 * You should have received a copy of the GNU Lesser General Public
17 2c0262af bellard
 * License along with this library; if not, write to the Free Software
18 2c0262af bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 2c0262af bellard
 */
20 2c0262af bellard
#include <stdarg.h>
21 2c0262af bellard
#include <stdlib.h>
22 2c0262af bellard
#include <stdio.h>
23 2c0262af bellard
#include <string.h>
24 2c0262af bellard
#include <inttypes.h>
25 2c0262af bellard
26 2c0262af bellard
#include "cpu.h"
27 2c0262af bellard
#include "exec-all.h"
28 2c0262af bellard
#include "disas.h"
29 2c0262af bellard
30 2c0262af bellard
/* internal defines */
31 2c0262af bellard
typedef struct DisasContext {
32 0fa85d43 bellard
    target_ulong pc;
33 2c0262af bellard
    int is_jmp;
34 2c0262af bellard
    struct TranslationBlock *tb;
35 2c0262af bellard
} DisasContext;
36 2c0262af bellard
37 2c0262af bellard
#define DISAS_JUMP_NEXT 4
38 2c0262af bellard
39 2c0262af bellard
/* XXX: move that elsewhere */
40 2c0262af bellard
static uint16_t *gen_opc_ptr;
41 2c0262af bellard
static uint32_t *gen_opparam_ptr;
42 2c0262af bellard
extern FILE *logfile;
43 2c0262af bellard
extern int loglevel;
44 2c0262af bellard
45 2c0262af bellard
enum {
46 2c0262af bellard
#define DEF(s, n, copy_size) INDEX_op_ ## s,
47 2c0262af bellard
#include "opc.h"
48 2c0262af bellard
#undef DEF
49 2c0262af bellard
    NB_OPS,
50 2c0262af bellard
};
51 2c0262af bellard
52 2c0262af bellard
#include "gen-op.h"
53 2c0262af bellard
54 2c0262af bellard
static GenOpFunc2 *gen_test_cc[14] = {
55 2c0262af bellard
    gen_op_test_eq,
56 2c0262af bellard
    gen_op_test_ne,
57 2c0262af bellard
    gen_op_test_cs,
58 2c0262af bellard
    gen_op_test_cc,
59 2c0262af bellard
    gen_op_test_mi,
60 2c0262af bellard
    gen_op_test_pl,
61 2c0262af bellard
    gen_op_test_vs,
62 2c0262af bellard
    gen_op_test_vc,
63 2c0262af bellard
    gen_op_test_hi,
64 2c0262af bellard
    gen_op_test_ls,
65 2c0262af bellard
    gen_op_test_ge,
66 2c0262af bellard
    gen_op_test_lt,
67 2c0262af bellard
    gen_op_test_gt,
68 2c0262af bellard
    gen_op_test_le,
69 2c0262af bellard
};
70 2c0262af bellard
71 2c0262af bellard
const uint8_t table_logic_cc[16] = {
72 2c0262af bellard
    1, /* and */
73 2c0262af bellard
    1, /* xor */
74 2c0262af bellard
    0, /* sub */
75 2c0262af bellard
    0, /* rsb */
76 2c0262af bellard
    0, /* add */
77 2c0262af bellard
    0, /* adc */
78 2c0262af bellard
    0, /* sbc */
79 2c0262af bellard
    0, /* rsc */
80 2c0262af bellard
    1, /* andl */
81 2c0262af bellard
    1, /* xorl */
82 2c0262af bellard
    0, /* cmp */
83 2c0262af bellard
    0, /* cmn */
84 2c0262af bellard
    1, /* orr */
85 2c0262af bellard
    1, /* mov */
86 2c0262af bellard
    1, /* bic */
87 2c0262af bellard
    1, /* mvn */
88 2c0262af bellard
};
89 2c0262af bellard
    
90 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im[4] = {
91 2c0262af bellard
    gen_op_shll_T1_im,
92 2c0262af bellard
    gen_op_shrl_T1_im,
93 2c0262af bellard
    gen_op_sarl_T1_im,
94 2c0262af bellard
    gen_op_rorl_T1_im,
95 2c0262af bellard
};
96 2c0262af bellard
97 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0[4] = {
98 1e8d4eec bellard
    NULL,
99 1e8d4eec bellard
    gen_op_shrl_T1_0,
100 1e8d4eec bellard
    gen_op_sarl_T1_0,
101 1e8d4eec bellard
    gen_op_rrxl_T1,
102 1e8d4eec bellard
};
103 1e8d4eec bellard
104 2c0262af bellard
static GenOpFunc1 *gen_shift_T2_im[4] = {
105 2c0262af bellard
    gen_op_shll_T2_im,
106 2c0262af bellard
    gen_op_shrl_T2_im,
107 2c0262af bellard
    gen_op_sarl_T2_im,
108 2c0262af bellard
    gen_op_rorl_T2_im,
109 2c0262af bellard
};
110 2c0262af bellard
111 1e8d4eec bellard
static GenOpFunc *gen_shift_T2_0[4] = {
112 1e8d4eec bellard
    NULL,
113 1e8d4eec bellard
    gen_op_shrl_T2_0,
114 1e8d4eec bellard
    gen_op_sarl_T2_0,
115 1e8d4eec bellard
    gen_op_rrxl_T2,
116 1e8d4eec bellard
};
117 1e8d4eec bellard
118 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
119 2c0262af bellard
    gen_op_shll_T1_im_cc,
120 2c0262af bellard
    gen_op_shrl_T1_im_cc,
121 2c0262af bellard
    gen_op_sarl_T1_im_cc,
122 2c0262af bellard
    gen_op_rorl_T1_im_cc,
123 2c0262af bellard
};
124 2c0262af bellard
125 1e8d4eec bellard
static GenOpFunc *gen_shift_T1_0_cc[4] = {
126 1e8d4eec bellard
    NULL,
127 1e8d4eec bellard
    gen_op_shrl_T1_0_cc,
128 1e8d4eec bellard
    gen_op_sarl_T1_0_cc,
129 1e8d4eec bellard
    gen_op_rrxl_T1_cc,
130 1e8d4eec bellard
};
131 1e8d4eec bellard
132 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0[4] = {
133 2c0262af bellard
    gen_op_shll_T1_T0,
134 2c0262af bellard
    gen_op_shrl_T1_T0,
135 2c0262af bellard
    gen_op_sarl_T1_T0,
136 2c0262af bellard
    gen_op_rorl_T1_T0,
137 2c0262af bellard
};
138 2c0262af bellard
139 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
140 2c0262af bellard
    gen_op_shll_T1_T0_cc,
141 2c0262af bellard
    gen_op_shrl_T1_T0_cc,
142 2c0262af bellard
    gen_op_sarl_T1_T0_cc,
143 2c0262af bellard
    gen_op_rorl_T1_T0_cc,
144 2c0262af bellard
};
145 2c0262af bellard
146 2c0262af bellard
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
147 2c0262af bellard
    {
148 2c0262af bellard
        gen_op_movl_T0_r0,
149 2c0262af bellard
        gen_op_movl_T0_r1,
150 2c0262af bellard
        gen_op_movl_T0_r2,
151 2c0262af bellard
        gen_op_movl_T0_r3,
152 2c0262af bellard
        gen_op_movl_T0_r4,
153 2c0262af bellard
        gen_op_movl_T0_r5,
154 2c0262af bellard
        gen_op_movl_T0_r6,
155 2c0262af bellard
        gen_op_movl_T0_r7,
156 2c0262af bellard
        gen_op_movl_T0_r8,
157 2c0262af bellard
        gen_op_movl_T0_r9,
158 2c0262af bellard
        gen_op_movl_T0_r10,
159 2c0262af bellard
        gen_op_movl_T0_r11,
160 2c0262af bellard
        gen_op_movl_T0_r12,
161 2c0262af bellard
        gen_op_movl_T0_r13,
162 2c0262af bellard
        gen_op_movl_T0_r14,
163 2c0262af bellard
        gen_op_movl_T0_r15,
164 2c0262af bellard
    },
165 2c0262af bellard
    {
166 2c0262af bellard
        gen_op_movl_T1_r0,
167 2c0262af bellard
        gen_op_movl_T1_r1,
168 2c0262af bellard
        gen_op_movl_T1_r2,
169 2c0262af bellard
        gen_op_movl_T1_r3,
170 2c0262af bellard
        gen_op_movl_T1_r4,
171 2c0262af bellard
        gen_op_movl_T1_r5,
172 2c0262af bellard
        gen_op_movl_T1_r6,
173 2c0262af bellard
        gen_op_movl_T1_r7,
174 2c0262af bellard
        gen_op_movl_T1_r8,
175 2c0262af bellard
        gen_op_movl_T1_r9,
176 2c0262af bellard
        gen_op_movl_T1_r10,
177 2c0262af bellard
        gen_op_movl_T1_r11,
178 2c0262af bellard
        gen_op_movl_T1_r12,
179 2c0262af bellard
        gen_op_movl_T1_r13,
180 2c0262af bellard
        gen_op_movl_T1_r14,
181 2c0262af bellard
        gen_op_movl_T1_r15,
182 2c0262af bellard
    },
183 2c0262af bellard
    {
184 2c0262af bellard
        gen_op_movl_T2_r0,
185 2c0262af bellard
        gen_op_movl_T2_r1,
186 2c0262af bellard
        gen_op_movl_T2_r2,
187 2c0262af bellard
        gen_op_movl_T2_r3,
188 2c0262af bellard
        gen_op_movl_T2_r4,
189 2c0262af bellard
        gen_op_movl_T2_r5,
190 2c0262af bellard
        gen_op_movl_T2_r6,
191 2c0262af bellard
        gen_op_movl_T2_r7,
192 2c0262af bellard
        gen_op_movl_T2_r8,
193 2c0262af bellard
        gen_op_movl_T2_r9,
194 2c0262af bellard
        gen_op_movl_T2_r10,
195 2c0262af bellard
        gen_op_movl_T2_r11,
196 2c0262af bellard
        gen_op_movl_T2_r12,
197 2c0262af bellard
        gen_op_movl_T2_r13,
198 2c0262af bellard
        gen_op_movl_T2_r14,
199 2c0262af bellard
        gen_op_movl_T2_r15,
200 2c0262af bellard
    },
201 2c0262af bellard
};
202 2c0262af bellard
203 2c0262af bellard
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
204 2c0262af bellard
    {
205 2c0262af bellard
        gen_op_movl_r0_T0,
206 2c0262af bellard
        gen_op_movl_r1_T0,
207 2c0262af bellard
        gen_op_movl_r2_T0,
208 2c0262af bellard
        gen_op_movl_r3_T0,
209 2c0262af bellard
        gen_op_movl_r4_T0,
210 2c0262af bellard
        gen_op_movl_r5_T0,
211 2c0262af bellard
        gen_op_movl_r6_T0,
212 2c0262af bellard
        gen_op_movl_r7_T0,
213 2c0262af bellard
        gen_op_movl_r8_T0,
214 2c0262af bellard
        gen_op_movl_r9_T0,
215 2c0262af bellard
        gen_op_movl_r10_T0,
216 2c0262af bellard
        gen_op_movl_r11_T0,
217 2c0262af bellard
        gen_op_movl_r12_T0,
218 2c0262af bellard
        gen_op_movl_r13_T0,
219 2c0262af bellard
        gen_op_movl_r14_T0,
220 2c0262af bellard
        gen_op_movl_r15_T0,
221 2c0262af bellard
    },
222 2c0262af bellard
    {
223 2c0262af bellard
        gen_op_movl_r0_T1,
224 2c0262af bellard
        gen_op_movl_r1_T1,
225 2c0262af bellard
        gen_op_movl_r2_T1,
226 2c0262af bellard
        gen_op_movl_r3_T1,
227 2c0262af bellard
        gen_op_movl_r4_T1,
228 2c0262af bellard
        gen_op_movl_r5_T1,
229 2c0262af bellard
        gen_op_movl_r6_T1,
230 2c0262af bellard
        gen_op_movl_r7_T1,
231 2c0262af bellard
        gen_op_movl_r8_T1,
232 2c0262af bellard
        gen_op_movl_r9_T1,
233 2c0262af bellard
        gen_op_movl_r10_T1,
234 2c0262af bellard
        gen_op_movl_r11_T1,
235 2c0262af bellard
        gen_op_movl_r12_T1,
236 2c0262af bellard
        gen_op_movl_r13_T1,
237 2c0262af bellard
        gen_op_movl_r14_T1,
238 2c0262af bellard
        gen_op_movl_r15_T1,
239 2c0262af bellard
    },
240 2c0262af bellard
};
241 2c0262af bellard
242 2c0262af bellard
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
243 2c0262af bellard
    gen_op_movl_T0_im,
244 2c0262af bellard
    gen_op_movl_T1_im,
245 2c0262af bellard
    gen_op_movl_T2_im,
246 2c0262af bellard
};
247 2c0262af bellard
248 99c475ab bellard
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
249 99c475ab bellard
    gen_op_shll_T0_im_thumb,
250 99c475ab bellard
    gen_op_shrl_T0_im_thumb,
251 99c475ab bellard
    gen_op_sarl_T0_im_thumb,
252 99c475ab bellard
};
253 99c475ab bellard
254 99c475ab bellard
static inline void gen_bx(DisasContext *s)
255 99c475ab bellard
{
256 99c475ab bellard
  s->is_jmp = DISAS_UPDATE;
257 99c475ab bellard
  gen_op_bx_T0();
258 99c475ab bellard
}
259 99c475ab bellard
260 2c0262af bellard
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
261 2c0262af bellard
{
262 2c0262af bellard
    int val;
263 2c0262af bellard
264 2c0262af bellard
    if (reg == 15) {
265 2c0262af bellard
        /* normaly, since we updated PC, we need only to add 4 */
266 2c0262af bellard
        val = (long)s->pc + 4;
267 2c0262af bellard
        gen_op_movl_TN_im[t](val);
268 2c0262af bellard
    } else {
269 2c0262af bellard
        gen_op_movl_TN_reg[t][reg]();
270 2c0262af bellard
    }
271 2c0262af bellard
}
272 2c0262af bellard
273 2c0262af bellard
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
274 2c0262af bellard
{
275 2c0262af bellard
    gen_movl_TN_reg(s, reg, 0);
276 2c0262af bellard
}
277 2c0262af bellard
278 2c0262af bellard
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
279 2c0262af bellard
{
280 2c0262af bellard
    gen_movl_TN_reg(s, reg, 1);
281 2c0262af bellard
}
282 2c0262af bellard
283 2c0262af bellard
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
284 2c0262af bellard
{
285 2c0262af bellard
    gen_movl_TN_reg(s, reg, 2);
286 2c0262af bellard
}
287 2c0262af bellard
288 2c0262af bellard
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
289 2c0262af bellard
{
290 2c0262af bellard
    gen_op_movl_reg_TN[t][reg]();
291 2c0262af bellard
    if (reg == 15) {
292 2c0262af bellard
        s->is_jmp = DISAS_JUMP;
293 2c0262af bellard
    }
294 2c0262af bellard
}
295 2c0262af bellard
296 2c0262af bellard
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
297 2c0262af bellard
{
298 2c0262af bellard
    gen_movl_reg_TN(s, reg, 0);
299 2c0262af bellard
}
300 2c0262af bellard
301 2c0262af bellard
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
302 2c0262af bellard
{
303 2c0262af bellard
    gen_movl_reg_TN(s, reg, 1);
304 2c0262af bellard
}
305 2c0262af bellard
306 2c0262af bellard
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
307 2c0262af bellard
{
308 1e8d4eec bellard
    int val, rm, shift, shiftop;
309 2c0262af bellard
310 2c0262af bellard
    if (!(insn & (1 << 25))) {
311 2c0262af bellard
        /* immediate */
312 2c0262af bellard
        val = insn & 0xfff;
313 2c0262af bellard
        if (!(insn & (1 << 23)))
314 2c0262af bellard
            val = -val;
315 537730b9 bellard
        if (val != 0)
316 537730b9 bellard
            gen_op_addl_T1_im(val);
317 2c0262af bellard
    } else {
318 2c0262af bellard
        /* shift/register */
319 2c0262af bellard
        rm = (insn) & 0xf;
320 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
321 2c0262af bellard
        gen_movl_T2_reg(s, rm);
322 1e8d4eec bellard
        shiftop = (insn >> 5) & 3;
323 2c0262af bellard
        if (shift != 0) {
324 1e8d4eec bellard
            gen_shift_T2_im[shiftop](shift);
325 1e8d4eec bellard
        } else if (shiftop != 0) {
326 1e8d4eec bellard
            gen_shift_T2_0[shiftop]();
327 2c0262af bellard
        }
328 2c0262af bellard
        if (!(insn & (1 << 23)))
329 2c0262af bellard
            gen_op_subl_T1_T2();
330 2c0262af bellard
        else
331 2c0262af bellard
            gen_op_addl_T1_T2();
332 2c0262af bellard
    }
333 2c0262af bellard
}
334 2c0262af bellard
335 2c0262af bellard
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
336 2c0262af bellard
{
337 2c0262af bellard
    int val, rm;
338 2c0262af bellard
    
339 2c0262af bellard
    if (insn & (1 << 22)) {
340 2c0262af bellard
        /* immediate */
341 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
342 2c0262af bellard
        if (!(insn & (1 << 23)))
343 2c0262af bellard
            val = -val;
344 537730b9 bellard
        if (val != 0)
345 537730b9 bellard
            gen_op_addl_T1_im(val);
346 2c0262af bellard
    } else {
347 2c0262af bellard
        /* register */
348 2c0262af bellard
        rm = (insn) & 0xf;
349 2c0262af bellard
        gen_movl_T2_reg(s, rm);
350 2c0262af bellard
        if (!(insn & (1 << 23)))
351 2c0262af bellard
            gen_op_subl_T1_T2();
352 2c0262af bellard
        else
353 2c0262af bellard
            gen_op_addl_T1_T2();
354 2c0262af bellard
    }
355 2c0262af bellard
}
356 2c0262af bellard
357 2c0262af bellard
static void disas_arm_insn(DisasContext *s)
358 2c0262af bellard
{
359 2c0262af bellard
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
360 2c0262af bellard
    
361 2c0262af bellard
    insn = ldl(s->pc);
362 2c0262af bellard
    s->pc += 4;
363 2c0262af bellard
    
364 2c0262af bellard
    cond = insn >> 28;
365 99c475ab bellard
    if (cond == 0xf){
366 99c475ab bellard
        if ((insn & 0x0d70f000) == 0x0550f000)
367 99c475ab bellard
            return; /* PLD */
368 99c475ab bellard
        else if ((insn & 0x0e000000) == 0x0a000000) {
369 99c475ab bellard
            /* branch link and change to thumb (blx <offset>) */
370 99c475ab bellard
            int32_t offset;
371 99c475ab bellard
372 99c475ab bellard
            val = (uint32_t)s->pc;
373 99c475ab bellard
            gen_op_movl_T0_im(val);
374 99c475ab bellard
            gen_movl_reg_T0(s, 14);
375 99c475ab bellard
            /* Sign-extend the 24-bit offset */
376 99c475ab bellard
            offset = (((int32_t)insn) << 8) >> 8;
377 99c475ab bellard
            /* offset * 4 + bit24 * 2 + (thumb bit) */
378 99c475ab bellard
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
379 99c475ab bellard
            /* pipeline offset */
380 99c475ab bellard
            val += 4;
381 99c475ab bellard
            gen_op_movl_T0_im(val);
382 99c475ab bellard
            gen_bx(s);
383 99c475ab bellard
            return;
384 99c475ab bellard
        }
385 2c0262af bellard
        goto illegal_op;
386 99c475ab bellard
    }
387 2c0262af bellard
    if (cond != 0xe) {
388 2c0262af bellard
        /* if not always execute, we generate a conditional jump to
389 2c0262af bellard
           next instruction */
390 2c0262af bellard
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
391 2c0262af bellard
        s->is_jmp = DISAS_JUMP_NEXT;
392 2c0262af bellard
    }
393 99c475ab bellard
    if ((insn & 0x0f900000) == 0x03000000) {
394 99c475ab bellard
        if ((insn & 0x0ff0f000) != 0x0360f000)
395 99c475ab bellard
            goto illegal_op;
396 99c475ab bellard
        /* CPSR = immediate */
397 99c475ab bellard
        val = insn & 0xff;
398 99c475ab bellard
        shift = ((insn >> 8) & 0xf) * 2;
399 99c475ab bellard
        if (shift)
400 99c475ab bellard
            val = (val >> shift) | (val << (32 - shift));
401 99c475ab bellard
        gen_op_movl_T0_im(val);
402 99c475ab bellard
        if (insn & (1 << 19))
403 99c475ab bellard
            gen_op_movl_psr_T0();
404 99c475ab bellard
    } else if ((insn & 0x0f900000) == 0x01000000
405 99c475ab bellard
               && (insn & 0x00000090) != 0x00000090) {
406 99c475ab bellard
        /* miscellaneous instructions */
407 99c475ab bellard
        op1 = (insn >> 21) & 3;
408 99c475ab bellard
        sh = (insn >> 4) & 0xf;
409 99c475ab bellard
        rm = insn & 0xf;
410 99c475ab bellard
        switch (sh) {
411 99c475ab bellard
        case 0x0: /* move program status register */
412 99c475ab bellard
            if (op1 & 2) {
413 99c475ab bellard
                /* SPSR not accessible in user mode */
414 99c475ab bellard
                goto illegal_op;
415 99c475ab bellard
            }
416 99c475ab bellard
            if (op1 & 1) {
417 99c475ab bellard
                /* CPSR = reg */
418 99c475ab bellard
                gen_movl_T0_reg(s, rm);
419 99c475ab bellard
                if (insn & (1 << 19))
420 99c475ab bellard
                    gen_op_movl_psr_T0();
421 99c475ab bellard
            } else {
422 99c475ab bellard
                /* reg = CPSR */
423 99c475ab bellard
                rd = (insn >> 12) & 0xf;
424 99c475ab bellard
                gen_op_movl_T0_psr();
425 99c475ab bellard
                gen_movl_reg_T0(s, rd);
426 99c475ab bellard
            }
427 b8a9e8f1 bellard
            break;
428 99c475ab bellard
        case 0x1:
429 99c475ab bellard
            if (op1 == 1) {
430 99c475ab bellard
                /* branch/exchange thumb (bx).  */
431 99c475ab bellard
                gen_movl_T0_reg(s, rm);
432 99c475ab bellard
                gen_bx(s);
433 99c475ab bellard
            } else if (op1 == 3) {
434 99c475ab bellard
                /* clz */
435 99c475ab bellard
                rd = (insn >> 12) & 0xf;
436 99c475ab bellard
                gen_movl_T0_reg(s, rm);
437 99c475ab bellard
                gen_op_clz_T0();
438 99c475ab bellard
                gen_movl_reg_T0(s, rd);
439 99c475ab bellard
            } else {
440 99c475ab bellard
                goto illegal_op;
441 99c475ab bellard
            }
442 99c475ab bellard
            break;
443 99c475ab bellard
        case 0x3:
444 99c475ab bellard
            if (op1 != 1)
445 99c475ab bellard
              goto illegal_op;
446 99c475ab bellard
447 99c475ab bellard
            /* branch link/exchange thumb (blx) */
448 99c475ab bellard
            val = (uint32_t)s->pc;
449 99c475ab bellard
            gen_op_movl_T0_im(val);
450 99c475ab bellard
            gen_movl_reg_T0(s, 14);
451 99c475ab bellard
            gen_movl_T0_reg(s, rm);
452 99c475ab bellard
            gen_bx(s);
453 99c475ab bellard
            break;
454 99c475ab bellard
        case 0x5: /* saturating add/subtract */
455 99c475ab bellard
            rd = (insn >> 12) & 0xf;
456 99c475ab bellard
            rn = (insn >> 16) & 0xf;
457 99c475ab bellard
            gen_movl_T0_reg(s, rn);
458 99c475ab bellard
            if (op1 & 2) {
459 99c475ab bellard
                gen_movl_T1_reg(s, rn);
460 99c475ab bellard
                if (op1 & 1) 
461 99c475ab bellard
                    gen_op_subl_T0_T1_saturate();
462 99c475ab bellard
                else
463 99c475ab bellard
                    gen_op_addl_T0_T1_saturate();
464 99c475ab bellard
            }
465 99c475ab bellard
            gen_movl_T1_reg(s, rm);
466 99c475ab bellard
            if (op1 & 1)
467 99c475ab bellard
                gen_op_subl_T0_T1_saturate();
468 99c475ab bellard
            else
469 99c475ab bellard
                gen_op_addl_T0_T1_saturate();
470 99c475ab bellard
            gen_movl_reg_T0(s, rn);
471 99c475ab bellard
            break;
472 99c475ab bellard
        case 0x8: /* signed multiply */
473 99c475ab bellard
        case 0xa:
474 99c475ab bellard
        case 0xc:
475 99c475ab bellard
        case 0xe:
476 99c475ab bellard
            rs = (insn >> 8) & 0xf;
477 99c475ab bellard
            rn = (insn >> 12) & 0xf;
478 99c475ab bellard
            rd = (insn >> 16) & 0xf;
479 99c475ab bellard
            if (op1 == 1) {
480 99c475ab bellard
                /* (32 * 16) >> 16 */
481 99c475ab bellard
                gen_movl_T0_reg(s, rm);
482 99c475ab bellard
                gen_movl_T1_reg(s, rs);
483 99c475ab bellard
                if (sh & 4)
484 99c475ab bellard
                    gen_op_sarl_T1_im(16);
485 99c475ab bellard
                else
486 99c475ab bellard
                    gen_op_sxl_T1();
487 99c475ab bellard
                gen_op_imulw_T0_T1();
488 99c475ab bellard
                if ((sh & 2) == 0) {
489 99c475ab bellard
                    gen_movl_T1_reg(s, rn);
490 99c475ab bellard
                    gen_op_addl_T0_T1_setq();
491 99c475ab bellard
                }
492 99c475ab bellard
                gen_movl_reg_T0(s, rd);
493 99c475ab bellard
            } else {
494 99c475ab bellard
                /* 16 * 16 */
495 99c475ab bellard
                gen_movl_T0_reg(s, rm);
496 99c475ab bellard
                if (sh & 2)
497 99c475ab bellard
                    gen_op_sarl_T0_im(16);
498 99c475ab bellard
                else
499 99c475ab bellard
                    gen_op_sxl_T0();
500 99c475ab bellard
                gen_movl_T1_reg(s, rs);
501 99c475ab bellard
                if (sh & 4)
502 99c475ab bellard
                    gen_op_sarl_T1_im(16);
503 99c475ab bellard
                else
504 99c475ab bellard
                    gen_op_sxl_T1();
505 99c475ab bellard
                if (op1 == 2) {
506 99c475ab bellard
                    gen_op_imull_T0_T1();
507 99c475ab bellard
                    gen_op_addq_T0_T1(rn, rd);
508 99c475ab bellard
                    gen_movl_reg_T0(s, rn);
509 99c475ab bellard
                    gen_movl_reg_T1(s, rd);
510 99c475ab bellard
                } else {
511 99c475ab bellard
                    gen_op_mul_T0_T1();
512 99c475ab bellard
                    if (op1 == 0) {
513 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
514 99c475ab bellard
                        gen_op_addl_T0_T1_setq();
515 99c475ab bellard
                    }
516 99c475ab bellard
                    gen_movl_reg_T0(s, rd);
517 99c475ab bellard
                }
518 99c475ab bellard
            }
519 99c475ab bellard
            break;
520 99c475ab bellard
        default:
521 99c475ab bellard
            goto illegal_op;
522 99c475ab bellard
        }
523 99c475ab bellard
    } else if (((insn & 0x0e000000) == 0 &&
524 99c475ab bellard
                (insn & 0x00000090) != 0x90) ||
525 99c475ab bellard
               ((insn & 0x0e000000) == (1 << 25))) {
526 2c0262af bellard
        int set_cc, logic_cc, shiftop;
527 2c0262af bellard
        
528 2c0262af bellard
        op1 = (insn >> 21) & 0xf;
529 2c0262af bellard
        set_cc = (insn >> 20) & 1;
530 2c0262af bellard
        logic_cc = table_logic_cc[op1] & set_cc;
531 2c0262af bellard
532 2c0262af bellard
        /* data processing instruction */
533 2c0262af bellard
        if (insn & (1 << 25)) {
534 2c0262af bellard
            /* immediate operand */
535 2c0262af bellard
            val = insn & 0xff;
536 2c0262af bellard
            shift = ((insn >> 8) & 0xf) * 2;
537 2c0262af bellard
            if (shift)
538 2c0262af bellard
                val = (val >> shift) | (val << (32 - shift));
539 2c0262af bellard
            gen_op_movl_T1_im(val);
540 7ff4d218 bellard
            if (logic_cc && shift)
541 7ff4d218 bellard
                gen_op_mov_CF_T1();
542 2c0262af bellard
        } else {
543 2c0262af bellard
            /* register */
544 2c0262af bellard
            rm = (insn) & 0xf;
545 2c0262af bellard
            gen_movl_T1_reg(s, rm);
546 2c0262af bellard
            shiftop = (insn >> 5) & 3;
547 2c0262af bellard
            if (!(insn & (1 << 4))) {
548 2c0262af bellard
                shift = (insn >> 7) & 0x1f;
549 2c0262af bellard
                if (shift != 0) {
550 2c0262af bellard
                    if (logic_cc) {
551 2c0262af bellard
                        gen_shift_T1_im_cc[shiftop](shift);
552 2c0262af bellard
                    } else {
553 2c0262af bellard
                        gen_shift_T1_im[shiftop](shift);
554 2c0262af bellard
                    }
555 1e8d4eec bellard
                } else if (shiftop != 0) {
556 1e8d4eec bellard
                    if (logic_cc) {
557 1e8d4eec bellard
                        gen_shift_T1_0_cc[shiftop]();
558 1e8d4eec bellard
                    } else {
559 1e8d4eec bellard
                        gen_shift_T1_0[shiftop]();
560 1e8d4eec bellard
                    }
561 2c0262af bellard
                }
562 2c0262af bellard
            } else {
563 2c0262af bellard
                rs = (insn >> 8) & 0xf;
564 2c0262af bellard
                gen_movl_T0_reg(s, rs);
565 2c0262af bellard
                if (logic_cc) {
566 2c0262af bellard
                    gen_shift_T1_T0_cc[shiftop]();
567 2c0262af bellard
                } else {
568 2c0262af bellard
                    gen_shift_T1_T0[shiftop]();
569 2c0262af bellard
                }
570 2c0262af bellard
            }
571 2c0262af bellard
        }
572 2c0262af bellard
        if (op1 != 0x0f && op1 != 0x0d) {
573 2c0262af bellard
            rn = (insn >> 16) & 0xf;
574 2c0262af bellard
            gen_movl_T0_reg(s, rn);
575 2c0262af bellard
        }
576 2c0262af bellard
        rd = (insn >> 12) & 0xf;
577 2c0262af bellard
        switch(op1) {
578 2c0262af bellard
        case 0x00:
579 2c0262af bellard
            gen_op_andl_T0_T1();
580 2c0262af bellard
            gen_movl_reg_T0(s, rd);
581 2c0262af bellard
            if (logic_cc)
582 2c0262af bellard
                gen_op_logic_T0_cc();
583 2c0262af bellard
            break;
584 2c0262af bellard
        case 0x01:
585 2c0262af bellard
            gen_op_xorl_T0_T1();
586 2c0262af bellard
            gen_movl_reg_T0(s, rd);
587 2c0262af bellard
            if (logic_cc)
588 2c0262af bellard
                gen_op_logic_T0_cc();
589 2c0262af bellard
            break;
590 2c0262af bellard
        case 0x02:
591 2c0262af bellard
            if (set_cc)
592 2c0262af bellard
                gen_op_subl_T0_T1_cc();
593 2c0262af bellard
            else
594 2c0262af bellard
                gen_op_subl_T0_T1();
595 2c0262af bellard
            gen_movl_reg_T0(s, rd);
596 2c0262af bellard
            break;
597 2c0262af bellard
        case 0x03:
598 2c0262af bellard
            if (set_cc)
599 2c0262af bellard
                gen_op_rsbl_T0_T1_cc();
600 2c0262af bellard
            else
601 2c0262af bellard
                gen_op_rsbl_T0_T1();
602 2c0262af bellard
            gen_movl_reg_T0(s, rd);
603 2c0262af bellard
            break;
604 2c0262af bellard
        case 0x04:
605 2c0262af bellard
            if (set_cc)
606 2c0262af bellard
                gen_op_addl_T0_T1_cc();
607 2c0262af bellard
            else
608 2c0262af bellard
                gen_op_addl_T0_T1();
609 2c0262af bellard
            gen_movl_reg_T0(s, rd);
610 2c0262af bellard
            break;
611 2c0262af bellard
        case 0x05:
612 2c0262af bellard
            if (set_cc)
613 2c0262af bellard
                gen_op_adcl_T0_T1_cc();
614 2c0262af bellard
            else
615 2c0262af bellard
                gen_op_adcl_T0_T1();
616 2c0262af bellard
            gen_movl_reg_T0(s, rd);
617 2c0262af bellard
            break;
618 2c0262af bellard
        case 0x06:
619 2c0262af bellard
            if (set_cc)
620 2c0262af bellard
                gen_op_sbcl_T0_T1_cc();
621 2c0262af bellard
            else
622 2c0262af bellard
                gen_op_sbcl_T0_T1();
623 2c0262af bellard
            gen_movl_reg_T0(s, rd);
624 2c0262af bellard
            break;
625 2c0262af bellard
        case 0x07:
626 2c0262af bellard
            if (set_cc)
627 2c0262af bellard
                gen_op_rscl_T0_T1_cc();
628 2c0262af bellard
            else
629 2c0262af bellard
                gen_op_rscl_T0_T1();
630 2c0262af bellard
            gen_movl_reg_T0(s, rd);
631 2c0262af bellard
            break;
632 2c0262af bellard
        case 0x08:
633 2c0262af bellard
            if (set_cc) {
634 2c0262af bellard
                gen_op_andl_T0_T1();
635 2c0262af bellard
                gen_op_logic_T0_cc();
636 2c0262af bellard
            }
637 2c0262af bellard
            break;
638 2c0262af bellard
        case 0x09:
639 2c0262af bellard
            if (set_cc) {
640 2c0262af bellard
                gen_op_xorl_T0_T1();
641 2c0262af bellard
                gen_op_logic_T0_cc();
642 2c0262af bellard
            }
643 2c0262af bellard
            break;
644 2c0262af bellard
        case 0x0a:
645 2c0262af bellard
            if (set_cc) {
646 2c0262af bellard
                gen_op_subl_T0_T1_cc();
647 2c0262af bellard
            }
648 2c0262af bellard
            break;
649 2c0262af bellard
        case 0x0b:
650 2c0262af bellard
            if (set_cc) {
651 2c0262af bellard
                gen_op_addl_T0_T1_cc();
652 2c0262af bellard
            }
653 2c0262af bellard
            break;
654 2c0262af bellard
        case 0x0c:
655 2c0262af bellard
            gen_op_orl_T0_T1();
656 2c0262af bellard
            gen_movl_reg_T0(s, rd);
657 2c0262af bellard
            if (logic_cc)
658 2c0262af bellard
                gen_op_logic_T0_cc();
659 2c0262af bellard
            break;
660 2c0262af bellard
        case 0x0d:
661 2c0262af bellard
            gen_movl_reg_T1(s, rd);
662 2c0262af bellard
            if (logic_cc)
663 2c0262af bellard
                gen_op_logic_T1_cc();
664 2c0262af bellard
            break;
665 2c0262af bellard
        case 0x0e:
666 2c0262af bellard
            gen_op_bicl_T0_T1();
667 2c0262af bellard
            gen_movl_reg_T0(s, rd);
668 2c0262af bellard
            if (logic_cc)
669 2c0262af bellard
                gen_op_logic_T0_cc();
670 2c0262af bellard
            break;
671 2c0262af bellard
        default:
672 2c0262af bellard
        case 0x0f:
673 2c0262af bellard
            gen_op_notl_T1();
674 2c0262af bellard
            gen_movl_reg_T1(s, rd);
675 2c0262af bellard
            if (logic_cc)
676 2c0262af bellard
                gen_op_logic_T1_cc();
677 2c0262af bellard
            break;
678 2c0262af bellard
        }
679 2c0262af bellard
    } else {
680 2c0262af bellard
        /* other instructions */
681 2c0262af bellard
        op1 = (insn >> 24) & 0xf;
682 2c0262af bellard
        switch(op1) {
683 2c0262af bellard
        case 0x0:
684 2c0262af bellard
        case 0x1:
685 99c475ab bellard
            /* multiplies, extra load/stores */
686 2c0262af bellard
            sh = (insn >> 5) & 3;
687 2c0262af bellard
            if (sh == 0) {
688 2c0262af bellard
                if (op1 == 0x0) {
689 2c0262af bellard
                    rd = (insn >> 16) & 0xf;
690 2c0262af bellard
                    rn = (insn >> 12) & 0xf;
691 2c0262af bellard
                    rs = (insn >> 8) & 0xf;
692 2c0262af bellard
                    rm = (insn) & 0xf;
693 99c475ab bellard
                    if (((insn >> 22) & 3) == 0) {
694 2c0262af bellard
                        /* 32 bit mul */
695 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
696 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
697 2c0262af bellard
                        gen_op_mul_T0_T1();
698 2c0262af bellard
                        if (insn & (1 << 21)) {
699 2c0262af bellard
                            gen_movl_T1_reg(s, rn);
700 2c0262af bellard
                            gen_op_addl_T0_T1();
701 2c0262af bellard
                        }
702 2c0262af bellard
                        if (insn & (1 << 20)) 
703 2c0262af bellard
                            gen_op_logic_T0_cc();
704 2c0262af bellard
                        gen_movl_reg_T0(s, rd);
705 2c0262af bellard
                    } else {
706 2c0262af bellard
                        /* 64 bit mul */
707 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
708 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
709 2c0262af bellard
                        if (insn & (1 << 22)) 
710 2c0262af bellard
                            gen_op_imull_T0_T1();
711 2e134c9c bellard
                        else
712 2e134c9c bellard
                            gen_op_mull_T0_T1();
713 99c475ab bellard
                        if (insn & (1 << 21)) /* mult accumulate */
714 2c0262af bellard
                            gen_op_addq_T0_T1(rn, rd);
715 99c475ab bellard
                        if (!(insn & (1 << 23))) { /* double accumulate */
716 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rn);
717 99c475ab bellard
                            gen_op_addq_lo_T0_T1(rd);
718 99c475ab bellard
                        }
719 2c0262af bellard
                        if (insn & (1 << 20)) 
720 2c0262af bellard
                            gen_op_logicq_cc();
721 2c0262af bellard
                        gen_movl_reg_T0(s, rn);
722 2c0262af bellard
                        gen_movl_reg_T1(s, rd);
723 2c0262af bellard
                    }
724 2c0262af bellard
                } else {
725 2c0262af bellard
                    rn = (insn >> 16) & 0xf;
726 2c0262af bellard
                    rd = (insn >> 12) & 0xf;
727 99c475ab bellard
                    if (insn & (1 << 23)) {
728 99c475ab bellard
                        /* load/store exclusive */
729 99c475ab bellard
                        goto illegal_op;
730 2c0262af bellard
                    } else {
731 99c475ab bellard
                        /* SWP instruction */
732 99c475ab bellard
                        rm = (insn) & 0xf;
733 99c475ab bellard
                        
734 99c475ab bellard
                        gen_movl_T0_reg(s, rm);
735 99c475ab bellard
                        gen_movl_T1_reg(s, rn);
736 99c475ab bellard
                        if (insn & (1 << 22)) {
737 99c475ab bellard
                            gen_op_swpb_T0_T1();
738 99c475ab bellard
                        } else {
739 99c475ab bellard
                            gen_op_swpl_T0_T1();
740 99c475ab bellard
                        }
741 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
742 2c0262af bellard
                    }
743 2c0262af bellard
                }
744 2c0262af bellard
            } else {
745 99c475ab bellard
                /* Misc load/store */
746 2c0262af bellard
                rn = (insn >> 16) & 0xf;
747 2c0262af bellard
                rd = (insn >> 12) & 0xf;
748 2c0262af bellard
                gen_movl_T1_reg(s, rn);
749 beddab75 bellard
                if (insn & (1 << 24))
750 beddab75 bellard
                    gen_add_datah_offset(s, insn);
751 2c0262af bellard
                if (insn & (1 << 20)) {
752 2c0262af bellard
                    /* load */
753 2c0262af bellard
                    switch(sh) {
754 2c0262af bellard
                    case 1:
755 2c0262af bellard
                        gen_op_lduw_T0_T1();
756 2c0262af bellard
                        break;
757 2c0262af bellard
                    case 2:
758 2c0262af bellard
                        gen_op_ldsb_T0_T1();
759 2c0262af bellard
                        break;
760 2c0262af bellard
                    default:
761 2c0262af bellard
                    case 3:
762 2c0262af bellard
                        gen_op_ldsw_T0_T1();
763 2c0262af bellard
                        break;
764 2c0262af bellard
                    }
765 e748ba4f bellard
                    gen_movl_reg_T0(s, rd);
766 99c475ab bellard
                } else if (sh & 2) {
767 99c475ab bellard
                    /* doubleword */
768 99c475ab bellard
                    if (sh & 1) {
769 99c475ab bellard
                        /* store */
770 99c475ab bellard
                        gen_movl_T0_reg(s, rd);
771 99c475ab bellard
                        gen_op_stl_T0_T1();
772 99c475ab bellard
                        gen_op_addl_T1_im(4);
773 99c475ab bellard
                        gen_movl_T0_reg(s, rd + 1);
774 99c475ab bellard
                        gen_op_stl_T0_T1();
775 99c475ab bellard
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
776 99c475ab bellard
                            gen_op_addl_T1_im(-4);
777 99c475ab bellard
                    } else {
778 99c475ab bellard
                        /* load */
779 99c475ab bellard
                        gen_op_ldl_T0_T1();
780 99c475ab bellard
                        gen_movl_reg_T0(s, rd);
781 99c475ab bellard
                        gen_op_addl_T1_im(4);
782 99c475ab bellard
                        gen_op_ldl_T0_T1();
783 99c475ab bellard
                        gen_movl_reg_T0(s, rd + 1);
784 99c475ab bellard
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
785 99c475ab bellard
                            gen_op_addl_T1_im(-4);
786 99c475ab bellard
                    }
787 2c0262af bellard
                } else {
788 2c0262af bellard
                    /* store */
789 e748ba4f bellard
                    gen_movl_T0_reg(s, rd);
790 2c0262af bellard
                    gen_op_stw_T0_T1();
791 2c0262af bellard
                }
792 2c0262af bellard
                if (!(insn & (1 << 24))) {
793 2c0262af bellard
                    gen_add_datah_offset(s, insn);
794 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
795 2c0262af bellard
                } else if (insn & (1 << 21)) {
796 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
797 2c0262af bellard
                }
798 2c0262af bellard
            }
799 2c0262af bellard
            break;
800 2c0262af bellard
        case 0x4:
801 2c0262af bellard
        case 0x5:
802 2c0262af bellard
        case 0x6:
803 2c0262af bellard
        case 0x7:
804 2c0262af bellard
            /* load/store byte/word */
805 2c0262af bellard
            rn = (insn >> 16) & 0xf;
806 2c0262af bellard
            rd = (insn >> 12) & 0xf;
807 2c0262af bellard
            gen_movl_T1_reg(s, rn);
808 2c0262af bellard
            if (insn & (1 << 24))
809 2c0262af bellard
                gen_add_data_offset(s, insn);
810 2c0262af bellard
            if (insn & (1 << 20)) {
811 2c0262af bellard
                /* load */
812 2c0262af bellard
                if (insn & (1 << 22))
813 2c0262af bellard
                    gen_op_ldub_T0_T1();
814 2c0262af bellard
                else
815 2c0262af bellard
                    gen_op_ldl_T0_T1();
816 99c475ab bellard
                if (rd == 15)
817 99c475ab bellard
                    gen_bx(s);
818 99c475ab bellard
                else
819 99c475ab bellard
                    gen_movl_reg_T0(s, rd);
820 2c0262af bellard
            } else {
821 2c0262af bellard
                /* store */
822 2c0262af bellard
                gen_movl_T0_reg(s, rd);
823 2c0262af bellard
                if (insn & (1 << 22))
824 2c0262af bellard
                    gen_op_stb_T0_T1();
825 2c0262af bellard
                else
826 2c0262af bellard
                    gen_op_stl_T0_T1();
827 2c0262af bellard
            }
828 2c0262af bellard
            if (!(insn & (1 << 24))) {
829 2c0262af bellard
                gen_add_data_offset(s, insn);
830 2c0262af bellard
                gen_movl_reg_T1(s, rn);
831 2c0262af bellard
            } else if (insn & (1 << 21))
832 2c0262af bellard
                gen_movl_reg_T1(s, rn); {
833 2c0262af bellard
            }
834 2c0262af bellard
            break;
835 2c0262af bellard
        case 0x08:
836 2c0262af bellard
        case 0x09:
837 2c0262af bellard
            {
838 2c0262af bellard
                int j, n;
839 2c0262af bellard
                /* load/store multiple words */
840 2c0262af bellard
                /* XXX: store correct base if write back */
841 2c0262af bellard
                if (insn & (1 << 22))
842 2c0262af bellard
                    goto illegal_op; /* only usable in supervisor mode */
843 2c0262af bellard
                rn = (insn >> 16) & 0xf;
844 2c0262af bellard
                gen_movl_T1_reg(s, rn);
845 2c0262af bellard
                
846 2c0262af bellard
                /* compute total size */
847 2c0262af bellard
                n = 0;
848 2c0262af bellard
                for(i=0;i<16;i++) {
849 2c0262af bellard
                    if (insn & (1 << i))
850 2c0262af bellard
                        n++;
851 2c0262af bellard
                }
852 2c0262af bellard
                /* XXX: test invalid n == 0 case ? */
853 2c0262af bellard
                if (insn & (1 << 23)) {
854 2c0262af bellard
                    if (insn & (1 << 24)) {
855 2c0262af bellard
                        /* pre increment */
856 2c0262af bellard
                        gen_op_addl_T1_im(4);
857 2c0262af bellard
                    } else {
858 2c0262af bellard
                        /* post increment */
859 2c0262af bellard
                    }
860 2c0262af bellard
                } else {
861 2c0262af bellard
                    if (insn & (1 << 24)) {
862 2c0262af bellard
                        /* pre decrement */
863 2c0262af bellard
                        gen_op_addl_T1_im(-(n * 4));
864 2c0262af bellard
                    } else {
865 2c0262af bellard
                        /* post decrement */
866 2c0262af bellard
                        if (n != 1)
867 2c0262af bellard
                            gen_op_addl_T1_im(-((n - 1) * 4));
868 2c0262af bellard
                    }
869 2c0262af bellard
                }
870 2c0262af bellard
                j = 0;
871 2c0262af bellard
                for(i=0;i<16;i++) {
872 2c0262af bellard
                    if (insn & (1 << i)) {
873 2c0262af bellard
                        if (insn & (1 << 20)) {
874 2c0262af bellard
                            /* load */
875 2c0262af bellard
                            gen_op_ldl_T0_T1();
876 99c475ab bellard
                            if (i == 15)
877 99c475ab bellard
                                gen_bx(s);
878 99c475ab bellard
                            else
879 99c475ab bellard
                                gen_movl_reg_T0(s, i);
880 2c0262af bellard
                        } else {
881 2c0262af bellard
                            /* store */
882 2c0262af bellard
                            if (i == 15) {
883 2c0262af bellard
                                /* special case: r15 = PC + 12 */
884 2c0262af bellard
                                val = (long)s->pc + 8;
885 2c0262af bellard
                                gen_op_movl_TN_im[0](val);
886 2c0262af bellard
                            } else {
887 2c0262af bellard
                                gen_movl_T0_reg(s, i);
888 2c0262af bellard
                            }
889 2c0262af bellard
                            gen_op_stl_T0_T1();
890 2c0262af bellard
                        }
891 2c0262af bellard
                        j++;
892 2c0262af bellard
                        /* no need to add after the last transfer */
893 2c0262af bellard
                        if (j != n)
894 2c0262af bellard
                            gen_op_addl_T1_im(4);
895 2c0262af bellard
                    }
896 2c0262af bellard
                }
897 2c0262af bellard
                if (insn & (1 << 21)) {
898 2c0262af bellard
                    /* write back */
899 2c0262af bellard
                    if (insn & (1 << 23)) {
900 2c0262af bellard
                        if (insn & (1 << 24)) {
901 2c0262af bellard
                            /* pre increment */
902 2c0262af bellard
                        } else {
903 2c0262af bellard
                            /* post increment */
904 2c0262af bellard
                            gen_op_addl_T1_im(4);
905 2c0262af bellard
                        }
906 2c0262af bellard
                    } else {
907 2c0262af bellard
                        if (insn & (1 << 24)) {
908 2c0262af bellard
                            /* pre decrement */
909 2c0262af bellard
                            if (n != 1)
910 2c0262af bellard
                                gen_op_addl_T1_im(-((n - 1) * 4));
911 2c0262af bellard
                        } else {
912 2c0262af bellard
                            /* post decrement */
913 2c0262af bellard
                            gen_op_addl_T1_im(-(n * 4));
914 2c0262af bellard
                        }
915 2c0262af bellard
                    }
916 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
917 2c0262af bellard
                }
918 2c0262af bellard
            }
919 2c0262af bellard
            break;
920 2c0262af bellard
        case 0xa:
921 2c0262af bellard
        case 0xb:
922 2c0262af bellard
            {
923 99c475ab bellard
                int32_t offset;
924 2c0262af bellard
                
925 2c0262af bellard
                /* branch (and link) */
926 99c475ab bellard
                val = (int32_t)s->pc;
927 2c0262af bellard
                if (insn & (1 << 24)) {
928 2c0262af bellard
                    gen_op_movl_T0_im(val);
929 2c0262af bellard
                    gen_op_movl_reg_TN[0][14]();
930 2c0262af bellard
                }
931 99c475ab bellard
                offset = (((int32_t)insn << 8) >> 8);
932 2c0262af bellard
                val += (offset << 2) + 4;
933 2c0262af bellard
                gen_op_jmp((long)s->tb, val);
934 2c0262af bellard
                s->is_jmp = DISAS_TB_JUMP;
935 2c0262af bellard
            }
936 2c0262af bellard
            break;
937 2c0262af bellard
        case 0xf:
938 2c0262af bellard
            /* swi */
939 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc);
940 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
941 2c0262af bellard
            gen_op_swi();
942 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
943 2c0262af bellard
            break;
944 2c0262af bellard
        default:
945 2c0262af bellard
        illegal_op:
946 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc - 4);
947 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
948 2c0262af bellard
            gen_op_undef_insn();
949 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
950 2c0262af bellard
            break;
951 2c0262af bellard
        }
952 2c0262af bellard
    }
953 2c0262af bellard
}
954 2c0262af bellard
955 99c475ab bellard
static void disas_thumb_insn(DisasContext *s)
956 99c475ab bellard
{
957 99c475ab bellard
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
958 99c475ab bellard
    int32_t offset;
959 99c475ab bellard
    int i;
960 99c475ab bellard
961 99c475ab bellard
    insn = lduw(s->pc);
962 99c475ab bellard
    s->pc += 2;
963 99c475ab bellard
    
964 99c475ab bellard
    switch (insn >> 12) {
965 99c475ab bellard
    case 0: case 1:
966 99c475ab bellard
        rd = insn & 7;
967 99c475ab bellard
        op = (insn >> 11) & 3;
968 99c475ab bellard
        if (op == 3) {
969 99c475ab bellard
            /* add/subtract */
970 99c475ab bellard
            rn = (insn >> 3) & 7;
971 99c475ab bellard
            gen_movl_T0_reg(s, rn);
972 99c475ab bellard
            if (insn & (1 << 10)) {
973 99c475ab bellard
                /* immediate */
974 99c475ab bellard
                gen_op_movl_T1_im((insn >> 6) & 7);
975 99c475ab bellard
            } else {
976 99c475ab bellard
                /* reg */
977 99c475ab bellard
                rm = (insn >> 6) & 7;
978 99c475ab bellard
                gen_movl_T1_reg(s, rm);
979 99c475ab bellard
            }
980 99c475ab bellard
            if (insn & (1 << 9))
981 99c475ab bellard
                gen_op_addl_T0_T1_cc();
982 99c475ab bellard
            else
983 99c475ab bellard
                gen_op_addl_T0_T1_cc();
984 99c475ab bellard
            gen_movl_reg_T0(s, rd);
985 99c475ab bellard
        } else {
986 99c475ab bellard
            /* shift immediate */
987 99c475ab bellard
            rm = (insn >> 3) & 7;
988 99c475ab bellard
            shift = (insn >> 6) & 0x1f;
989 99c475ab bellard
            gen_movl_T0_reg(s, rm);
990 99c475ab bellard
            gen_shift_T0_im_thumb[op](shift);
991 99c475ab bellard
            gen_movl_reg_T0(s, rd);
992 99c475ab bellard
        }
993 99c475ab bellard
        break;
994 99c475ab bellard
    case 2: case 3:
995 99c475ab bellard
        /* arithmetic large immediate */
996 99c475ab bellard
        op = (insn >> 11) & 3;
997 99c475ab bellard
        rd = (insn >> 8) & 0x7;
998 99c475ab bellard
        if (op == 0) {
999 99c475ab bellard
            gen_op_movl_T0_im(insn & 0xff);
1000 99c475ab bellard
        } else {
1001 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1002 99c475ab bellard
            gen_op_movl_T1_im(insn & 0xff);
1003 99c475ab bellard
        }
1004 99c475ab bellard
        switch (op) {
1005 99c475ab bellard
        case 0: /* mov */
1006 99c475ab bellard
            gen_op_logic_T0_cc();
1007 99c475ab bellard
            break;
1008 99c475ab bellard
        case 1: /* cmp */
1009 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1010 99c475ab bellard
            break;
1011 99c475ab bellard
        case 2: /* add */
1012 99c475ab bellard
            gen_op_addl_T0_T1_cc();
1013 99c475ab bellard
            break;
1014 99c475ab bellard
        case 3: /* sub */
1015 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1016 99c475ab bellard
            break;
1017 99c475ab bellard
        }
1018 99c475ab bellard
        if (op != 1)
1019 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1020 99c475ab bellard
        break;
1021 99c475ab bellard
    case 4:
1022 99c475ab bellard
        if (insn & (1 << 11)) {
1023 99c475ab bellard
            rd = (insn >> 8) & 7;
1024 99c475ab bellard
            /* load pc-relative */
1025 99c475ab bellard
            val = (insn & 0xff) * 4;
1026 99c475ab bellard
            gen_op_movl_T1_im(val);
1027 99c475ab bellard
            gen_movl_T2_reg(s, 15);
1028 99c475ab bellard
            gen_op_addl_T1_T2();
1029 99c475ab bellard
            gen_op_ldl_T0_T1();
1030 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1031 99c475ab bellard
            break;
1032 99c475ab bellard
        }
1033 99c475ab bellard
        if (insn & (1 << 10)) {
1034 99c475ab bellard
            /* data processing extended or blx */
1035 99c475ab bellard
            rd = (insn & 7) | ((insn >> 4) & 8);
1036 99c475ab bellard
            rm = (insn >> 3) & 0xf;
1037 99c475ab bellard
            op = (insn >> 8) & 3;
1038 99c475ab bellard
            switch (op) {
1039 99c475ab bellard
            case 0: /* add */
1040 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1041 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1042 99c475ab bellard
                gen_op_addl_T0_T1();
1043 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1044 99c475ab bellard
                break;
1045 99c475ab bellard
            case 1: /* cmp */
1046 99c475ab bellard
                gen_movl_T0_reg(s, rd);
1047 99c475ab bellard
                gen_movl_T1_reg(s, rm);
1048 99c475ab bellard
                gen_op_subl_T0_T1_cc();
1049 99c475ab bellard
                break;
1050 99c475ab bellard
            case 2: /* mov/cpy */
1051 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1052 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1053 99c475ab bellard
                break;
1054 99c475ab bellard
            case 3:/* branch [and link] exchange thumb register */
1055 99c475ab bellard
                if (insn & (1 << 7)) {
1056 99c475ab bellard
                    val = (uint32_t)s->pc | 1;
1057 99c475ab bellard
                    gen_op_movl_T1_im(val);
1058 99c475ab bellard
                    gen_movl_reg_T1(s, 14);
1059 99c475ab bellard
                }
1060 99c475ab bellard
                gen_movl_T0_reg(s, rm);
1061 99c475ab bellard
                gen_bx(s);
1062 99c475ab bellard
                break;
1063 99c475ab bellard
            }
1064 99c475ab bellard
            break;
1065 99c475ab bellard
        }
1066 99c475ab bellard
1067 99c475ab bellard
        /* data processing register */
1068 99c475ab bellard
        rd = insn & 7;
1069 99c475ab bellard
        rm = (insn >> 3) & 7;
1070 99c475ab bellard
        op = (insn >> 6) & 0xf;
1071 99c475ab bellard
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1072 99c475ab bellard
            /* the shift/rotate ops want the operands backwards */
1073 99c475ab bellard
            val = rm;
1074 99c475ab bellard
            rm = rd;
1075 99c475ab bellard
            rd = val;
1076 99c475ab bellard
            val = 1;
1077 99c475ab bellard
        } else {
1078 99c475ab bellard
            val = 0;
1079 99c475ab bellard
        }
1080 99c475ab bellard
1081 99c475ab bellard
        if (op == 9) /* neg */
1082 99c475ab bellard
            gen_op_movl_T0_im(0);
1083 99c475ab bellard
        else if (op != 0xf) /* mvn doesn't read its first operand */
1084 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1085 99c475ab bellard
1086 99c475ab bellard
        gen_movl_T1_reg(s, rm);
1087 99c475ab bellard
        switch (insn >> 6) {
1088 99c475ab bellard
        case 0x0: /* and */
1089 99c475ab bellard
            gen_op_andl_T0_T1();
1090 99c475ab bellard
            gen_op_logic_T0_cc();
1091 99c475ab bellard
            break;
1092 99c475ab bellard
        case 0x1: /* eor */
1093 99c475ab bellard
            gen_op_xorl_T0_T1();
1094 99c475ab bellard
            gen_op_logic_T0_cc();
1095 99c475ab bellard
            break;
1096 99c475ab bellard
        case 0x2: /* lsl */
1097 99c475ab bellard
            gen_op_shll_T1_T0_cc();
1098 99c475ab bellard
            break;
1099 99c475ab bellard
        case 0x3: /* lsr */
1100 99c475ab bellard
            gen_op_shrl_T1_T0_cc();
1101 99c475ab bellard
            break;
1102 99c475ab bellard
        case 0x4: /* asr */
1103 99c475ab bellard
            gen_op_sarl_T1_T0_cc();
1104 99c475ab bellard
            break;
1105 99c475ab bellard
        case 0x5: /* adc */
1106 99c475ab bellard
            gen_op_adcl_T0_T1_cc();
1107 99c475ab bellard
            break;
1108 99c475ab bellard
        case 0x6: /* sbc */
1109 99c475ab bellard
            gen_op_sbcl_T0_T1_cc();
1110 99c475ab bellard
            break;
1111 99c475ab bellard
        case 0x7: /* ror */
1112 99c475ab bellard
            gen_op_rorl_T1_T0_cc();
1113 99c475ab bellard
            break;
1114 99c475ab bellard
        case 0x8: /* tst */
1115 99c475ab bellard
            gen_op_andl_T0_T1();
1116 99c475ab bellard
            gen_op_logic_T0_cc();
1117 99c475ab bellard
            rd = 16;
1118 99c475ab bellard
        case 0x9: /* neg */
1119 99c475ab bellard
            gen_op_rsbl_T0_T1_cc();
1120 99c475ab bellard
            break;
1121 99c475ab bellard
        case 0xa: /* cmp */
1122 99c475ab bellard
            gen_op_subl_T0_T1_cc();
1123 99c475ab bellard
            rd = 16;
1124 99c475ab bellard
            break;
1125 99c475ab bellard
        case 0xb: /* cmn */
1126 99c475ab bellard
            gen_op_addl_T0_T1_cc();
1127 99c475ab bellard
            rd = 16;
1128 99c475ab bellard
            break;
1129 99c475ab bellard
        case 0xc: /* orr */
1130 99c475ab bellard
            gen_op_orl_T0_T1();
1131 99c475ab bellard
            gen_op_logic_T0_cc();
1132 99c475ab bellard
            break;
1133 99c475ab bellard
        case 0xd: /* mul */
1134 99c475ab bellard
            gen_op_mull_T0_T1();
1135 99c475ab bellard
            gen_op_logic_T0_cc();
1136 99c475ab bellard
            break;
1137 99c475ab bellard
        case 0xe: /* bic */
1138 99c475ab bellard
            gen_op_bicl_T0_T1();
1139 99c475ab bellard
            gen_op_logic_T0_cc();
1140 99c475ab bellard
            break;
1141 99c475ab bellard
        case 0xf: /* mvn */
1142 99c475ab bellard
            gen_op_notl_T1();
1143 99c475ab bellard
            gen_op_logic_T1_cc();
1144 99c475ab bellard
            val = 1;
1145 99c475ab bellard
            break;
1146 99c475ab bellard
        }
1147 99c475ab bellard
        if (rd != 16) {
1148 99c475ab bellard
            if (val)
1149 99c475ab bellard
                gen_movl_reg_T1(s, rd);
1150 99c475ab bellard
            else
1151 99c475ab bellard
                gen_movl_reg_T0(s, rd);
1152 99c475ab bellard
        }
1153 99c475ab bellard
        break;
1154 99c475ab bellard
1155 99c475ab bellard
    case 5:
1156 99c475ab bellard
        /* load/store register offset.  */
1157 99c475ab bellard
        rd = insn & 7;
1158 99c475ab bellard
        rn = (insn >> 3) & 7;
1159 99c475ab bellard
        rm = (insn >> 6) & 7;
1160 99c475ab bellard
        op = (insn >> 9) & 7;
1161 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1162 99c475ab bellard
        gen_movl_T2_reg(s, rm);
1163 99c475ab bellard
        gen_op_addl_T1_T2();
1164 99c475ab bellard
1165 99c475ab bellard
        if (op < 3) /* store */
1166 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1167 99c475ab bellard
1168 99c475ab bellard
        switch (op) {
1169 99c475ab bellard
        case 0: /* str */
1170 99c475ab bellard
            gen_op_stl_T0_T1();
1171 99c475ab bellard
            break;
1172 99c475ab bellard
        case 1: /* strh */
1173 99c475ab bellard
            gen_op_stw_T0_T1();
1174 99c475ab bellard
            break;
1175 99c475ab bellard
        case 2: /* strb */
1176 99c475ab bellard
            gen_op_stb_T0_T1();
1177 99c475ab bellard
            break;
1178 99c475ab bellard
        case 3: /* ldrsb */
1179 99c475ab bellard
            gen_op_ldsb_T0_T1();
1180 99c475ab bellard
            break;
1181 99c475ab bellard
        case 4: /* ldr */
1182 99c475ab bellard
            gen_op_ldl_T0_T1();
1183 99c475ab bellard
            break;
1184 99c475ab bellard
        case 5: /* ldrh */
1185 99c475ab bellard
            gen_op_ldsw_T0_T1();
1186 99c475ab bellard
            break;
1187 99c475ab bellard
        case 6: /* ldrb */
1188 99c475ab bellard
            gen_op_ldub_T0_T1();
1189 99c475ab bellard
            break;
1190 99c475ab bellard
        case 7: /* ldrsh */
1191 99c475ab bellard
            gen_op_ldsw_T0_T1();
1192 99c475ab bellard
            break;
1193 99c475ab bellard
        }
1194 99c475ab bellard
        if (op >= 3) /* load */
1195 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1196 99c475ab bellard
        break;
1197 99c475ab bellard
1198 99c475ab bellard
    case 6:
1199 99c475ab bellard
        /* load/store word immediate offset */
1200 99c475ab bellard
        rd = insn & 7;
1201 99c475ab bellard
        rn = (insn >> 3) & 7;
1202 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1203 99c475ab bellard
        val = (insn >> 4) & 0x7c;
1204 99c475ab bellard
        gen_op_movl_T2_im(val);
1205 99c475ab bellard
        gen_op_addl_T1_T2();
1206 99c475ab bellard
1207 99c475ab bellard
        if (insn & (1 << 11)) {
1208 99c475ab bellard
            /* load */
1209 99c475ab bellard
            gen_op_ldl_T0_T1();
1210 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1211 99c475ab bellard
        } else {
1212 99c475ab bellard
            /* store */
1213 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1214 99c475ab bellard
            gen_op_stl_T0_T1();
1215 99c475ab bellard
        }
1216 99c475ab bellard
        break;
1217 99c475ab bellard
1218 99c475ab bellard
    case 7:
1219 99c475ab bellard
        /* load/store byte immediate offset */
1220 99c475ab bellard
        rd = insn & 7;
1221 99c475ab bellard
        rn = (insn >> 3) & 7;
1222 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1223 99c475ab bellard
        val = (insn >> 6) & 0x1f;
1224 99c475ab bellard
        gen_op_movl_T2_im(val);
1225 99c475ab bellard
        gen_op_addl_T1_T2();
1226 99c475ab bellard
1227 99c475ab bellard
        if (insn & (1 << 11)) {
1228 99c475ab bellard
            /* load */
1229 99c475ab bellard
            gen_op_ldub_T0_T1();
1230 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1231 99c475ab bellard
        } else {
1232 99c475ab bellard
            /* store */
1233 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1234 99c475ab bellard
            gen_op_stb_T0_T1();
1235 99c475ab bellard
        }
1236 99c475ab bellard
        break;
1237 99c475ab bellard
1238 99c475ab bellard
    case 8:
1239 99c475ab bellard
        /* load/store halfword immediate offset */
1240 99c475ab bellard
        rd = insn & 7;
1241 99c475ab bellard
        rn = (insn >> 3) & 7;
1242 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1243 99c475ab bellard
        val = (insn >> 5) & 0x3e;
1244 99c475ab bellard
        gen_op_movl_T2_im(val);
1245 99c475ab bellard
        gen_op_addl_T1_T2();
1246 99c475ab bellard
1247 99c475ab bellard
        if (insn & (1 << 11)) {
1248 99c475ab bellard
            /* load */
1249 99c475ab bellard
            gen_op_lduw_T0_T1();
1250 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1251 99c475ab bellard
        } else {
1252 99c475ab bellard
            /* store */
1253 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1254 99c475ab bellard
            gen_op_stw_T0_T1();
1255 99c475ab bellard
        }
1256 99c475ab bellard
        break;
1257 99c475ab bellard
1258 99c475ab bellard
    case 9:
1259 99c475ab bellard
        /* load/store from stack */
1260 99c475ab bellard
        rd = (insn >> 8) & 7;
1261 99c475ab bellard
        gen_movl_T1_reg(s, 13);
1262 99c475ab bellard
        val = (insn & 0xff) * 4;
1263 99c475ab bellard
        gen_op_movl_T2_im(val);
1264 99c475ab bellard
        gen_op_addl_T1_T2();
1265 99c475ab bellard
1266 99c475ab bellard
        if (insn & (1 << 11)) {
1267 99c475ab bellard
            /* load */
1268 99c475ab bellard
            gen_op_ldl_T0_T1();
1269 99c475ab bellard
            gen_movl_reg_T0(s, rd);
1270 99c475ab bellard
        } else {
1271 99c475ab bellard
            /* store */
1272 99c475ab bellard
            gen_movl_T0_reg(s, rd);
1273 99c475ab bellard
            gen_op_stl_T0_T1();
1274 99c475ab bellard
        }
1275 99c475ab bellard
        break;
1276 99c475ab bellard
1277 99c475ab bellard
    case 10:
1278 99c475ab bellard
        /* add to high reg */
1279 99c475ab bellard
        rd = (insn >> 8) & 7;
1280 99c475ab bellard
        if (insn & (1 << 11))
1281 99c475ab bellard
            rm = 13; /* sp */
1282 99c475ab bellard
        else
1283 99c475ab bellard
            rm = 15; /* pc */
1284 99c475ab bellard
        gen_movl_T0_reg(s, rm);
1285 99c475ab bellard
        val = (insn & 0xff) * 4;
1286 99c475ab bellard
        gen_op_movl_T1_im(val);
1287 99c475ab bellard
        gen_op_addl_T0_T1();
1288 99c475ab bellard
        gen_movl_reg_T0(s, rd);
1289 99c475ab bellard
        break;
1290 99c475ab bellard
1291 99c475ab bellard
    case 11:
1292 99c475ab bellard
        /* misc */
1293 99c475ab bellard
        op = (insn >> 8) & 0xf;
1294 99c475ab bellard
        switch (op) {
1295 99c475ab bellard
        case 0:
1296 99c475ab bellard
            /* adjust stack pointer */
1297 99c475ab bellard
            gen_movl_T1_reg(s, 13);
1298 99c475ab bellard
            val = (insn & 0x7f) * 4;
1299 99c475ab bellard
            if (insn & (1 << 7))
1300 99c475ab bellard
              val = -(int32_t)val;
1301 99c475ab bellard
            gen_op_movl_T2_im(val);
1302 99c475ab bellard
            gen_op_addl_T1_T2();
1303 99c475ab bellard
            gen_movl_reg_T1(s, 13);
1304 99c475ab bellard
            break;
1305 99c475ab bellard
1306 99c475ab bellard
        case 4: case 5: case 0xc: case 0xd:
1307 99c475ab bellard
            /* push/pop */
1308 99c475ab bellard
            gen_movl_T1_reg(s, 13);
1309 99c475ab bellard
            if (insn & (1 << 11))
1310 99c475ab bellard
                val = 4;
1311 99c475ab bellard
            else
1312 99c475ab bellard
                val = -4;
1313 99c475ab bellard
            gen_op_movl_T2_im(val);
1314 99c475ab bellard
            for (i = 0; i < 8; i++) {
1315 99c475ab bellard
                if (insn & (1 << i)) {
1316 99c475ab bellard
                    if (insn & (1 << 11)) {
1317 99c475ab bellard
                        /* pop */
1318 99c475ab bellard
                        gen_op_ldl_T0_T1();
1319 99c475ab bellard
                        gen_movl_reg_T0(s, i);
1320 99c475ab bellard
                    } else {
1321 99c475ab bellard
                        /* push */
1322 99c475ab bellard
                        gen_movl_T0_reg(s, i);
1323 99c475ab bellard
                        gen_op_stl_T0_T1();
1324 99c475ab bellard
                    }
1325 99c475ab bellard
                    /* move to the next address */
1326 99c475ab bellard
                    gen_op_addl_T1_T2();
1327 99c475ab bellard
                }
1328 99c475ab bellard
            }
1329 99c475ab bellard
            if (insn & (1 << 8)) {
1330 99c475ab bellard
                if (insn & (1 << 11)) {
1331 99c475ab bellard
                    /* pop pc */
1332 99c475ab bellard
                    gen_op_ldl_T0_T1();
1333 99c475ab bellard
                    /* don't set the pc until the rest of the instruction
1334 99c475ab bellard
                       has completed */
1335 99c475ab bellard
                } else {
1336 99c475ab bellard
                    /* push lr */
1337 99c475ab bellard
                    gen_movl_T0_reg(s, 14);
1338 99c475ab bellard
                    gen_op_stl_T0_T1();
1339 99c475ab bellard
                }
1340 99c475ab bellard
                gen_op_addl_T1_T2();
1341 99c475ab bellard
            }
1342 99c475ab bellard
1343 99c475ab bellard
            /* write back the new stack pointer */
1344 99c475ab bellard
            gen_movl_reg_T1(s, 13);
1345 99c475ab bellard
            /* set the new PC value */
1346 99c475ab bellard
            if ((insn & 0x0900) == 0x0900)
1347 99c475ab bellard
                gen_bx(s);
1348 99c475ab bellard
            break;
1349 99c475ab bellard
1350 99c475ab bellard
        default:
1351 99c475ab bellard
            goto undef;
1352 99c475ab bellard
        }
1353 99c475ab bellard
        break;
1354 99c475ab bellard
1355 99c475ab bellard
    case 12:
1356 99c475ab bellard
        /* load/store multiple */
1357 99c475ab bellard
        rn = (insn >> 8) & 0x7;
1358 99c475ab bellard
        gen_movl_T1_reg(s, rn);
1359 99c475ab bellard
        gen_op_movl_T2_im(4);
1360 99c475ab bellard
        val = 0;
1361 99c475ab bellard
        for (i = 0; i < 8; i++) {
1362 99c475ab bellard
            if (insn & (1 << i)) {
1363 99c475ab bellard
                /* advance to the next address */
1364 99c475ab bellard
                if (val)
1365 99c475ab bellard
                    gen_op_addl_T1_T2();
1366 99c475ab bellard
                else
1367 99c475ab bellard
                    val = 1;
1368 99c475ab bellard
                if (insn & (1 << 11)) {
1369 99c475ab bellard
                    /* load */
1370 99c475ab bellard
                    gen_op_ldl_T0_T1();
1371 99c475ab bellard
                    gen_movl_reg_T0(s, i);
1372 99c475ab bellard
                } else {
1373 99c475ab bellard
                    /* store */
1374 99c475ab bellard
                    gen_movl_T0_reg(s, i);
1375 99c475ab bellard
                    gen_op_stl_T0_T1();
1376 99c475ab bellard
                }
1377 99c475ab bellard
            }
1378 99c475ab bellard
        }
1379 99c475ab bellard
        break;
1380 99c475ab bellard
1381 99c475ab bellard
    case 13:
1382 99c475ab bellard
        /* conditional branch or swi */
1383 99c475ab bellard
        cond = (insn >> 8) & 0xf;
1384 99c475ab bellard
        if (cond == 0xe)
1385 99c475ab bellard
            goto undef;
1386 99c475ab bellard
1387 99c475ab bellard
        if (cond == 0xf) {
1388 99c475ab bellard
            /* swi */
1389 99c475ab bellard
            gen_op_movl_T0_im((long)s->pc | 1);
1390 99c475ab bellard
            /* Don't set r15.  */
1391 99c475ab bellard
            gen_op_movl_reg_TN[0][15]();
1392 99c475ab bellard
            gen_op_swi();
1393 99c475ab bellard
            s->is_jmp = DISAS_JUMP;
1394 99c475ab bellard
            break;
1395 99c475ab bellard
        }
1396 99c475ab bellard
        /* generate a conditional jump to next instruction */
1397 99c475ab bellard
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1398 99c475ab bellard
        s->is_jmp = DISAS_JUMP_NEXT;
1399 99c475ab bellard
        gen_movl_T1_reg(s, 15);
1400 99c475ab bellard
1401 99c475ab bellard
        /* jump to the offset */
1402 99c475ab bellard
        val = (uint32_t)s->pc;
1403 99c475ab bellard
        offset = ((int32_t)insn << 24) >> 24;
1404 99c475ab bellard
        val += (offset << 1) + 2;
1405 99c475ab bellard
        gen_op_jmp((long)s->tb, val);
1406 99c475ab bellard
        s->is_jmp = DISAS_TB_JUMP;
1407 99c475ab bellard
        break;
1408 99c475ab bellard
1409 99c475ab bellard
    case 14:
1410 99c475ab bellard
        /* unconditional branch */
1411 99c475ab bellard
        if (insn & (1 << 11))
1412 99c475ab bellard
            goto undef; /* Second half of a blx */
1413 99c475ab bellard
        val = (uint32_t)s->pc;
1414 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 21;
1415 99c475ab bellard
        val += (offset << 1) + 2;
1416 99c475ab bellard
        gen_op_jmp((long)s->tb, val);
1417 99c475ab bellard
        s->is_jmp = DISAS_TB_JUMP;
1418 99c475ab bellard
        break;
1419 99c475ab bellard
1420 99c475ab bellard
    case 15:
1421 99c475ab bellard
        /* branch and link [and switch to arm] */
1422 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 10;
1423 99c475ab bellard
        insn = lduw(s->pc);
1424 99c475ab bellard
        offset |= insn & 0x7ff;
1425 99c475ab bellard
1426 99c475ab bellard
        val = (uint32_t)s->pc + 2;
1427 99c475ab bellard
        gen_op_movl_T1_im(val | 1);
1428 99c475ab bellard
        gen_movl_reg_T1(s, 14);
1429 99c475ab bellard
        
1430 99c475ab bellard
        val += offset;
1431 99c475ab bellard
        if (insn & (1 << 11)) {
1432 99c475ab bellard
            /* bl */
1433 99c475ab bellard
            gen_op_jmp((long)s->tb, val);
1434 99c475ab bellard
            s->is_jmp = DISAS_TB_JUMP;
1435 99c475ab bellard
        } else {
1436 99c475ab bellard
            /* blx */
1437 99c475ab bellard
            gen_op_movl_T0_im(val);
1438 99c475ab bellard
            gen_bx(s);
1439 99c475ab bellard
        }
1440 99c475ab bellard
    }
1441 99c475ab bellard
    return;
1442 99c475ab bellard
undef:
1443 99c475ab bellard
    gen_op_movl_T0_im((long)s->pc - 4);
1444 99c475ab bellard
    gen_op_movl_reg_TN[0][15]();
1445 99c475ab bellard
    gen_op_undef_insn();
1446 99c475ab bellard
    s->is_jmp = DISAS_JUMP;
1447 99c475ab bellard
}
1448 99c475ab bellard
1449 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1450 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
1451 2c0262af bellard
   information for each intermediate instruction. */
1452 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env, 
1453 2c0262af bellard
                                                 TranslationBlock *tb, 
1454 2c0262af bellard
                                                 int search_pc)
1455 2c0262af bellard
{
1456 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
1457 2c0262af bellard
    uint16_t *gen_opc_end;
1458 2c0262af bellard
    int j, lj;
1459 0fa85d43 bellard
    target_ulong pc_start;
1460 2c0262af bellard
    
1461 2c0262af bellard
    /* generate intermediate code */
1462 0fa85d43 bellard
    pc_start = tb->pc;
1463 2c0262af bellard
       
1464 2c0262af bellard
    dc->tb = tb;
1465 2c0262af bellard
1466 2c0262af bellard
    gen_opc_ptr = gen_opc_buf;
1467 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1468 2c0262af bellard
    gen_opparam_ptr = gen_opparam_buf;
1469 2c0262af bellard
1470 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
1471 2c0262af bellard
    dc->pc = pc_start;
1472 2c0262af bellard
    lj = -1;
1473 2c0262af bellard
    do {
1474 2c0262af bellard
        if (search_pc) {
1475 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
1476 2c0262af bellard
            if (lj < j) {
1477 2c0262af bellard
                lj++;
1478 2c0262af bellard
                while (lj < j)
1479 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
1480 2c0262af bellard
            }
1481 0fa85d43 bellard
            gen_opc_pc[lj] = dc->pc;
1482 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
1483 2c0262af bellard
        }
1484 99c475ab bellard
        if (env->thumb)
1485 99c475ab bellard
          disas_thumb_insn(dc);
1486 99c475ab bellard
        else
1487 99c475ab bellard
          disas_arm_insn(dc);
1488 2c0262af bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
1489 2c0262af bellard
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1490 2c0262af bellard
    switch(dc->is_jmp) {
1491 2c0262af bellard
    case DISAS_JUMP_NEXT:
1492 2c0262af bellard
    case DISAS_NEXT:
1493 2c0262af bellard
        gen_op_jmp((long)dc->tb, (long)dc->pc);
1494 2c0262af bellard
        break;
1495 2c0262af bellard
    default:
1496 2c0262af bellard
    case DISAS_JUMP:
1497 99c475ab bellard
    case DISAS_UPDATE:
1498 2c0262af bellard
        /* indicate that the hash table must be used to find the next TB */
1499 2c0262af bellard
        gen_op_movl_T0_0();
1500 2c0262af bellard
        gen_op_exit_tb();
1501 2c0262af bellard
        break;
1502 2c0262af bellard
    case DISAS_TB_JUMP:
1503 2c0262af bellard
        /* nothing more to generate */
1504 2c0262af bellard
        break;
1505 2c0262af bellard
    }
1506 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
1507 2c0262af bellard
1508 2c0262af bellard
#ifdef DEBUG_DISAS
1509 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
1510 2c0262af bellard
        fprintf(logfile, "----------------\n");
1511 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1512 0fa85d43 bellard
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
1513 2c0262af bellard
        fprintf(logfile, "\n");
1514 e19e89a5 bellard
        if (loglevel & (CPU_LOG_TB_OP)) {
1515 e19e89a5 bellard
            fprintf(logfile, "OP:\n");
1516 e19e89a5 bellard
            dump_ops(gen_opc_buf, gen_opparam_buf);
1517 e19e89a5 bellard
            fprintf(logfile, "\n");
1518 e19e89a5 bellard
        }
1519 2c0262af bellard
    }
1520 2c0262af bellard
#endif
1521 2c0262af bellard
    if (!search_pc)
1522 2c0262af bellard
        tb->size = dc->pc - pc_start;
1523 2c0262af bellard
    return 0;
1524 2c0262af bellard
}
1525 2c0262af bellard
1526 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1527 2c0262af bellard
{
1528 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
1529 2c0262af bellard
}
1530 2c0262af bellard
1531 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1532 2c0262af bellard
{
1533 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
1534 2c0262af bellard
}
1535 2c0262af bellard
1536 2c0262af bellard
CPUARMState *cpu_arm_init(void)
1537 2c0262af bellard
{
1538 2c0262af bellard
    CPUARMState *env;
1539 2c0262af bellard
1540 2c0262af bellard
    cpu_exec_init();
1541 2c0262af bellard
1542 2c0262af bellard
    env = malloc(sizeof(CPUARMState));
1543 2c0262af bellard
    if (!env)
1544 2c0262af bellard
        return NULL;
1545 2c0262af bellard
    memset(env, 0, sizeof(CPUARMState));
1546 7496f526 bellard
    cpu_single_env = env;
1547 2c0262af bellard
    return env;
1548 2c0262af bellard
}
1549 2c0262af bellard
1550 2c0262af bellard
void cpu_arm_close(CPUARMState *env)
1551 2c0262af bellard
{
1552 2c0262af bellard
    free(env);
1553 2c0262af bellard
}
1554 2c0262af bellard
1555 7fe48483 bellard
void cpu_dump_state(CPUState *env, FILE *f, 
1556 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1557 7fe48483 bellard
                    int flags)
1558 2c0262af bellard
{
1559 2c0262af bellard
    int i;
1560 2c0262af bellard
1561 2c0262af bellard
    for(i=0;i<16;i++) {
1562 7fe48483 bellard
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
1563 2c0262af bellard
        if ((i % 4) == 3)
1564 7fe48483 bellard
            cpu_fprintf(f, "\n");
1565 2c0262af bellard
        else
1566 7fe48483 bellard
            cpu_fprintf(f, " ");
1567 2c0262af bellard
    }
1568 7fe48483 bellard
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
1569 2c0262af bellard
            env->cpsr, 
1570 2c0262af bellard
            env->cpsr & (1 << 31) ? 'N' : '-',
1571 2c0262af bellard
            env->cpsr & (1 << 30) ? 'Z' : '-',
1572 2c0262af bellard
            env->cpsr & (1 << 29) ? 'C' : '-',
1573 2c0262af bellard
            env->cpsr & (1 << 28) ? 'V' : '-');
1574 2c0262af bellard
}
1575 a6b025d3 bellard
1576 a6b025d3 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1577 a6b025d3 bellard
{
1578 a6b025d3 bellard
    return addr;
1579 a6b025d3 bellard
}
1580 b8a9e8f1 bellard
1581 b8a9e8f1 bellard
#if defined(CONFIG_USER_ONLY) 
1582 b8a9e8f1 bellard
1583 b8a9e8f1 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1584 b8a9e8f1 bellard
                              int is_user, int is_softmmu)
1585 b8a9e8f1 bellard
{
1586 b8a9e8f1 bellard
    env->cp15_6 = address;
1587 b8a9e8f1 bellard
    if (rw == 2) {
1588 b8a9e8f1 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
1589 b8a9e8f1 bellard
    } else {
1590 b8a9e8f1 bellard
        env->exception_index = EXCP_DATA_ABORT;
1591 b8a9e8f1 bellard
    }
1592 b8a9e8f1 bellard
    return 1;
1593 b8a9e8f1 bellard
}
1594 b8a9e8f1 bellard
1595 b8a9e8f1 bellard
#else
1596 b8a9e8f1 bellard
1597 b8a9e8f1 bellard
#error not implemented
1598 b8a9e8f1 bellard
1599 b8a9e8f1 bellard
#endif