Statistics
| Branch: | Revision:

root / target-arm / translate.c @ d1d9f421

History | View | Annotate | Download (23.5 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 2c0262af bellard
    uint8_t *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 2c0262af bellard
static GenOpFunc1 *gen_shift_T2_im[4] = {
98 2c0262af bellard
    gen_op_shll_T2_im,
99 2c0262af bellard
    gen_op_shrl_T2_im,
100 2c0262af bellard
    gen_op_sarl_T2_im,
101 2c0262af bellard
    gen_op_rorl_T2_im,
102 2c0262af bellard
};
103 2c0262af bellard
104 2c0262af bellard
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
105 2c0262af bellard
    gen_op_shll_T1_im_cc,
106 2c0262af bellard
    gen_op_shrl_T1_im_cc,
107 2c0262af bellard
    gen_op_sarl_T1_im_cc,
108 2c0262af bellard
    gen_op_rorl_T1_im_cc,
109 2c0262af bellard
};
110 2c0262af bellard
111 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0[4] = {
112 2c0262af bellard
    gen_op_shll_T1_T0,
113 2c0262af bellard
    gen_op_shrl_T1_T0,
114 2c0262af bellard
    gen_op_sarl_T1_T0,
115 2c0262af bellard
    gen_op_rorl_T1_T0,
116 2c0262af bellard
};
117 2c0262af bellard
118 2c0262af bellard
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
119 2c0262af bellard
    gen_op_shll_T1_T0_cc,
120 2c0262af bellard
    gen_op_shrl_T1_T0_cc,
121 2c0262af bellard
    gen_op_sarl_T1_T0_cc,
122 2c0262af bellard
    gen_op_rorl_T1_T0_cc,
123 2c0262af bellard
};
124 2c0262af bellard
125 2c0262af bellard
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
126 2c0262af bellard
    {
127 2c0262af bellard
        gen_op_movl_T0_r0,
128 2c0262af bellard
        gen_op_movl_T0_r1,
129 2c0262af bellard
        gen_op_movl_T0_r2,
130 2c0262af bellard
        gen_op_movl_T0_r3,
131 2c0262af bellard
        gen_op_movl_T0_r4,
132 2c0262af bellard
        gen_op_movl_T0_r5,
133 2c0262af bellard
        gen_op_movl_T0_r6,
134 2c0262af bellard
        gen_op_movl_T0_r7,
135 2c0262af bellard
        gen_op_movl_T0_r8,
136 2c0262af bellard
        gen_op_movl_T0_r9,
137 2c0262af bellard
        gen_op_movl_T0_r10,
138 2c0262af bellard
        gen_op_movl_T0_r11,
139 2c0262af bellard
        gen_op_movl_T0_r12,
140 2c0262af bellard
        gen_op_movl_T0_r13,
141 2c0262af bellard
        gen_op_movl_T0_r14,
142 2c0262af bellard
        gen_op_movl_T0_r15,
143 2c0262af bellard
    },
144 2c0262af bellard
    {
145 2c0262af bellard
        gen_op_movl_T1_r0,
146 2c0262af bellard
        gen_op_movl_T1_r1,
147 2c0262af bellard
        gen_op_movl_T1_r2,
148 2c0262af bellard
        gen_op_movl_T1_r3,
149 2c0262af bellard
        gen_op_movl_T1_r4,
150 2c0262af bellard
        gen_op_movl_T1_r5,
151 2c0262af bellard
        gen_op_movl_T1_r6,
152 2c0262af bellard
        gen_op_movl_T1_r7,
153 2c0262af bellard
        gen_op_movl_T1_r8,
154 2c0262af bellard
        gen_op_movl_T1_r9,
155 2c0262af bellard
        gen_op_movl_T1_r10,
156 2c0262af bellard
        gen_op_movl_T1_r11,
157 2c0262af bellard
        gen_op_movl_T1_r12,
158 2c0262af bellard
        gen_op_movl_T1_r13,
159 2c0262af bellard
        gen_op_movl_T1_r14,
160 2c0262af bellard
        gen_op_movl_T1_r15,
161 2c0262af bellard
    },
162 2c0262af bellard
    {
163 2c0262af bellard
        gen_op_movl_T2_r0,
164 2c0262af bellard
        gen_op_movl_T2_r1,
165 2c0262af bellard
        gen_op_movl_T2_r2,
166 2c0262af bellard
        gen_op_movl_T2_r3,
167 2c0262af bellard
        gen_op_movl_T2_r4,
168 2c0262af bellard
        gen_op_movl_T2_r5,
169 2c0262af bellard
        gen_op_movl_T2_r6,
170 2c0262af bellard
        gen_op_movl_T2_r7,
171 2c0262af bellard
        gen_op_movl_T2_r8,
172 2c0262af bellard
        gen_op_movl_T2_r9,
173 2c0262af bellard
        gen_op_movl_T2_r10,
174 2c0262af bellard
        gen_op_movl_T2_r11,
175 2c0262af bellard
        gen_op_movl_T2_r12,
176 2c0262af bellard
        gen_op_movl_T2_r13,
177 2c0262af bellard
        gen_op_movl_T2_r14,
178 2c0262af bellard
        gen_op_movl_T2_r15,
179 2c0262af bellard
    },
180 2c0262af bellard
};
181 2c0262af bellard
182 2c0262af bellard
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
183 2c0262af bellard
    {
184 2c0262af bellard
        gen_op_movl_r0_T0,
185 2c0262af bellard
        gen_op_movl_r1_T0,
186 2c0262af bellard
        gen_op_movl_r2_T0,
187 2c0262af bellard
        gen_op_movl_r3_T0,
188 2c0262af bellard
        gen_op_movl_r4_T0,
189 2c0262af bellard
        gen_op_movl_r5_T0,
190 2c0262af bellard
        gen_op_movl_r6_T0,
191 2c0262af bellard
        gen_op_movl_r7_T0,
192 2c0262af bellard
        gen_op_movl_r8_T0,
193 2c0262af bellard
        gen_op_movl_r9_T0,
194 2c0262af bellard
        gen_op_movl_r10_T0,
195 2c0262af bellard
        gen_op_movl_r11_T0,
196 2c0262af bellard
        gen_op_movl_r12_T0,
197 2c0262af bellard
        gen_op_movl_r13_T0,
198 2c0262af bellard
        gen_op_movl_r14_T0,
199 2c0262af bellard
        gen_op_movl_r15_T0,
200 2c0262af bellard
    },
201 2c0262af bellard
    {
202 2c0262af bellard
        gen_op_movl_r0_T1,
203 2c0262af bellard
        gen_op_movl_r1_T1,
204 2c0262af bellard
        gen_op_movl_r2_T1,
205 2c0262af bellard
        gen_op_movl_r3_T1,
206 2c0262af bellard
        gen_op_movl_r4_T1,
207 2c0262af bellard
        gen_op_movl_r5_T1,
208 2c0262af bellard
        gen_op_movl_r6_T1,
209 2c0262af bellard
        gen_op_movl_r7_T1,
210 2c0262af bellard
        gen_op_movl_r8_T1,
211 2c0262af bellard
        gen_op_movl_r9_T1,
212 2c0262af bellard
        gen_op_movl_r10_T1,
213 2c0262af bellard
        gen_op_movl_r11_T1,
214 2c0262af bellard
        gen_op_movl_r12_T1,
215 2c0262af bellard
        gen_op_movl_r13_T1,
216 2c0262af bellard
        gen_op_movl_r14_T1,
217 2c0262af bellard
        gen_op_movl_r15_T1,
218 2c0262af bellard
    },
219 2c0262af bellard
};
220 2c0262af bellard
221 2c0262af bellard
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
222 2c0262af bellard
    gen_op_movl_T0_im,
223 2c0262af bellard
    gen_op_movl_T1_im,
224 2c0262af bellard
    gen_op_movl_T2_im,
225 2c0262af bellard
};
226 2c0262af bellard
227 2c0262af bellard
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
228 2c0262af bellard
{
229 2c0262af bellard
    int val;
230 2c0262af bellard
231 2c0262af bellard
    if (reg == 15) {
232 2c0262af bellard
        /* normaly, since we updated PC, we need only to add 4 */
233 2c0262af bellard
        val = (long)s->pc + 4;
234 2c0262af bellard
        gen_op_movl_TN_im[t](val);
235 2c0262af bellard
    } else {
236 2c0262af bellard
        gen_op_movl_TN_reg[t][reg]();
237 2c0262af bellard
    }
238 2c0262af bellard
}
239 2c0262af bellard
240 2c0262af bellard
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
241 2c0262af bellard
{
242 2c0262af bellard
    gen_movl_TN_reg(s, reg, 0);
243 2c0262af bellard
}
244 2c0262af bellard
245 2c0262af bellard
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
246 2c0262af bellard
{
247 2c0262af bellard
    gen_movl_TN_reg(s, reg, 1);
248 2c0262af bellard
}
249 2c0262af bellard
250 2c0262af bellard
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
251 2c0262af bellard
{
252 2c0262af bellard
    gen_movl_TN_reg(s, reg, 2);
253 2c0262af bellard
}
254 2c0262af bellard
255 2c0262af bellard
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
256 2c0262af bellard
{
257 2c0262af bellard
    gen_op_movl_reg_TN[t][reg]();
258 2c0262af bellard
    if (reg == 15) {
259 2c0262af bellard
        s->is_jmp = DISAS_JUMP;
260 2c0262af bellard
    }
261 2c0262af bellard
}
262 2c0262af bellard
263 2c0262af bellard
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
264 2c0262af bellard
{
265 2c0262af bellard
    gen_movl_reg_TN(s, reg, 0);
266 2c0262af bellard
}
267 2c0262af bellard
268 2c0262af bellard
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
269 2c0262af bellard
{
270 2c0262af bellard
    gen_movl_reg_TN(s, reg, 1);
271 2c0262af bellard
}
272 2c0262af bellard
273 2c0262af bellard
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
274 2c0262af bellard
{
275 2c0262af bellard
    int val, rm, shift;
276 2c0262af bellard
277 2c0262af bellard
    if (!(insn & (1 << 25))) {
278 2c0262af bellard
        /* immediate */
279 2c0262af bellard
        val = insn & 0xfff;
280 2c0262af bellard
        if (!(insn & (1 << 23)))
281 2c0262af bellard
            val = -val;
282 537730b9 bellard
        if (val != 0)
283 537730b9 bellard
            gen_op_addl_T1_im(val);
284 2c0262af bellard
    } else {
285 2c0262af bellard
        /* shift/register */
286 2c0262af bellard
        rm = (insn) & 0xf;
287 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
288 2c0262af bellard
        gen_movl_T2_reg(s, rm);
289 2c0262af bellard
        if (shift != 0) {
290 2c0262af bellard
            gen_shift_T2_im[(insn >> 5) & 3](shift);
291 2c0262af bellard
        }
292 2c0262af bellard
        if (!(insn & (1 << 23)))
293 2c0262af bellard
            gen_op_subl_T1_T2();
294 2c0262af bellard
        else
295 2c0262af bellard
            gen_op_addl_T1_T2();
296 2c0262af bellard
    }
297 2c0262af bellard
}
298 2c0262af bellard
299 2c0262af bellard
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
300 2c0262af bellard
{
301 2c0262af bellard
    int val, rm;
302 2c0262af bellard
    
303 2c0262af bellard
    if (insn & (1 << 22)) {
304 2c0262af bellard
        /* immediate */
305 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
306 2c0262af bellard
        if (!(insn & (1 << 23)))
307 2c0262af bellard
            val = -val;
308 537730b9 bellard
        if (val != 0)
309 537730b9 bellard
            gen_op_addl_T1_im(val);
310 2c0262af bellard
    } else {
311 2c0262af bellard
        /* register */
312 2c0262af bellard
        rm = (insn) & 0xf;
313 2c0262af bellard
        gen_movl_T2_reg(s, rm);
314 2c0262af bellard
        if (!(insn & (1 << 23)))
315 2c0262af bellard
            gen_op_subl_T1_T2();
316 2c0262af bellard
        else
317 2c0262af bellard
            gen_op_addl_T1_T2();
318 2c0262af bellard
    }
319 2c0262af bellard
}
320 2c0262af bellard
321 2c0262af bellard
static void disas_arm_insn(DisasContext *s)
322 2c0262af bellard
{
323 2c0262af bellard
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
324 2c0262af bellard
    
325 2c0262af bellard
    insn = ldl(s->pc);
326 2c0262af bellard
    s->pc += 4;
327 2c0262af bellard
    
328 2c0262af bellard
    cond = insn >> 28;
329 2c0262af bellard
    if (cond == 0xf)
330 2c0262af bellard
        goto illegal_op;
331 2c0262af bellard
    if (cond != 0xe) {
332 2c0262af bellard
        /* if not always execute, we generate a conditional jump to
333 2c0262af bellard
           next instruction */
334 2c0262af bellard
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
335 2c0262af bellard
        s->is_jmp = DISAS_JUMP_NEXT;
336 2c0262af bellard
    }
337 2c0262af bellard
    if (((insn & 0x0e000000) == 0 &&
338 2c0262af bellard
         (insn & 0x00000090) != 0x90) ||
339 2c0262af bellard
        ((insn & 0x0e000000) == (1 << 25))) {
340 2c0262af bellard
        int set_cc, logic_cc, shiftop;
341 2c0262af bellard
        
342 2c0262af bellard
        op1 = (insn >> 21) & 0xf;
343 2c0262af bellard
        set_cc = (insn >> 20) & 1;
344 2c0262af bellard
        logic_cc = table_logic_cc[op1] & set_cc;
345 2c0262af bellard
346 2c0262af bellard
        /* data processing instruction */
347 2c0262af bellard
        if (insn & (1 << 25)) {
348 2c0262af bellard
            /* immediate operand */
349 2c0262af bellard
            val = insn & 0xff;
350 2c0262af bellard
            shift = ((insn >> 8) & 0xf) * 2;
351 2c0262af bellard
            if (shift)
352 2c0262af bellard
                val = (val >> shift) | (val << (32 - shift));
353 2c0262af bellard
            gen_op_movl_T1_im(val);
354 2c0262af bellard
            /* XXX: is CF modified ? */
355 2c0262af bellard
        } else {
356 2c0262af bellard
            /* register */
357 2c0262af bellard
            rm = (insn) & 0xf;
358 2c0262af bellard
            gen_movl_T1_reg(s, rm);
359 2c0262af bellard
            shiftop = (insn >> 5) & 3;
360 2c0262af bellard
            if (!(insn & (1 << 4))) {
361 2c0262af bellard
                shift = (insn >> 7) & 0x1f;
362 2c0262af bellard
                if (shift != 0) {
363 2c0262af bellard
                    if (logic_cc) {
364 2c0262af bellard
                        gen_shift_T1_im_cc[shiftop](shift);
365 2c0262af bellard
                    } else {
366 2c0262af bellard
                        gen_shift_T1_im[shiftop](shift);
367 2c0262af bellard
                    }
368 2c0262af bellard
                }
369 2c0262af bellard
            } else {
370 2c0262af bellard
                rs = (insn >> 8) & 0xf;
371 2c0262af bellard
                gen_movl_T0_reg(s, rs);
372 2c0262af bellard
                if (logic_cc) {
373 2c0262af bellard
                    gen_shift_T1_T0_cc[shiftop]();
374 2c0262af bellard
                } else {
375 2c0262af bellard
                    gen_shift_T1_T0[shiftop]();
376 2c0262af bellard
                }
377 2c0262af bellard
            }
378 2c0262af bellard
        }
379 2c0262af bellard
        if (op1 != 0x0f && op1 != 0x0d) {
380 2c0262af bellard
            rn = (insn >> 16) & 0xf;
381 2c0262af bellard
            gen_movl_T0_reg(s, rn);
382 2c0262af bellard
        }
383 2c0262af bellard
        rd = (insn >> 12) & 0xf;
384 2c0262af bellard
        switch(op1) {
385 2c0262af bellard
        case 0x00:
386 2c0262af bellard
            gen_op_andl_T0_T1();
387 2c0262af bellard
            gen_movl_reg_T0(s, rd);
388 2c0262af bellard
            if (logic_cc)
389 2c0262af bellard
                gen_op_logic_T0_cc();
390 2c0262af bellard
            break;
391 2c0262af bellard
        case 0x01:
392 2c0262af bellard
            gen_op_xorl_T0_T1();
393 2c0262af bellard
            gen_movl_reg_T0(s, rd);
394 2c0262af bellard
            if (logic_cc)
395 2c0262af bellard
                gen_op_logic_T0_cc();
396 2c0262af bellard
            break;
397 2c0262af bellard
        case 0x02:
398 2c0262af bellard
            if (set_cc)
399 2c0262af bellard
                gen_op_subl_T0_T1_cc();
400 2c0262af bellard
            else
401 2c0262af bellard
                gen_op_subl_T0_T1();
402 2c0262af bellard
            gen_movl_reg_T0(s, rd);
403 2c0262af bellard
            break;
404 2c0262af bellard
        case 0x03:
405 2c0262af bellard
            if (set_cc)
406 2c0262af bellard
                gen_op_rsbl_T0_T1_cc();
407 2c0262af bellard
            else
408 2c0262af bellard
                gen_op_rsbl_T0_T1();
409 2c0262af bellard
            gen_movl_reg_T0(s, rd);
410 2c0262af bellard
            break;
411 2c0262af bellard
        case 0x04:
412 2c0262af bellard
            if (set_cc)
413 2c0262af bellard
                gen_op_addl_T0_T1_cc();
414 2c0262af bellard
            else
415 2c0262af bellard
                gen_op_addl_T0_T1();
416 2c0262af bellard
            gen_movl_reg_T0(s, rd);
417 2c0262af bellard
            break;
418 2c0262af bellard
        case 0x05:
419 2c0262af bellard
            if (set_cc)
420 2c0262af bellard
                gen_op_adcl_T0_T1_cc();
421 2c0262af bellard
            else
422 2c0262af bellard
                gen_op_adcl_T0_T1();
423 2c0262af bellard
            gen_movl_reg_T0(s, rd);
424 2c0262af bellard
            break;
425 2c0262af bellard
        case 0x06:
426 2c0262af bellard
            if (set_cc)
427 2c0262af bellard
                gen_op_sbcl_T0_T1_cc();
428 2c0262af bellard
            else
429 2c0262af bellard
                gen_op_sbcl_T0_T1();
430 2c0262af bellard
            gen_movl_reg_T0(s, rd);
431 2c0262af bellard
            break;
432 2c0262af bellard
        case 0x07:
433 2c0262af bellard
            if (set_cc)
434 2c0262af bellard
                gen_op_rscl_T0_T1_cc();
435 2c0262af bellard
            else
436 2c0262af bellard
                gen_op_rscl_T0_T1();
437 2c0262af bellard
            gen_movl_reg_T0(s, rd);
438 2c0262af bellard
            break;
439 2c0262af bellard
        case 0x08:
440 2c0262af bellard
            if (set_cc) {
441 2c0262af bellard
                gen_op_andl_T0_T1();
442 2c0262af bellard
                gen_op_logic_T0_cc();
443 2c0262af bellard
            }
444 2c0262af bellard
            break;
445 2c0262af bellard
        case 0x09:
446 2c0262af bellard
            if (set_cc) {
447 2c0262af bellard
                gen_op_xorl_T0_T1();
448 2c0262af bellard
                gen_op_logic_T0_cc();
449 2c0262af bellard
            }
450 2c0262af bellard
            break;
451 2c0262af bellard
        case 0x0a:
452 2c0262af bellard
            if (set_cc) {
453 2c0262af bellard
                gen_op_subl_T0_T1_cc();
454 2c0262af bellard
            }
455 2c0262af bellard
            break;
456 2c0262af bellard
        case 0x0b:
457 2c0262af bellard
            if (set_cc) {
458 2c0262af bellard
                gen_op_addl_T0_T1_cc();
459 2c0262af bellard
            }
460 2c0262af bellard
            break;
461 2c0262af bellard
        case 0x0c:
462 2c0262af bellard
            gen_op_orl_T0_T1();
463 2c0262af bellard
            gen_movl_reg_T0(s, rd);
464 2c0262af bellard
            if (logic_cc)
465 2c0262af bellard
                gen_op_logic_T0_cc();
466 2c0262af bellard
            break;
467 2c0262af bellard
        case 0x0d:
468 2c0262af bellard
            gen_movl_reg_T1(s, rd);
469 2c0262af bellard
            if (logic_cc)
470 2c0262af bellard
                gen_op_logic_T1_cc();
471 2c0262af bellard
            break;
472 2c0262af bellard
        case 0x0e:
473 2c0262af bellard
            gen_op_bicl_T0_T1();
474 2c0262af bellard
            gen_movl_reg_T0(s, rd);
475 2c0262af bellard
            if (logic_cc)
476 2c0262af bellard
                gen_op_logic_T0_cc();
477 2c0262af bellard
            break;
478 2c0262af bellard
        default:
479 2c0262af bellard
        case 0x0f:
480 2c0262af bellard
            gen_op_notl_T1();
481 2c0262af bellard
            gen_movl_reg_T1(s, rd);
482 2c0262af bellard
            if (logic_cc)
483 2c0262af bellard
                gen_op_logic_T1_cc();
484 2c0262af bellard
            break;
485 2c0262af bellard
        }
486 2c0262af bellard
    } else {
487 2c0262af bellard
        /* other instructions */
488 2c0262af bellard
        op1 = (insn >> 24) & 0xf;
489 2c0262af bellard
        switch(op1) {
490 2c0262af bellard
        case 0x0:
491 2c0262af bellard
        case 0x1:
492 2c0262af bellard
            sh = (insn >> 5) & 3;
493 2c0262af bellard
            if (sh == 0) {
494 2c0262af bellard
                if (op1 == 0x0) {
495 2c0262af bellard
                    rd = (insn >> 16) & 0xf;
496 2c0262af bellard
                    rn = (insn >> 12) & 0xf;
497 2c0262af bellard
                    rs = (insn >> 8) & 0xf;
498 2c0262af bellard
                    rm = (insn) & 0xf;
499 2c0262af bellard
                    if (!(insn & (1 << 23))) {
500 2c0262af bellard
                        /* 32 bit mul */
501 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
502 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
503 2c0262af bellard
                        gen_op_mul_T0_T1();
504 2c0262af bellard
                        if (insn & (1 << 21)) {
505 2c0262af bellard
                            gen_movl_T1_reg(s, rn);
506 2c0262af bellard
                            gen_op_addl_T0_T1();
507 2c0262af bellard
                        }
508 2c0262af bellard
                        if (insn & (1 << 20)) 
509 2c0262af bellard
                            gen_op_logic_T0_cc();
510 2c0262af bellard
                        gen_movl_reg_T0(s, rd);
511 2c0262af bellard
                    } else {
512 2c0262af bellard
                        /* 64 bit mul */
513 2c0262af bellard
                        gen_movl_T0_reg(s, rs);
514 2c0262af bellard
                        gen_movl_T1_reg(s, rm);
515 2c0262af bellard
                        if (insn & (1 << 22)) 
516 2c0262af bellard
                            gen_op_imull_T0_T1();
517 2e134c9c bellard
                        else
518 2e134c9c bellard
                            gen_op_mull_T0_T1();
519 2c0262af bellard
                        if (insn & (1 << 21)) 
520 2c0262af bellard
                            gen_op_addq_T0_T1(rn, rd);
521 2c0262af bellard
                        if (insn & (1 << 20)) 
522 2c0262af bellard
                            gen_op_logicq_cc();
523 2c0262af bellard
                        gen_movl_reg_T0(s, rn);
524 2c0262af bellard
                        gen_movl_reg_T1(s, rd);
525 2c0262af bellard
                    }
526 2c0262af bellard
                } else {
527 2c0262af bellard
                    /* SWP instruction */
528 2c0262af bellard
                    rn = (insn >> 16) & 0xf;
529 2c0262af bellard
                    rd = (insn >> 12) & 0xf;
530 2c0262af bellard
                    rm = (insn) & 0xf;
531 2c0262af bellard
                    
532 2c0262af bellard
                    gen_movl_T0_reg(s, rm);
533 2c0262af bellard
                    gen_movl_T1_reg(s, rn);
534 2c0262af bellard
                    if (insn & (1 << 22)) {
535 2c0262af bellard
                        gen_op_swpb_T0_T1();
536 2c0262af bellard
                    } else {
537 2c0262af bellard
                        gen_op_swpl_T0_T1();
538 2c0262af bellard
                    }
539 2c0262af bellard
                    gen_movl_reg_T0(s, rd);
540 2c0262af bellard
                }
541 2c0262af bellard
            } else {
542 2c0262af bellard
                /* load/store half word */
543 2c0262af bellard
                rn = (insn >> 16) & 0xf;
544 2c0262af bellard
                rd = (insn >> 12) & 0xf;
545 2c0262af bellard
                gen_movl_T1_reg(s, rn);
546 beddab75 bellard
                if (insn & (1 << 24))
547 beddab75 bellard
                    gen_add_datah_offset(s, insn);
548 2c0262af bellard
                if (insn & (1 << 20)) {
549 2c0262af bellard
                    /* load */
550 2c0262af bellard
                    switch(sh) {
551 2c0262af bellard
                    case 1:
552 2c0262af bellard
                        gen_op_lduw_T0_T1();
553 2c0262af bellard
                        break;
554 2c0262af bellard
                    case 2:
555 2c0262af bellard
                        gen_op_ldsb_T0_T1();
556 2c0262af bellard
                        break;
557 2c0262af bellard
                    default:
558 2c0262af bellard
                    case 3:
559 2c0262af bellard
                        gen_op_ldsw_T0_T1();
560 2c0262af bellard
                        break;
561 2c0262af bellard
                    }
562 e748ba4f bellard
                    gen_movl_reg_T0(s, rd);
563 2c0262af bellard
                } else {
564 2c0262af bellard
                    /* store */
565 e748ba4f bellard
                    gen_movl_T0_reg(s, rd);
566 2c0262af bellard
                    gen_op_stw_T0_T1();
567 2c0262af bellard
                }
568 2c0262af bellard
                if (!(insn & (1 << 24))) {
569 2c0262af bellard
                    gen_add_datah_offset(s, insn);
570 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
571 2c0262af bellard
                } else if (insn & (1 << 21)) {
572 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
573 2c0262af bellard
                }
574 2c0262af bellard
            }
575 2c0262af bellard
            break;
576 2c0262af bellard
        case 0x4:
577 2c0262af bellard
        case 0x5:
578 2c0262af bellard
        case 0x6:
579 2c0262af bellard
        case 0x7:
580 2c0262af bellard
            /* load/store byte/word */
581 2c0262af bellard
            rn = (insn >> 16) & 0xf;
582 2c0262af bellard
            rd = (insn >> 12) & 0xf;
583 2c0262af bellard
            gen_movl_T1_reg(s, rn);
584 2c0262af bellard
            if (insn & (1 << 24))
585 2c0262af bellard
                gen_add_data_offset(s, insn);
586 2c0262af bellard
            if (insn & (1 << 20)) {
587 2c0262af bellard
                /* load */
588 2c0262af bellard
                if (insn & (1 << 22))
589 2c0262af bellard
                    gen_op_ldub_T0_T1();
590 2c0262af bellard
                else
591 2c0262af bellard
                    gen_op_ldl_T0_T1();
592 2c0262af bellard
                gen_movl_reg_T0(s, rd);
593 2c0262af bellard
            } else {
594 2c0262af bellard
                /* store */
595 2c0262af bellard
                gen_movl_T0_reg(s, rd);
596 2c0262af bellard
                if (insn & (1 << 22))
597 2c0262af bellard
                    gen_op_stb_T0_T1();
598 2c0262af bellard
                else
599 2c0262af bellard
                    gen_op_stl_T0_T1();
600 2c0262af bellard
            }
601 2c0262af bellard
            if (!(insn & (1 << 24))) {
602 2c0262af bellard
                gen_add_data_offset(s, insn);
603 2c0262af bellard
                gen_movl_reg_T1(s, rn);
604 2c0262af bellard
            } else if (insn & (1 << 21))
605 2c0262af bellard
                gen_movl_reg_T1(s, rn); {
606 2c0262af bellard
            }
607 2c0262af bellard
            break;
608 2c0262af bellard
        case 0x08:
609 2c0262af bellard
        case 0x09:
610 2c0262af bellard
            {
611 2c0262af bellard
                int j, n;
612 2c0262af bellard
                /* load/store multiple words */
613 2c0262af bellard
                /* XXX: store correct base if write back */
614 2c0262af bellard
                if (insn & (1 << 22))
615 2c0262af bellard
                    goto illegal_op; /* only usable in supervisor mode */
616 2c0262af bellard
                rn = (insn >> 16) & 0xf;
617 2c0262af bellard
                gen_movl_T1_reg(s, rn);
618 2c0262af bellard
                
619 2c0262af bellard
                /* compute total size */
620 2c0262af bellard
                n = 0;
621 2c0262af bellard
                for(i=0;i<16;i++) {
622 2c0262af bellard
                    if (insn & (1 << i))
623 2c0262af bellard
                        n++;
624 2c0262af bellard
                }
625 2c0262af bellard
                /* XXX: test invalid n == 0 case ? */
626 2c0262af bellard
                if (insn & (1 << 23)) {
627 2c0262af bellard
                    if (insn & (1 << 24)) {
628 2c0262af bellard
                        /* pre increment */
629 2c0262af bellard
                        gen_op_addl_T1_im(4);
630 2c0262af bellard
                    } else {
631 2c0262af bellard
                        /* post increment */
632 2c0262af bellard
                    }
633 2c0262af bellard
                } else {
634 2c0262af bellard
                    if (insn & (1 << 24)) {
635 2c0262af bellard
                        /* pre decrement */
636 2c0262af bellard
                        gen_op_addl_T1_im(-(n * 4));
637 2c0262af bellard
                    } else {
638 2c0262af bellard
                        /* post decrement */
639 2c0262af bellard
                        if (n != 1)
640 2c0262af bellard
                            gen_op_addl_T1_im(-((n - 1) * 4));
641 2c0262af bellard
                    }
642 2c0262af bellard
                }
643 2c0262af bellard
                j = 0;
644 2c0262af bellard
                for(i=0;i<16;i++) {
645 2c0262af bellard
                    if (insn & (1 << i)) {
646 2c0262af bellard
                        if (insn & (1 << 20)) {
647 2c0262af bellard
                            /* load */
648 2c0262af bellard
                            gen_op_ldl_T0_T1();
649 2c0262af bellard
                            gen_movl_reg_T0(s, i);
650 2c0262af bellard
                        } else {
651 2c0262af bellard
                            /* store */
652 2c0262af bellard
                            if (i == 15) {
653 2c0262af bellard
                                /* special case: r15 = PC + 12 */
654 2c0262af bellard
                                val = (long)s->pc + 8;
655 2c0262af bellard
                                gen_op_movl_TN_im[0](val);
656 2c0262af bellard
                            } else {
657 2c0262af bellard
                                gen_movl_T0_reg(s, i);
658 2c0262af bellard
                            }
659 2c0262af bellard
                            gen_op_stl_T0_T1();
660 2c0262af bellard
                        }
661 2c0262af bellard
                        j++;
662 2c0262af bellard
                        /* no need to add after the last transfer */
663 2c0262af bellard
                        if (j != n)
664 2c0262af bellard
                            gen_op_addl_T1_im(4);
665 2c0262af bellard
                    }
666 2c0262af bellard
                }
667 2c0262af bellard
                if (insn & (1 << 21)) {
668 2c0262af bellard
                    /* write back */
669 2c0262af bellard
                    if (insn & (1 << 23)) {
670 2c0262af bellard
                        if (insn & (1 << 24)) {
671 2c0262af bellard
                            /* pre increment */
672 2c0262af bellard
                        } else {
673 2c0262af bellard
                            /* post increment */
674 2c0262af bellard
                            gen_op_addl_T1_im(4);
675 2c0262af bellard
                        }
676 2c0262af bellard
                    } else {
677 2c0262af bellard
                        if (insn & (1 << 24)) {
678 2c0262af bellard
                            /* pre decrement */
679 2c0262af bellard
                            if (n != 1)
680 2c0262af bellard
                                gen_op_addl_T1_im(-((n - 1) * 4));
681 2c0262af bellard
                        } else {
682 2c0262af bellard
                            /* post decrement */
683 2c0262af bellard
                            gen_op_addl_T1_im(-(n * 4));
684 2c0262af bellard
                        }
685 2c0262af bellard
                    }
686 2c0262af bellard
                    gen_movl_reg_T1(s, rn);
687 2c0262af bellard
                }
688 2c0262af bellard
            }
689 2c0262af bellard
            break;
690 2c0262af bellard
        case 0xa:
691 2c0262af bellard
        case 0xb:
692 2c0262af bellard
            {
693 2c0262af bellard
                int offset;
694 2c0262af bellard
                
695 2c0262af bellard
                /* branch (and link) */
696 2c0262af bellard
                val = (int)s->pc;
697 2c0262af bellard
                if (insn & (1 << 24)) {
698 2c0262af bellard
                    gen_op_movl_T0_im(val);
699 2c0262af bellard
                    gen_op_movl_reg_TN[0][14]();
700 2c0262af bellard
                }
701 2c0262af bellard
                offset = (((int)insn << 8) >> 8);
702 2c0262af bellard
                val += (offset << 2) + 4;
703 2c0262af bellard
                gen_op_jmp((long)s->tb, val);
704 2c0262af bellard
                s->is_jmp = DISAS_TB_JUMP;
705 2c0262af bellard
            }
706 2c0262af bellard
            break;
707 2c0262af bellard
        case 0xf:
708 2c0262af bellard
            /* swi */
709 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc);
710 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
711 2c0262af bellard
            gen_op_swi();
712 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
713 2c0262af bellard
            break;
714 2c0262af bellard
        default:
715 2c0262af bellard
        illegal_op:
716 2c0262af bellard
            gen_op_movl_T0_im((long)s->pc - 4);
717 2c0262af bellard
            gen_op_movl_reg_TN[0][15]();
718 2c0262af bellard
            gen_op_undef_insn();
719 2c0262af bellard
            s->is_jmp = DISAS_JUMP;
720 2c0262af bellard
            break;
721 2c0262af bellard
        }
722 2c0262af bellard
    }
723 2c0262af bellard
}
724 2c0262af bellard
725 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
726 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
727 2c0262af bellard
   information for each intermediate instruction. */
728 2c0262af bellard
static inline int gen_intermediate_code_internal(CPUState *env, 
729 2c0262af bellard
                                                 TranslationBlock *tb, 
730 2c0262af bellard
                                                 int search_pc)
731 2c0262af bellard
{
732 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
733 2c0262af bellard
    uint16_t *gen_opc_end;
734 2c0262af bellard
    int j, lj;
735 2c0262af bellard
    uint8_t *pc_start;
736 2c0262af bellard
    
737 2c0262af bellard
    /* generate intermediate code */
738 2c0262af bellard
    pc_start = (uint8_t *)tb->pc;
739 2c0262af bellard
       
740 2c0262af bellard
    dc->tb = tb;
741 2c0262af bellard
742 2c0262af bellard
    gen_opc_ptr = gen_opc_buf;
743 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
744 2c0262af bellard
    gen_opparam_ptr = gen_opparam_buf;
745 2c0262af bellard
746 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
747 2c0262af bellard
    dc->pc = pc_start;
748 2c0262af bellard
    lj = -1;
749 2c0262af bellard
    do {
750 2c0262af bellard
        if (search_pc) {
751 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
752 2c0262af bellard
            if (lj < j) {
753 2c0262af bellard
                lj++;
754 2c0262af bellard
                while (lj < j)
755 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
756 2c0262af bellard
            }
757 2c0262af bellard
            gen_opc_pc[lj] = (uint32_t)dc->pc;
758 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
759 2c0262af bellard
        }
760 2c0262af bellard
        disas_arm_insn(dc);
761 2c0262af bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
762 2c0262af bellard
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
763 2c0262af bellard
    switch(dc->is_jmp) {
764 2c0262af bellard
    case DISAS_JUMP_NEXT:
765 2c0262af bellard
    case DISAS_NEXT:
766 2c0262af bellard
        gen_op_jmp((long)dc->tb, (long)dc->pc);
767 2c0262af bellard
        break;
768 2c0262af bellard
    default:
769 2c0262af bellard
    case DISAS_JUMP:
770 2c0262af bellard
        /* indicate that the hash table must be used to find the next TB */
771 2c0262af bellard
        gen_op_movl_T0_0();
772 2c0262af bellard
        gen_op_exit_tb();
773 2c0262af bellard
        break;
774 2c0262af bellard
    case DISAS_TB_JUMP:
775 2c0262af bellard
        /* nothing more to generate */
776 2c0262af bellard
        break;
777 2c0262af bellard
    }
778 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
779 2c0262af bellard
780 2c0262af bellard
#ifdef DEBUG_DISAS
781 e19e89a5 bellard
    if (loglevel & CPU_LOG_TB_IN_ASM) {
782 2c0262af bellard
        fprintf(logfile, "----------------\n");
783 2c0262af bellard
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
784 e19e89a5 bellard
        disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
785 2c0262af bellard
        fprintf(logfile, "\n");
786 e19e89a5 bellard
        if (loglevel & (CPU_LOG_TB_OP)) {
787 e19e89a5 bellard
            fprintf(logfile, "OP:\n");
788 e19e89a5 bellard
            dump_ops(gen_opc_buf, gen_opparam_buf);
789 e19e89a5 bellard
            fprintf(logfile, "\n");
790 e19e89a5 bellard
        }
791 2c0262af bellard
    }
792 2c0262af bellard
#endif
793 2c0262af bellard
    if (!search_pc)
794 2c0262af bellard
        tb->size = dc->pc - pc_start;
795 2c0262af bellard
    return 0;
796 2c0262af bellard
}
797 2c0262af bellard
798 2c0262af bellard
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
799 2c0262af bellard
{
800 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 0);
801 2c0262af bellard
}
802 2c0262af bellard
803 2c0262af bellard
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
804 2c0262af bellard
{
805 2c0262af bellard
    return gen_intermediate_code_internal(env, tb, 1);
806 2c0262af bellard
}
807 2c0262af bellard
808 2c0262af bellard
CPUARMState *cpu_arm_init(void)
809 2c0262af bellard
{
810 2c0262af bellard
    CPUARMState *env;
811 2c0262af bellard
812 2c0262af bellard
    cpu_exec_init();
813 2c0262af bellard
814 2c0262af bellard
    env = malloc(sizeof(CPUARMState));
815 2c0262af bellard
    if (!env)
816 2c0262af bellard
        return NULL;
817 2c0262af bellard
    memset(env, 0, sizeof(CPUARMState));
818 7496f526 bellard
    cpu_single_env = env;
819 2c0262af bellard
    return env;
820 2c0262af bellard
}
821 2c0262af bellard
822 2c0262af bellard
void cpu_arm_close(CPUARMState *env)
823 2c0262af bellard
{
824 2c0262af bellard
    free(env);
825 2c0262af bellard
}
826 2c0262af bellard
827 2c0262af bellard
void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
828 2c0262af bellard
{
829 2c0262af bellard
    int i;
830 2c0262af bellard
831 2c0262af bellard
    for(i=0;i<16;i++) {
832 2c0262af bellard
        fprintf(f, "R%02d=%08x", i, env->regs[i]);
833 2c0262af bellard
        if ((i % 4) == 3)
834 2c0262af bellard
            fprintf(f, "\n");
835 2c0262af bellard
        else
836 2c0262af bellard
            fprintf(f, " ");
837 2c0262af bellard
    }
838 2c0262af bellard
    fprintf(f, "PSR=%08x %c%c%c%c\n", 
839 2c0262af bellard
            env->cpsr, 
840 2c0262af bellard
            env->cpsr & (1 << 31) ? 'N' : '-',
841 2c0262af bellard
            env->cpsr & (1 << 30) ? 'Z' : '-',
842 2c0262af bellard
            env->cpsr & (1 << 29) ? 'C' : '-',
843 2c0262af bellard
            env->cpsr & (1 << 28) ? 'V' : '-');
844 2c0262af bellard
}
845 a6b025d3 bellard
846 a6b025d3 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
847 a6b025d3 bellard
{
848 a6b025d3 bellard
    return addr;
849 a6b025d3 bellard
}