]> git.proxmox.com Git - mirror_qemu.git/blame - target-arm/translate.c
ARM TCG conversion 4/16.
[mirror_qemu.git] / target-arm / translate.c
CommitLineData
2c0262af
FB
1/*
2 * ARM translation
5fafdf24 3 *
2c0262af 4 * Copyright (c) 2003 Fabrice Bellard
9ee6e8bb 5 * Copyright (c) 2005-2007 CodeSourcery
18c9b560 6 * Copyright (c) 2007 OpenedHand, Ltd.
2c0262af
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <stdarg.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <inttypes.h>
27
28#include "cpu.h"
29#include "exec-all.h"
30#include "disas.h"
57fec1fe 31#include "tcg-op.h"
1497c961
PB
32
33#define GEN_HELPER 1
b26eefb6 34#include "helpers.h"
2c0262af 35
9ee6e8bb
PB
36#define ENABLE_ARCH_5J 0
37#define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
38#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
39#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
40#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
b5ff1b31
FB
41
42#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
43
2c0262af
FB
44/* internal defines */
45typedef struct DisasContext {
0fa85d43 46 target_ulong pc;
2c0262af 47 int is_jmp;
e50e6a20
FB
48 /* Nonzero if this instruction has been conditionally skipped. */
49 int condjmp;
50 /* The label that will be jumped to when the instruction is skipped. */
51 int condlabel;
9ee6e8bb
PB
52 /* Thumb-2 condtional execution bits. */
53 int condexec_mask;
54 int condexec_cond;
2c0262af 55 struct TranslationBlock *tb;
8aaca4c0 56 int singlestep_enabled;
5899f386 57 int thumb;
6658ffb8 58 int is_mem;
b5ff1b31
FB
59#if !defined(CONFIG_USER_ONLY)
60 int user;
61#endif
2c0262af
FB
62} DisasContext;
63
b5ff1b31
FB
64#if defined(CONFIG_USER_ONLY)
65#define IS_USER(s) 1
66#else
67#define IS_USER(s) (s->user)
68#endif
69
9ee6e8bb
PB
70/* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72#define DISAS_WFI 4
73#define DISAS_SWI 5
2c0262af
FB
74
75/* XXX: move that elsewhere */
2c0262af
FB
76extern FILE *logfile;
77extern int loglevel;
78
b26eefb6
PB
79static TCGv cpu_env;
80/* FIXME: These should be removed. */
81static TCGv cpu_T[3];
82
83/* initialize TCG globals. */
84void arm_translate_init(void)
85{
86 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
87
88 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
89 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
90 cpu_T[2] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG3, "T2");
91}
92
93/* The code generator doesn't like lots of temporaries, so maintain our own
94 cache for reuse within a function. */
95#define MAX_TEMPS 8
96static int num_temps;
97static TCGv temps[MAX_TEMPS];
98
99/* Allocate a temporary variable. */
100static TCGv new_tmp(void)
101{
102 TCGv tmp;
103 if (num_temps == MAX_TEMPS)
104 abort();
105
106 if (GET_TCGV(temps[num_temps]))
107 return temps[num_temps++];
108
109 tmp = tcg_temp_new(TCG_TYPE_I32);
110 temps[num_temps++] = tmp;
111 return tmp;
112}
113
114/* Release a temporary variable. */
115static void dead_tmp(TCGv tmp)
116{
117 int i;
118 num_temps--;
119 i = num_temps;
120 if (GET_TCGV(temps[i]) == GET_TCGV(tmp))
121 return;
122
123 /* Shuffle this temp to the last slot. */
124 while (GET_TCGV(temps[i]) != GET_TCGV(tmp))
125 i--;
126 while (i < num_temps) {
127 temps[i] = temps[i + 1];
128 i++;
129 }
130 temps[i] = tmp;
131}
132
133/* Set a variable to the value of a CPU register. */
134static void load_reg_var(DisasContext *s, TCGv var, int reg)
135{
136 if (reg == 15) {
137 uint32_t addr;
138 /* normaly, since we updated PC, we need only to add one insn */
139 if (s->thumb)
140 addr = (long)s->pc + 2;
141 else
142 addr = (long)s->pc + 4;
143 tcg_gen_movi_i32(var, addr);
144 } else {
145 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
146 }
147}
148
149/* Create a new temporary and set it to the value of a CPU register. */
150static inline TCGv load_reg(DisasContext *s, int reg)
151{
152 TCGv tmp = new_tmp();
153 load_reg_var(s, tmp, reg);
154 return tmp;
155}
156
157/* Set a CPU register. The source must be a temporary and will be
158 marked as dead. */
159static void store_reg(DisasContext *s, int reg, TCGv var)
160{
161 if (reg == 15) {
162 tcg_gen_andi_i32(var, var, ~1);
163 s->is_jmp = DISAS_JUMP;
164 }
165 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
166 dead_tmp(var);
167}
168
169
170/* Basic operations. */
171#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
172#define gen_op_movl_T0_T2() tcg_gen_mov_i32(cpu_T[0], cpu_T[2])
173#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
174#define gen_op_movl_T1_T2() tcg_gen_mov_i32(cpu_T[1], cpu_T[2])
175#define gen_op_movl_T2_T0() tcg_gen_mov_i32(cpu_T[2], cpu_T[0])
176#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
177#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
178#define gen_op_movl_T2_im(im) tcg_gen_movi_i32(cpu_T[2], im)
179
180#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
181#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
182#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
183#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
184
185#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
186#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
187#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
188#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
189#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
190#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
191#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
192
193#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
194#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
195#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
196#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
197#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
198
199/* Value extensions. */
200#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
201#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
202#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
203#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
204
1497c961
PB
205#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
b26eefb6 207
1497c961
PB
208#define gen_op_addl_T0_T1_setq() \
209 gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
210#define gen_op_addl_T0_T1_saturate() \
211 gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
212#define gen_op_subl_T0_T1_saturate() \
213 gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
214#define gen_op_addl_T0_T1_usaturate() \
215 gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
216#define gen_op_subl_T0_T1_usaturate() \
217 gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
f51bbbfe 218
b26eefb6
PB
219/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
220 tmp = (t0 ^ t1) & 0x8000;
221 t0 &= ~0x8000;
222 t1 &= ~0x8000;
223 t0 = (t0 + t1) ^ tmp;
224 */
225
226static void gen_add16(TCGv t0, TCGv t1)
227{
228 TCGv tmp = new_tmp();
229 tcg_gen_xor_i32(tmp, t0, t1);
230 tcg_gen_andi_i32(tmp, tmp, 0x8000);
231 tcg_gen_andi_i32(t0, t0, ~0x8000);
232 tcg_gen_andi_i32(t1, t1, ~0x8000);
233 tcg_gen_add_i32(t0, t0, t1);
234 tcg_gen_xor_i32(t0, t0, tmp);
235 dead_tmp(tmp);
236 dead_tmp(t1);
237}
238
9a119ff6
PB
239#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
240
b26eefb6
PB
241/* Set CF to the top bit of var. */
242static void gen_set_CF_bit31(TCGv var)
243{
244 TCGv tmp = new_tmp();
245 tcg_gen_shri_i32(tmp, var, 31);
9a119ff6 246 gen_set_CF(var);
b26eefb6
PB
247 dead_tmp(tmp);
248}
249
250/* Set N and Z flags from var. */
251static inline void gen_logic_CC(TCGv var)
252{
253 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
254}
255
256/* T0 += T1 + CF. */
257static void gen_adc_T0_T1(void)
258{
259 TCGv tmp = new_tmp();
260 gen_op_addl_T0_T1();
261 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
262 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
263 dead_tmp(tmp);
264}
265
266/* FIXME: Implement this natively. */
267static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
268{
269 tcg_gen_xori_i32(t0, t1, ~0);
270}
271
272/* T0 &= ~T1. Clobbers T1. */
273/* FIXME: Implement bic natively. */
274static inline void gen_op_bicl_T0_T1(void)
275{
276 gen_op_notl_T1();
277 gen_op_andl_T0_T1();
278}
279
280/* FIXME: Implement this natively. */
281static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
282{
283 TCGv tmp;
284
285 if (i == 0)
286 return;
287
288 tmp = new_tmp();
289 tcg_gen_shri_i32(tmp, t1, i);
290 tcg_gen_shli_i32(t1, t1, 32 - i);
291 tcg_gen_or_i32(t0, t1, tmp);
292 dead_tmp(tmp);
293}
294
9a119ff6 295static void shifter_out_im(TCGv var, int shift)
b26eefb6 296{
9a119ff6
PB
297 TCGv tmp = new_tmp();
298 if (shift == 0) {
299 tcg_gen_andi_i32(tmp, var, 1);
b26eefb6 300 } else {
9a119ff6
PB
301 tcg_gen_shri_i32(tmp, var, shift);
302 if (shift != 31);
303 tcg_gen_andi_i32(tmp, tmp, 1);
304 }
305 gen_set_CF(tmp);
306 dead_tmp(tmp);
307}
b26eefb6 308
9a119ff6
PB
309/* Shift by immediate. Includes special handling for shift == 0. */
310static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
311{
312 switch (shiftop) {
313 case 0: /* LSL */
314 if (shift != 0) {
315 if (flags)
316 shifter_out_im(var, 32 - shift);
317 tcg_gen_shli_i32(var, var, shift);
318 }
319 break;
320 case 1: /* LSR */
321 if (shift == 0) {
322 if (flags) {
323 tcg_gen_shri_i32(var, var, 31);
324 gen_set_CF(var);
325 }
326 tcg_gen_movi_i32(var, 0);
327 } else {
328 if (flags)
329 shifter_out_im(var, shift - 1);
330 tcg_gen_shri_i32(var, var, shift);
331 }
332 break;
333 case 2: /* ASR */
334 if (shift == 0)
335 shift = 32;
336 if (flags)
337 shifter_out_im(var, shift - 1);
338 if (shift == 32)
339 shift = 31;
340 tcg_gen_sari_i32(var, var, shift);
341 break;
342 case 3: /* ROR/RRX */
343 if (shift != 0) {
344 if (flags)
345 shifter_out_im(var, shift - 1);
346 tcg_gen_rori_i32(var, var, shift); break;
347 } else {
348 TCGv tmp = new_tmp();
b26eefb6 349 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
9a119ff6
PB
350 if (flags)
351 shifter_out_im(var, 0);
352 tcg_gen_shri_i32(var, var, 1);
b26eefb6
PB
353 tcg_gen_shli_i32(tmp, tmp, 31);
354 tcg_gen_or_i32(var, var, tmp);
355 dead_tmp(tmp);
b26eefb6
PB
356 }
357 }
358};
359
9ee6e8bb
PB
360#define PAS_OP(pfx) { \
361 gen_op_ ## pfx ## add16_T0_T1, \
362 gen_op_ ## pfx ## addsubx_T0_T1, \
363 gen_op_ ## pfx ## subaddx_T0_T1, \
364 gen_op_ ## pfx ## sub16_T0_T1, \
365 gen_op_ ## pfx ## add8_T0_T1, \
366 NULL, \
367 NULL, \
368 gen_op_ ## pfx ## sub8_T0_T1 }
369
370static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
371 {},
372 PAS_OP(s),
373 PAS_OP(q),
374 PAS_OP(sh),
375 {},
376 PAS_OP(u),
377 PAS_OP(uq),
378 PAS_OP(uh),
379};
380#undef PAS_OP
381
382/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings. */
383#define PAS_OP(pfx) { \
384 gen_op_ ## pfx ## add8_T0_T1, \
385 gen_op_ ## pfx ## add16_T0_T1, \
386 gen_op_ ## pfx ## addsubx_T0_T1, \
387 NULL, \
388 gen_op_ ## pfx ## sub8_T0_T1, \
389 gen_op_ ## pfx ## sub16_T0_T1, \
390 gen_op_ ## pfx ## subaddx_T0_T1, \
391 NULL }
392
393static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
394 PAS_OP(s),
395 PAS_OP(q),
396 PAS_OP(sh),
397 {},
398 PAS_OP(u),
399 PAS_OP(uq),
400 PAS_OP(uh),
401 {}
402};
403#undef PAS_OP
404
e50e6a20 405static GenOpFunc1 *gen_test_cc[14] = {
2c0262af
FB
406 gen_op_test_eq,
407 gen_op_test_ne,
408 gen_op_test_cs,
409 gen_op_test_cc,
410 gen_op_test_mi,
411 gen_op_test_pl,
412 gen_op_test_vs,
413 gen_op_test_vc,
414 gen_op_test_hi,
415 gen_op_test_ls,
416 gen_op_test_ge,
417 gen_op_test_lt,
418 gen_op_test_gt,
419 gen_op_test_le,
420};
421
422const uint8_t table_logic_cc[16] = {
423 1, /* and */
424 1, /* xor */
425 0, /* sub */
426 0, /* rsb */
427 0, /* add */
428 0, /* adc */
429 0, /* sbc */
430 0, /* rsc */
431 1, /* andl */
432 1, /* xorl */
433 0, /* cmp */
434 0, /* cmn */
435 1, /* orr */
436 1, /* mov */
437 1, /* bic */
438 1, /* mvn */
439};
3b46e624 440
2c0262af
FB
441static GenOpFunc *gen_shift_T1_T0[4] = {
442 gen_op_shll_T1_T0,
443 gen_op_shrl_T1_T0,
444 gen_op_sarl_T1_T0,
445 gen_op_rorl_T1_T0,
446};
447
448static GenOpFunc *gen_shift_T1_T0_cc[4] = {
449 gen_op_shll_T1_T0_cc,
450 gen_op_shrl_T1_T0_cc,
451 gen_op_sarl_T1_T0_cc,
452 gen_op_rorl_T1_T0_cc,
453};
454
b26eefb6 455/* Set PC and thumb state from T0. Clobbers T0. */
99c475ab
FB
456static inline void gen_bx(DisasContext *s)
457{
b26eefb6 458 TCGv tmp;
99c475ab 459
b26eefb6
PB
460 s->is_jmp = DISAS_UPDATE;
461 tmp = new_tmp();
462 tcg_gen_andi_i32(tmp, cpu_T[0], 1);
463 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
464 dead_tmp(tmp);
465 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ~1);
466 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
467}
b5ff1b31
FB
468
469#if defined(CONFIG_USER_ONLY)
470#define gen_ldst(name, s) gen_op_##name##_raw()
471#else
472#define gen_ldst(name, s) do { \
6658ffb8 473 s->is_mem = 1; \
b5ff1b31
FB
474 if (IS_USER(s)) \
475 gen_op_##name##_user(); \
476 else \
477 gen_op_##name##_kernel(); \
478 } while (0)
479#endif
480
2c0262af
FB
481static inline void gen_movl_T0_reg(DisasContext *s, int reg)
482{
b26eefb6 483 load_reg_var(s, cpu_T[0], reg);
2c0262af
FB
484}
485
486static inline void gen_movl_T1_reg(DisasContext *s, int reg)
487{
b26eefb6 488 load_reg_var(s, cpu_T[1], reg);
2c0262af
FB
489}
490
491static inline void gen_movl_T2_reg(DisasContext *s, int reg)
492{
b26eefb6
PB
493 load_reg_var(s, cpu_T[2], reg);
494}
495
496static inline void gen_set_pc_T0(void)
497{
498 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
2c0262af
FB
499}
500
501static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
502{
b26eefb6
PB
503 TCGv tmp;
504 if (reg == 15) {
505 tmp = new_tmp();
506 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
507 } else {
508 tmp = cpu_T[t];
509 }
510 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
2c0262af 511 if (reg == 15) {
b26eefb6 512 dead_tmp(tmp);
2c0262af
FB
513 s->is_jmp = DISAS_JUMP;
514 }
515}
516
517static inline void gen_movl_reg_T0(DisasContext *s, int reg)
518{
519 gen_movl_reg_TN(s, reg, 0);
520}
521
522static inline void gen_movl_reg_T1(DisasContext *s, int reg)
523{
524 gen_movl_reg_TN(s, reg, 1);
525}
526
b5ff1b31
FB
527/* Force a TB lookup after an instruction that changes the CPU state. */
528static inline void gen_lookup_tb(DisasContext *s)
529{
530 gen_op_movl_T0_im(s->pc);
531 gen_movl_reg_T0(s, 15);
532 s->is_jmp = DISAS_UPDATE;
533}
534
2c0262af
FB
535static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
536{
1e8d4eec 537 int val, rm, shift, shiftop;
b26eefb6 538 TCGv offset;
2c0262af
FB
539
540 if (!(insn & (1 << 25))) {
541 /* immediate */
542 val = insn & 0xfff;
543 if (!(insn & (1 << 23)))
544 val = -val;
537730b9
FB
545 if (val != 0)
546 gen_op_addl_T1_im(val);
2c0262af
FB
547 } else {
548 /* shift/register */
549 rm = (insn) & 0xf;
550 shift = (insn >> 7) & 0x1f;
1e8d4eec 551 shiftop = (insn >> 5) & 3;
b26eefb6 552 offset = load_reg(s, rm);
9a119ff6 553 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 554 if (!(insn & (1 << 23)))
b26eefb6 555 tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
2c0262af 556 else
b26eefb6
PB
557 tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
558 dead_tmp(offset);
2c0262af
FB
559 }
560}
561
191f9a93
PB
562static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
563 int extra)
2c0262af
FB
564{
565 int val, rm;
b26eefb6 566 TCGv offset;
3b46e624 567
2c0262af
FB
568 if (insn & (1 << 22)) {
569 /* immediate */
570 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
571 if (!(insn & (1 << 23)))
572 val = -val;
18acad92 573 val += extra;
537730b9
FB
574 if (val != 0)
575 gen_op_addl_T1_im(val);
2c0262af
FB
576 } else {
577 /* register */
191f9a93
PB
578 if (extra)
579 gen_op_addl_T1_im(extra);
2c0262af 580 rm = (insn) & 0xf;
b26eefb6 581 offset = load_reg(s, rm);
2c0262af 582 if (!(insn & (1 << 23)))
b26eefb6 583 tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
2c0262af 584 else
b26eefb6
PB
585 tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
586 dead_tmp(offset);
2c0262af
FB
587 }
588}
589
b7bcbe95
FB
590#define VFP_OP(name) \
591static inline void gen_vfp_##name(int dp) \
592{ \
593 if (dp) \
594 gen_op_vfp_##name##d(); \
595 else \
596 gen_op_vfp_##name##s(); \
597}
598
9ee6e8bb
PB
599#define VFP_OP1(name) \
600static inline void gen_vfp_##name(int dp, int arg) \
601{ \
602 if (dp) \
603 gen_op_vfp_##name##d(arg); \
604 else \
605 gen_op_vfp_##name##s(arg); \
606}
607
b7bcbe95
FB
608VFP_OP(add)
609VFP_OP(sub)
610VFP_OP(mul)
611VFP_OP(div)
612VFP_OP(neg)
613VFP_OP(abs)
614VFP_OP(sqrt)
615VFP_OP(cmp)
616VFP_OP(cmpe)
617VFP_OP(F1_ld0)
618VFP_OP(uito)
619VFP_OP(sito)
620VFP_OP(toui)
621VFP_OP(touiz)
622VFP_OP(tosi)
623VFP_OP(tosiz)
9ee6e8bb
PB
624VFP_OP1(tosh)
625VFP_OP1(tosl)
626VFP_OP1(touh)
627VFP_OP1(toul)
628VFP_OP1(shto)
629VFP_OP1(slto)
630VFP_OP1(uhto)
631VFP_OP1(ulto)
b7bcbe95
FB
632
633#undef VFP_OP
634
9ee6e8bb
PB
635static inline void gen_vfp_fconst(int dp, uint32_t val)
636{
637 if (dp)
638 gen_op_vfp_fconstd(val);
639 else
640 gen_op_vfp_fconsts(val);
641}
642
b5ff1b31
FB
643static inline void gen_vfp_ld(DisasContext *s, int dp)
644{
645 if (dp)
646 gen_ldst(vfp_ldd, s);
647 else
648 gen_ldst(vfp_lds, s);
649}
650
651static inline void gen_vfp_st(DisasContext *s, int dp)
652{
653 if (dp)
654 gen_ldst(vfp_std, s);
655 else
656 gen_ldst(vfp_sts, s);
657}
658
8e96005d
FB
659static inline long
660vfp_reg_offset (int dp, int reg)
661{
662 if (dp)
663 return offsetof(CPUARMState, vfp.regs[reg]);
664 else if (reg & 1) {
665 return offsetof(CPUARMState, vfp.regs[reg >> 1])
666 + offsetof(CPU_DoubleU, l.upper);
667 } else {
668 return offsetof(CPUARMState, vfp.regs[reg >> 1])
669 + offsetof(CPU_DoubleU, l.lower);
670 }
671}
9ee6e8bb
PB
672
673/* Return the offset of a 32-bit piece of a NEON register.
674 zero is the least significant end of the register. */
675static inline long
676neon_reg_offset (int reg, int n)
677{
678 int sreg;
679 sreg = reg * 2 + n;
680 return vfp_reg_offset(0, sreg);
681}
682
683#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
684#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
685
b7bcbe95
FB
686static inline void gen_mov_F0_vreg(int dp, int reg)
687{
688 if (dp)
8e96005d 689 gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
b7bcbe95 690 else
8e96005d 691 gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
b7bcbe95
FB
692}
693
694static inline void gen_mov_F1_vreg(int dp, int reg)
695{
696 if (dp)
8e96005d 697 gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
b7bcbe95 698 else
8e96005d 699 gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
b7bcbe95
FB
700}
701
702static inline void gen_mov_vreg_F0(int dp, int reg)
703{
704 if (dp)
8e96005d 705 gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
b7bcbe95 706 else
8e96005d 707 gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
b7bcbe95
FB
708}
709
18c9b560
AZ
710#define ARM_CP_RW_BIT (1 << 20)
711
712static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
713{
714 int rd;
715 uint32_t offset;
716
717 rd = (insn >> 16) & 0xf;
718 gen_movl_T1_reg(s, rd);
719
720 offset = (insn & 0xff) << ((insn >> 7) & 2);
721 if (insn & (1 << 24)) {
722 /* Pre indexed */
723 if (insn & (1 << 23))
724 gen_op_addl_T1_im(offset);
725 else
726 gen_op_addl_T1_im(-offset);
727
728 if (insn & (1 << 21))
729 gen_movl_reg_T1(s, rd);
730 } else if (insn & (1 << 21)) {
731 /* Post indexed */
732 if (insn & (1 << 23))
733 gen_op_movl_T0_im(offset);
734 else
735 gen_op_movl_T0_im(- offset);
736 gen_op_addl_T0_T1();
737 gen_movl_reg_T0(s, rd);
738 } else if (!(insn & (1 << 23)))
739 return 1;
740 return 0;
741}
742
743static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
744{
745 int rd = (insn >> 0) & 0xf;
746
747 if (insn & (1 << 8))
748 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
749 return 1;
750 else
751 gen_op_iwmmxt_movl_T0_wCx(rd);
752 else
753 gen_op_iwmmxt_movl_T0_T1_wRn(rd);
754
755 gen_op_movl_T1_im(mask);
756 gen_op_andl_T0_T1();
757 return 0;
758}
759
760/* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
761 (ie. an undefined instruction). */
762static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
763{
764 int rd, wrd;
765 int rdhi, rdlo, rd0, rd1, i;
766
767 if ((insn & 0x0e000e00) == 0x0c000000) {
768 if ((insn & 0x0fe00ff0) == 0x0c400000) {
769 wrd = insn & 0xf;
770 rdlo = (insn >> 12) & 0xf;
771 rdhi = (insn >> 16) & 0xf;
772 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
773 gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
774 gen_movl_reg_T0(s, rdlo);
775 gen_movl_reg_T1(s, rdhi);
776 } else { /* TMCRR */
777 gen_movl_T0_reg(s, rdlo);
778 gen_movl_T1_reg(s, rdhi);
779 gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
780 gen_op_iwmmxt_set_mup();
781 }
782 return 0;
783 }
784
785 wrd = (insn >> 12) & 0xf;
786 if (gen_iwmmxt_address(s, insn))
787 return 1;
788 if (insn & ARM_CP_RW_BIT) {
789 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
790 gen_ldst(ldl, s);
791 gen_op_iwmmxt_movl_wCx_T0(wrd);
792 } else {
793 if (insn & (1 << 8))
794 if (insn & (1 << 22)) /* WLDRD */
795 gen_ldst(iwmmxt_ldq, s);
796 else /* WLDRW wRd */
797 gen_ldst(iwmmxt_ldl, s);
798 else
799 if (insn & (1 << 22)) /* WLDRH */
800 gen_ldst(iwmmxt_ldw, s);
801 else /* WLDRB */
802 gen_ldst(iwmmxt_ldb, s);
803 gen_op_iwmmxt_movq_wRn_M0(wrd);
804 }
805 } else {
806 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
807 gen_op_iwmmxt_movl_T0_wCx(wrd);
808 gen_ldst(stl, s);
809 } else {
810 gen_op_iwmmxt_movq_M0_wRn(wrd);
811 if (insn & (1 << 8))
812 if (insn & (1 << 22)) /* WSTRD */
813 gen_ldst(iwmmxt_stq, s);
814 else /* WSTRW wRd */
815 gen_ldst(iwmmxt_stl, s);
816 else
817 if (insn & (1 << 22)) /* WSTRH */
818 gen_ldst(iwmmxt_ldw, s);
819 else /* WSTRB */
820 gen_ldst(iwmmxt_stb, s);
821 }
822 }
823 return 0;
824 }
825
826 if ((insn & 0x0f000000) != 0x0e000000)
827 return 1;
828
829 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
830 case 0x000: /* WOR */
831 wrd = (insn >> 12) & 0xf;
832 rd0 = (insn >> 0) & 0xf;
833 rd1 = (insn >> 16) & 0xf;
834 gen_op_iwmmxt_movq_M0_wRn(rd0);
835 gen_op_iwmmxt_orq_M0_wRn(rd1);
836 gen_op_iwmmxt_setpsr_nz();
837 gen_op_iwmmxt_movq_wRn_M0(wrd);
838 gen_op_iwmmxt_set_mup();
839 gen_op_iwmmxt_set_cup();
840 break;
841 case 0x011: /* TMCR */
842 if (insn & 0xf)
843 return 1;
844 rd = (insn >> 12) & 0xf;
845 wrd = (insn >> 16) & 0xf;
846 switch (wrd) {
847 case ARM_IWMMXT_wCID:
848 case ARM_IWMMXT_wCASF:
849 break;
850 case ARM_IWMMXT_wCon:
851 gen_op_iwmmxt_set_cup();
852 /* Fall through. */
853 case ARM_IWMMXT_wCSSF:
854 gen_op_iwmmxt_movl_T0_wCx(wrd);
855 gen_movl_T1_reg(s, rd);
856 gen_op_bicl_T0_T1();
857 gen_op_iwmmxt_movl_wCx_T0(wrd);
858 break;
859 case ARM_IWMMXT_wCGR0:
860 case ARM_IWMMXT_wCGR1:
861 case ARM_IWMMXT_wCGR2:
862 case ARM_IWMMXT_wCGR3:
863 gen_op_iwmmxt_set_cup();
864 gen_movl_reg_T0(s, rd);
865 gen_op_iwmmxt_movl_wCx_T0(wrd);
866 break;
867 default:
868 return 1;
869 }
870 break;
871 case 0x100: /* WXOR */
872 wrd = (insn >> 12) & 0xf;
873 rd0 = (insn >> 0) & 0xf;
874 rd1 = (insn >> 16) & 0xf;
875 gen_op_iwmmxt_movq_M0_wRn(rd0);
876 gen_op_iwmmxt_xorq_M0_wRn(rd1);
877 gen_op_iwmmxt_setpsr_nz();
878 gen_op_iwmmxt_movq_wRn_M0(wrd);
879 gen_op_iwmmxt_set_mup();
880 gen_op_iwmmxt_set_cup();
881 break;
882 case 0x111: /* TMRC */
883 if (insn & 0xf)
884 return 1;
885 rd = (insn >> 12) & 0xf;
886 wrd = (insn >> 16) & 0xf;
887 gen_op_iwmmxt_movl_T0_wCx(wrd);
888 gen_movl_reg_T0(s, rd);
889 break;
890 case 0x300: /* WANDN */
891 wrd = (insn >> 12) & 0xf;
892 rd0 = (insn >> 0) & 0xf;
893 rd1 = (insn >> 16) & 0xf;
894 gen_op_iwmmxt_movq_M0_wRn(rd0);
895 gen_op_iwmmxt_negq_M0();
896 gen_op_iwmmxt_andq_M0_wRn(rd1);
897 gen_op_iwmmxt_setpsr_nz();
898 gen_op_iwmmxt_movq_wRn_M0(wrd);
899 gen_op_iwmmxt_set_mup();
900 gen_op_iwmmxt_set_cup();
901 break;
902 case 0x200: /* WAND */
903 wrd = (insn >> 12) & 0xf;
904 rd0 = (insn >> 0) & 0xf;
905 rd1 = (insn >> 16) & 0xf;
906 gen_op_iwmmxt_movq_M0_wRn(rd0);
907 gen_op_iwmmxt_andq_M0_wRn(rd1);
908 gen_op_iwmmxt_setpsr_nz();
909 gen_op_iwmmxt_movq_wRn_M0(wrd);
910 gen_op_iwmmxt_set_mup();
911 gen_op_iwmmxt_set_cup();
912 break;
913 case 0x810: case 0xa10: /* WMADD */
914 wrd = (insn >> 12) & 0xf;
915 rd0 = (insn >> 0) & 0xf;
916 rd1 = (insn >> 16) & 0xf;
917 gen_op_iwmmxt_movq_M0_wRn(rd0);
918 if (insn & (1 << 21))
919 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
920 else
921 gen_op_iwmmxt_madduq_M0_wRn(rd1);
922 gen_op_iwmmxt_movq_wRn_M0(wrd);
923 gen_op_iwmmxt_set_mup();
924 break;
925 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
926 wrd = (insn >> 12) & 0xf;
927 rd0 = (insn >> 16) & 0xf;
928 rd1 = (insn >> 0) & 0xf;
929 gen_op_iwmmxt_movq_M0_wRn(rd0);
930 switch ((insn >> 22) & 3) {
931 case 0:
932 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
933 break;
934 case 1:
935 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
936 break;
937 case 2:
938 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
939 break;
940 case 3:
941 return 1;
942 }
943 gen_op_iwmmxt_movq_wRn_M0(wrd);
944 gen_op_iwmmxt_set_mup();
945 gen_op_iwmmxt_set_cup();
946 break;
947 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
948 wrd = (insn >> 12) & 0xf;
949 rd0 = (insn >> 16) & 0xf;
950 rd1 = (insn >> 0) & 0xf;
951 gen_op_iwmmxt_movq_M0_wRn(rd0);
952 switch ((insn >> 22) & 3) {
953 case 0:
954 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
955 break;
956 case 1:
957 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
958 break;
959 case 2:
960 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
961 break;
962 case 3:
963 return 1;
964 }
965 gen_op_iwmmxt_movq_wRn_M0(wrd);
966 gen_op_iwmmxt_set_mup();
967 gen_op_iwmmxt_set_cup();
968 break;
969 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
970 wrd = (insn >> 12) & 0xf;
971 rd0 = (insn >> 16) & 0xf;
972 rd1 = (insn >> 0) & 0xf;
973 gen_op_iwmmxt_movq_M0_wRn(rd0);
974 if (insn & (1 << 22))
975 gen_op_iwmmxt_sadw_M0_wRn(rd1);
976 else
977 gen_op_iwmmxt_sadb_M0_wRn(rd1);
978 if (!(insn & (1 << 20)))
979 gen_op_iwmmxt_addl_M0_wRn(wrd);
980 gen_op_iwmmxt_movq_wRn_M0(wrd);
981 gen_op_iwmmxt_set_mup();
982 break;
983 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
984 wrd = (insn >> 12) & 0xf;
985 rd0 = (insn >> 16) & 0xf;
986 rd1 = (insn >> 0) & 0xf;
987 gen_op_iwmmxt_movq_M0_wRn(rd0);
988 if (insn & (1 << 21))
989 gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
990 else
991 gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
992 gen_op_iwmmxt_movq_wRn_M0(wrd);
993 gen_op_iwmmxt_set_mup();
994 break;
995 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
996 wrd = (insn >> 12) & 0xf;
997 rd0 = (insn >> 16) & 0xf;
998 rd1 = (insn >> 0) & 0xf;
999 gen_op_iwmmxt_movq_M0_wRn(rd0);
1000 if (insn & (1 << 21))
1001 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1002 else
1003 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1004 if (!(insn & (1 << 20))) {
1005 if (insn & (1 << 21))
1006 gen_op_iwmmxt_addsq_M0_wRn(wrd);
1007 else
1008 gen_op_iwmmxt_adduq_M0_wRn(wrd);
1009 }
1010 gen_op_iwmmxt_movq_wRn_M0(wrd);
1011 gen_op_iwmmxt_set_mup();
1012 break;
1013 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1014 wrd = (insn >> 12) & 0xf;
1015 rd0 = (insn >> 16) & 0xf;
1016 rd1 = (insn >> 0) & 0xf;
1017 gen_op_iwmmxt_movq_M0_wRn(rd0);
1018 switch ((insn >> 22) & 3) {
1019 case 0:
1020 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1021 break;
1022 case 1:
1023 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1024 break;
1025 case 2:
1026 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1027 break;
1028 case 3:
1029 return 1;
1030 }
1031 gen_op_iwmmxt_movq_wRn_M0(wrd);
1032 gen_op_iwmmxt_set_mup();
1033 gen_op_iwmmxt_set_cup();
1034 break;
1035 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1036 wrd = (insn >> 12) & 0xf;
1037 rd0 = (insn >> 16) & 0xf;
1038 rd1 = (insn >> 0) & 0xf;
1039 gen_op_iwmmxt_movq_M0_wRn(rd0);
1040 if (insn & (1 << 22))
1041 gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
1042 else
1043 gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
1044 gen_op_iwmmxt_movq_wRn_M0(wrd);
1045 gen_op_iwmmxt_set_mup();
1046 gen_op_iwmmxt_set_cup();
1047 break;
1048 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1049 wrd = (insn >> 12) & 0xf;
1050 rd0 = (insn >> 16) & 0xf;
1051 rd1 = (insn >> 0) & 0xf;
1052 gen_op_iwmmxt_movq_M0_wRn(rd0);
1053 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1054 gen_op_movl_T1_im(7);
1055 gen_op_andl_T0_T1();
1056 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1057 gen_op_iwmmxt_movq_wRn_M0(wrd);
1058 gen_op_iwmmxt_set_mup();
1059 break;
1060 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1061 rd = (insn >> 12) & 0xf;
1062 wrd = (insn >> 16) & 0xf;
1063 gen_movl_T0_reg(s, rd);
1064 gen_op_iwmmxt_movq_M0_wRn(wrd);
1065 switch ((insn >> 6) & 3) {
1066 case 0:
1067 gen_op_movl_T1_im(0xff);
1068 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1069 break;
1070 case 1:
1071 gen_op_movl_T1_im(0xffff);
1072 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1073 break;
1074 case 2:
1075 gen_op_movl_T1_im(0xffffffff);
1076 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1077 break;
1078 case 3:
1079 return 1;
1080 }
1081 gen_op_iwmmxt_movq_wRn_M0(wrd);
1082 gen_op_iwmmxt_set_mup();
1083 break;
1084 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1085 rd = (insn >> 12) & 0xf;
1086 wrd = (insn >> 16) & 0xf;
1087 if (rd == 15)
1088 return 1;
1089 gen_op_iwmmxt_movq_M0_wRn(wrd);
1090 switch ((insn >> 22) & 3) {
1091 case 0:
1092 if (insn & 8)
1093 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1094 else {
1095 gen_op_movl_T1_im(0xff);
1096 gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
1097 }
1098 break;
1099 case 1:
1100 if (insn & 8)
1101 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1102 else {
1103 gen_op_movl_T1_im(0xffff);
1104 gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
1105 }
1106 break;
1107 case 2:
1108 gen_op_movl_T1_im(0xffffffff);
1109 gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
1110 break;
1111 case 3:
1112 return 1;
1113 }
b26eefb6 1114 gen_movl_reg_T0(s, rd);
18c9b560
AZ
1115 break;
1116 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1117 if ((insn & 0x000ff008) != 0x0003f000)
1118 return 1;
1119 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1120 switch ((insn >> 22) & 3) {
1121 case 0:
1122 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1123 break;
1124 case 1:
1125 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1126 break;
1127 case 2:
1128 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1129 break;
1130 case 3:
1131 return 1;
1132 }
1133 gen_op_shll_T1_im(28);
1134 gen_op_movl_T0_T1();
1135 gen_op_movl_cpsr_T0(0xf0000000);
1136 break;
1137 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1138 rd = (insn >> 12) & 0xf;
1139 wrd = (insn >> 16) & 0xf;
1140 gen_movl_T0_reg(s, rd);
1141 switch ((insn >> 6) & 3) {
1142 case 0:
1143 gen_op_iwmmxt_bcstb_M0_T0();
1144 break;
1145 case 1:
1146 gen_op_iwmmxt_bcstw_M0_T0();
1147 break;
1148 case 2:
1149 gen_op_iwmmxt_bcstl_M0_T0();
1150 break;
1151 case 3:
1152 return 1;
1153 }
1154 gen_op_iwmmxt_movq_wRn_M0(wrd);
1155 gen_op_iwmmxt_set_mup();
1156 break;
1157 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1158 if ((insn & 0x000ff00f) != 0x0003f000)
1159 return 1;
1160 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1161 switch ((insn >> 22) & 3) {
1162 case 0:
1163 for (i = 0; i < 7; i ++) {
1164 gen_op_shll_T1_im(4);
1165 gen_op_andl_T0_T1();
1166 }
1167 break;
1168 case 1:
1169 for (i = 0; i < 3; i ++) {
1170 gen_op_shll_T1_im(8);
1171 gen_op_andl_T0_T1();
1172 }
1173 break;
1174 case 2:
1175 gen_op_shll_T1_im(16);
1176 gen_op_andl_T0_T1();
1177 break;
1178 case 3:
1179 return 1;
1180 }
1181 gen_op_movl_cpsr_T0(0xf0000000);
1182 break;
1183 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1184 wrd = (insn >> 12) & 0xf;
1185 rd0 = (insn >> 16) & 0xf;
1186 gen_op_iwmmxt_movq_M0_wRn(rd0);
1187 switch ((insn >> 22) & 3) {
1188 case 0:
1189 gen_op_iwmmxt_addcb_M0();
1190 break;
1191 case 1:
1192 gen_op_iwmmxt_addcw_M0();
1193 break;
1194 case 2:
1195 gen_op_iwmmxt_addcl_M0();
1196 break;
1197 case 3:
1198 return 1;
1199 }
1200 gen_op_iwmmxt_movq_wRn_M0(wrd);
1201 gen_op_iwmmxt_set_mup();
1202 break;
1203 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1204 if ((insn & 0x000ff00f) != 0x0003f000)
1205 return 1;
1206 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1207 switch ((insn >> 22) & 3) {
1208 case 0:
1209 for (i = 0; i < 7; i ++) {
1210 gen_op_shll_T1_im(4);
1211 gen_op_orl_T0_T1();
1212 }
1213 break;
1214 case 1:
1215 for (i = 0; i < 3; i ++) {
1216 gen_op_shll_T1_im(8);
1217 gen_op_orl_T0_T1();
1218 }
1219 break;
1220 case 2:
1221 gen_op_shll_T1_im(16);
1222 gen_op_orl_T0_T1();
1223 break;
1224 case 3:
1225 return 1;
1226 }
1227 gen_op_movl_T1_im(0xf0000000);
1228 gen_op_andl_T0_T1();
1229 gen_op_movl_cpsr_T0(0xf0000000);
1230 break;
1231 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1232 rd = (insn >> 12) & 0xf;
1233 rd0 = (insn >> 16) & 0xf;
1234 if ((insn & 0xf) != 0)
1235 return 1;
1236 gen_op_iwmmxt_movq_M0_wRn(rd0);
1237 switch ((insn >> 22) & 3) {
1238 case 0:
1239 gen_op_iwmmxt_msbb_T0_M0();
1240 break;
1241 case 1:
1242 gen_op_iwmmxt_msbw_T0_M0();
1243 break;
1244 case 2:
1245 gen_op_iwmmxt_msbl_T0_M0();
1246 break;
1247 case 3:
1248 return 1;
1249 }
1250 gen_movl_reg_T0(s, rd);
1251 break;
1252 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1253 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1254 wrd = (insn >> 12) & 0xf;
1255 rd0 = (insn >> 16) & 0xf;
1256 rd1 = (insn >> 0) & 0xf;
1257 gen_op_iwmmxt_movq_M0_wRn(rd0);
1258 switch ((insn >> 22) & 3) {
1259 case 0:
1260 if (insn & (1 << 21))
1261 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1262 else
1263 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1264 break;
1265 case 1:
1266 if (insn & (1 << 21))
1267 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1268 else
1269 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1270 break;
1271 case 2:
1272 if (insn & (1 << 21))
1273 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1274 else
1275 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1276 break;
1277 case 3:
1278 return 1;
1279 }
1280 gen_op_iwmmxt_movq_wRn_M0(wrd);
1281 gen_op_iwmmxt_set_mup();
1282 gen_op_iwmmxt_set_cup();
1283 break;
1284 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1285 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1286 wrd = (insn >> 12) & 0xf;
1287 rd0 = (insn >> 16) & 0xf;
1288 gen_op_iwmmxt_movq_M0_wRn(rd0);
1289 switch ((insn >> 22) & 3) {
1290 case 0:
1291 if (insn & (1 << 21))
1292 gen_op_iwmmxt_unpacklsb_M0();
1293 else
1294 gen_op_iwmmxt_unpacklub_M0();
1295 break;
1296 case 1:
1297 if (insn & (1 << 21))
1298 gen_op_iwmmxt_unpacklsw_M0();
1299 else
1300 gen_op_iwmmxt_unpackluw_M0();
1301 break;
1302 case 2:
1303 if (insn & (1 << 21))
1304 gen_op_iwmmxt_unpacklsl_M0();
1305 else
1306 gen_op_iwmmxt_unpacklul_M0();
1307 break;
1308 case 3:
1309 return 1;
1310 }
1311 gen_op_iwmmxt_movq_wRn_M0(wrd);
1312 gen_op_iwmmxt_set_mup();
1313 gen_op_iwmmxt_set_cup();
1314 break;
1315 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1316 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1317 wrd = (insn >> 12) & 0xf;
1318 rd0 = (insn >> 16) & 0xf;
1319 gen_op_iwmmxt_movq_M0_wRn(rd0);
1320 switch ((insn >> 22) & 3) {
1321 case 0:
1322 if (insn & (1 << 21))
1323 gen_op_iwmmxt_unpackhsb_M0();
1324 else
1325 gen_op_iwmmxt_unpackhub_M0();
1326 break;
1327 case 1:
1328 if (insn & (1 << 21))
1329 gen_op_iwmmxt_unpackhsw_M0();
1330 else
1331 gen_op_iwmmxt_unpackhuw_M0();
1332 break;
1333 case 2:
1334 if (insn & (1 << 21))
1335 gen_op_iwmmxt_unpackhsl_M0();
1336 else
1337 gen_op_iwmmxt_unpackhul_M0();
1338 break;
1339 case 3:
1340 return 1;
1341 }
1342 gen_op_iwmmxt_movq_wRn_M0(wrd);
1343 gen_op_iwmmxt_set_mup();
1344 gen_op_iwmmxt_set_cup();
1345 break;
1346 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1347 case 0x214: case 0x614: case 0xa14: case 0xe14:
1348 wrd = (insn >> 12) & 0xf;
1349 rd0 = (insn >> 16) & 0xf;
1350 gen_op_iwmmxt_movq_M0_wRn(rd0);
1351 if (gen_iwmmxt_shift(insn, 0xff))
1352 return 1;
1353 switch ((insn >> 22) & 3) {
1354 case 0:
1355 return 1;
1356 case 1:
1357 gen_op_iwmmxt_srlw_M0_T0();
1358 break;
1359 case 2:
1360 gen_op_iwmmxt_srll_M0_T0();
1361 break;
1362 case 3:
1363 gen_op_iwmmxt_srlq_M0_T0();
1364 break;
1365 }
1366 gen_op_iwmmxt_movq_wRn_M0(wrd);
1367 gen_op_iwmmxt_set_mup();
1368 gen_op_iwmmxt_set_cup();
1369 break;
1370 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1371 case 0x014: case 0x414: case 0x814: case 0xc14:
1372 wrd = (insn >> 12) & 0xf;
1373 rd0 = (insn >> 16) & 0xf;
1374 gen_op_iwmmxt_movq_M0_wRn(rd0);
1375 if (gen_iwmmxt_shift(insn, 0xff))
1376 return 1;
1377 switch ((insn >> 22) & 3) {
1378 case 0:
1379 return 1;
1380 case 1:
1381 gen_op_iwmmxt_sraw_M0_T0();
1382 break;
1383 case 2:
1384 gen_op_iwmmxt_sral_M0_T0();
1385 break;
1386 case 3:
1387 gen_op_iwmmxt_sraq_M0_T0();
1388 break;
1389 }
1390 gen_op_iwmmxt_movq_wRn_M0(wrd);
1391 gen_op_iwmmxt_set_mup();
1392 gen_op_iwmmxt_set_cup();
1393 break;
1394 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
1395 case 0x114: case 0x514: case 0x914: case 0xd14:
1396 wrd = (insn >> 12) & 0xf;
1397 rd0 = (insn >> 16) & 0xf;
1398 gen_op_iwmmxt_movq_M0_wRn(rd0);
1399 if (gen_iwmmxt_shift(insn, 0xff))
1400 return 1;
1401 switch ((insn >> 22) & 3) {
1402 case 0:
1403 return 1;
1404 case 1:
1405 gen_op_iwmmxt_sllw_M0_T0();
1406 break;
1407 case 2:
1408 gen_op_iwmmxt_slll_M0_T0();
1409 break;
1410 case 3:
1411 gen_op_iwmmxt_sllq_M0_T0();
1412 break;
1413 }
1414 gen_op_iwmmxt_movq_wRn_M0(wrd);
1415 gen_op_iwmmxt_set_mup();
1416 gen_op_iwmmxt_set_cup();
1417 break;
1418 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
1419 case 0x314: case 0x714: case 0xb14: case 0xf14:
1420 wrd = (insn >> 12) & 0xf;
1421 rd0 = (insn >> 16) & 0xf;
1422 gen_op_iwmmxt_movq_M0_wRn(rd0);
1423 switch ((insn >> 22) & 3) {
1424 case 0:
1425 return 1;
1426 case 1:
1427 if (gen_iwmmxt_shift(insn, 0xf))
1428 return 1;
1429 gen_op_iwmmxt_rorw_M0_T0();
1430 break;
1431 case 2:
1432 if (gen_iwmmxt_shift(insn, 0x1f))
1433 return 1;
1434 gen_op_iwmmxt_rorl_M0_T0();
1435 break;
1436 case 3:
1437 if (gen_iwmmxt_shift(insn, 0x3f))
1438 return 1;
1439 gen_op_iwmmxt_rorq_M0_T0();
1440 break;
1441 }
1442 gen_op_iwmmxt_movq_wRn_M0(wrd);
1443 gen_op_iwmmxt_set_mup();
1444 gen_op_iwmmxt_set_cup();
1445 break;
1446 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
1447 case 0x916: case 0xb16: case 0xd16: case 0xf16:
1448 wrd = (insn >> 12) & 0xf;
1449 rd0 = (insn >> 16) & 0xf;
1450 rd1 = (insn >> 0) & 0xf;
1451 gen_op_iwmmxt_movq_M0_wRn(rd0);
1452 switch ((insn >> 22) & 3) {
1453 case 0:
1454 if (insn & (1 << 21))
1455 gen_op_iwmmxt_minsb_M0_wRn(rd1);
1456 else
1457 gen_op_iwmmxt_minub_M0_wRn(rd1);
1458 break;
1459 case 1:
1460 if (insn & (1 << 21))
1461 gen_op_iwmmxt_minsw_M0_wRn(rd1);
1462 else
1463 gen_op_iwmmxt_minuw_M0_wRn(rd1);
1464 break;
1465 case 2:
1466 if (insn & (1 << 21))
1467 gen_op_iwmmxt_minsl_M0_wRn(rd1);
1468 else
1469 gen_op_iwmmxt_minul_M0_wRn(rd1);
1470 break;
1471 case 3:
1472 return 1;
1473 }
1474 gen_op_iwmmxt_movq_wRn_M0(wrd);
1475 gen_op_iwmmxt_set_mup();
1476 break;
1477 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
1478 case 0x816: case 0xa16: case 0xc16: case 0xe16:
1479 wrd = (insn >> 12) & 0xf;
1480 rd0 = (insn >> 16) & 0xf;
1481 rd1 = (insn >> 0) & 0xf;
1482 gen_op_iwmmxt_movq_M0_wRn(rd0);
1483 switch ((insn >> 22) & 3) {
1484 case 0:
1485 if (insn & (1 << 21))
1486 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1487 else
1488 gen_op_iwmmxt_maxub_M0_wRn(rd1);
1489 break;
1490 case 1:
1491 if (insn & (1 << 21))
1492 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1493 else
1494 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1495 break;
1496 case 2:
1497 if (insn & (1 << 21))
1498 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1499 else
1500 gen_op_iwmmxt_maxul_M0_wRn(rd1);
1501 break;
1502 case 3:
1503 return 1;
1504 }
1505 gen_op_iwmmxt_movq_wRn_M0(wrd);
1506 gen_op_iwmmxt_set_mup();
1507 break;
1508 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
1509 case 0x402: case 0x502: case 0x602: case 0x702:
1510 wrd = (insn >> 12) & 0xf;
1511 rd0 = (insn >> 16) & 0xf;
1512 rd1 = (insn >> 0) & 0xf;
1513 gen_op_iwmmxt_movq_M0_wRn(rd0);
1514 gen_op_movl_T0_im((insn >> 20) & 3);
1515 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1516 gen_op_iwmmxt_movq_wRn_M0(wrd);
1517 gen_op_iwmmxt_set_mup();
1518 break;
1519 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
1520 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1521 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1522 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1523 wrd = (insn >> 12) & 0xf;
1524 rd0 = (insn >> 16) & 0xf;
1525 rd1 = (insn >> 0) & 0xf;
1526 gen_op_iwmmxt_movq_M0_wRn(rd0);
1527 switch ((insn >> 20) & 0xf) {
1528 case 0x0:
1529 gen_op_iwmmxt_subnb_M0_wRn(rd1);
1530 break;
1531 case 0x1:
1532 gen_op_iwmmxt_subub_M0_wRn(rd1);
1533 break;
1534 case 0x3:
1535 gen_op_iwmmxt_subsb_M0_wRn(rd1);
1536 break;
1537 case 0x4:
1538 gen_op_iwmmxt_subnw_M0_wRn(rd1);
1539 break;
1540 case 0x5:
1541 gen_op_iwmmxt_subuw_M0_wRn(rd1);
1542 break;
1543 case 0x7:
1544 gen_op_iwmmxt_subsw_M0_wRn(rd1);
1545 break;
1546 case 0x8:
1547 gen_op_iwmmxt_subnl_M0_wRn(rd1);
1548 break;
1549 case 0x9:
1550 gen_op_iwmmxt_subul_M0_wRn(rd1);
1551 break;
1552 case 0xb:
1553 gen_op_iwmmxt_subsl_M0_wRn(rd1);
1554 break;
1555 default:
1556 return 1;
1557 }
1558 gen_op_iwmmxt_movq_wRn_M0(wrd);
1559 gen_op_iwmmxt_set_mup();
1560 gen_op_iwmmxt_set_cup();
1561 break;
1562 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
1563 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1564 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1565 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1566 wrd = (insn >> 12) & 0xf;
1567 rd0 = (insn >> 16) & 0xf;
1568 gen_op_iwmmxt_movq_M0_wRn(rd0);
1569 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
1570 gen_op_iwmmxt_shufh_M0_T0();
1571 gen_op_iwmmxt_movq_wRn_M0(wrd);
1572 gen_op_iwmmxt_set_mup();
1573 gen_op_iwmmxt_set_cup();
1574 break;
1575 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
1576 case 0x418: case 0x518: case 0x618: case 0x718:
1577 case 0x818: case 0x918: case 0xa18: case 0xb18:
1578 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1579 wrd = (insn >> 12) & 0xf;
1580 rd0 = (insn >> 16) & 0xf;
1581 rd1 = (insn >> 0) & 0xf;
1582 gen_op_iwmmxt_movq_M0_wRn(rd0);
1583 switch ((insn >> 20) & 0xf) {
1584 case 0x0:
1585 gen_op_iwmmxt_addnb_M0_wRn(rd1);
1586 break;
1587 case 0x1:
1588 gen_op_iwmmxt_addub_M0_wRn(rd1);
1589 break;
1590 case 0x3:
1591 gen_op_iwmmxt_addsb_M0_wRn(rd1);
1592 break;
1593 case 0x4:
1594 gen_op_iwmmxt_addnw_M0_wRn(rd1);
1595 break;
1596 case 0x5:
1597 gen_op_iwmmxt_adduw_M0_wRn(rd1);
1598 break;
1599 case 0x7:
1600 gen_op_iwmmxt_addsw_M0_wRn(rd1);
1601 break;
1602 case 0x8:
1603 gen_op_iwmmxt_addnl_M0_wRn(rd1);
1604 break;
1605 case 0x9:
1606 gen_op_iwmmxt_addul_M0_wRn(rd1);
1607 break;
1608 case 0xb:
1609 gen_op_iwmmxt_addsl_M0_wRn(rd1);
1610 break;
1611 default:
1612 return 1;
1613 }
1614 gen_op_iwmmxt_movq_wRn_M0(wrd);
1615 gen_op_iwmmxt_set_mup();
1616 gen_op_iwmmxt_set_cup();
1617 break;
1618 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
1619 case 0x408: case 0x508: case 0x608: case 0x708:
1620 case 0x808: case 0x908: case 0xa08: case 0xb08:
1621 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1622 wrd = (insn >> 12) & 0xf;
1623 rd0 = (insn >> 16) & 0xf;
1624 rd1 = (insn >> 0) & 0xf;
1625 gen_op_iwmmxt_movq_M0_wRn(rd0);
1626 if (!(insn & (1 << 20)))
1627 return 1;
1628 switch ((insn >> 22) & 3) {
1629 case 0:
1630 return 1;
1631 case 1:
1632 if (insn & (1 << 21))
1633 gen_op_iwmmxt_packsw_M0_wRn(rd1);
1634 else
1635 gen_op_iwmmxt_packuw_M0_wRn(rd1);
1636 break;
1637 case 2:
1638 if (insn & (1 << 21))
1639 gen_op_iwmmxt_packsl_M0_wRn(rd1);
1640 else
1641 gen_op_iwmmxt_packul_M0_wRn(rd1);
1642 break;
1643 case 3:
1644 if (insn & (1 << 21))
1645 gen_op_iwmmxt_packsq_M0_wRn(rd1);
1646 else
1647 gen_op_iwmmxt_packuq_M0_wRn(rd1);
1648 break;
1649 }
1650 gen_op_iwmmxt_movq_wRn_M0(wrd);
1651 gen_op_iwmmxt_set_mup();
1652 gen_op_iwmmxt_set_cup();
1653 break;
1654 case 0x201: case 0x203: case 0x205: case 0x207:
1655 case 0x209: case 0x20b: case 0x20d: case 0x20f:
1656 case 0x211: case 0x213: case 0x215: case 0x217:
1657 case 0x219: case 0x21b: case 0x21d: case 0x21f:
1658 wrd = (insn >> 5) & 0xf;
1659 rd0 = (insn >> 12) & 0xf;
1660 rd1 = (insn >> 0) & 0xf;
1661 if (rd0 == 0xf || rd1 == 0xf)
1662 return 1;
1663 gen_op_iwmmxt_movq_M0_wRn(wrd);
1664 switch ((insn >> 16) & 0xf) {
1665 case 0x0: /* TMIA */
b26eefb6
PB
1666 gen_movl_T0_reg(s, rd0);
1667 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1668 gen_op_iwmmxt_muladdsl_M0_T0_T1();
1669 break;
1670 case 0x8: /* TMIAPH */
b26eefb6
PB
1671 gen_movl_T0_reg(s, rd0);
1672 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1673 gen_op_iwmmxt_muladdsw_M0_T0_T1();
1674 break;
1675 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
b26eefb6 1676 gen_movl_T1_reg(s, rd0);
18c9b560
AZ
1677 if (insn & (1 << 16))
1678 gen_op_shrl_T1_im(16);
1679 gen_op_movl_T0_T1();
b26eefb6 1680 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1681 if (insn & (1 << 17))
1682 gen_op_shrl_T1_im(16);
1683 gen_op_iwmmxt_muladdswl_M0_T0_T1();
1684 break;
1685 default:
1686 return 1;
1687 }
1688 gen_op_iwmmxt_movq_wRn_M0(wrd);
1689 gen_op_iwmmxt_set_mup();
1690 break;
1691 default:
1692 return 1;
1693 }
1694
1695 return 0;
1696}
1697
1698/* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
1699 (ie. an undefined instruction). */
1700static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1701{
1702 int acc, rd0, rd1, rdhi, rdlo;
1703
1704 if ((insn & 0x0ff00f10) == 0x0e200010) {
1705 /* Multiply with Internal Accumulate Format */
1706 rd0 = (insn >> 12) & 0xf;
1707 rd1 = insn & 0xf;
1708 acc = (insn >> 5) & 7;
1709
1710 if (acc != 0)
1711 return 1;
1712
1713 switch ((insn >> 16) & 0xf) {
1714 case 0x0: /* MIA */
b26eefb6
PB
1715 gen_movl_T0_reg(s, rd0);
1716 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1717 gen_op_iwmmxt_muladdsl_M0_T0_T1();
1718 break;
1719 case 0x8: /* MIAPH */
b26eefb6
PB
1720 gen_movl_T0_reg(s, rd0);
1721 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1722 gen_op_iwmmxt_muladdsw_M0_T0_T1();
1723 break;
1724 case 0xc: /* MIABB */
1725 case 0xd: /* MIABT */
1726 case 0xe: /* MIATB */
1727 case 0xf: /* MIATT */
b26eefb6 1728 gen_movl_T1_reg(s, rd0);
18c9b560
AZ
1729 if (insn & (1 << 16))
1730 gen_op_shrl_T1_im(16);
1731 gen_op_movl_T0_T1();
b26eefb6 1732 gen_movl_T1_reg(s, rd1);
18c9b560
AZ
1733 if (insn & (1 << 17))
1734 gen_op_shrl_T1_im(16);
1735 gen_op_iwmmxt_muladdswl_M0_T0_T1();
1736 break;
1737 default:
1738 return 1;
1739 }
1740
1741 gen_op_iwmmxt_movq_wRn_M0(acc);
1742 return 0;
1743 }
1744
1745 if ((insn & 0x0fe00ff8) == 0x0c400000) {
1746 /* Internal Accumulator Access Format */
1747 rdhi = (insn >> 16) & 0xf;
1748 rdlo = (insn >> 12) & 0xf;
1749 acc = insn & 7;
1750
1751 if (acc != 0)
1752 return 1;
1753
1754 if (insn & ARM_CP_RW_BIT) { /* MRA */
1755 gen_op_iwmmxt_movl_T0_T1_wRn(acc);
b26eefb6 1756 gen_movl_reg_T0(s, rdlo);
18c9b560
AZ
1757 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1758 gen_op_andl_T0_T1();
b26eefb6 1759 gen_movl_reg_T0(s, rdhi);
18c9b560 1760 } else { /* MAR */
b26eefb6
PB
1761 gen_movl_T0_reg(s, rdlo);
1762 gen_movl_T1_reg(s, rdhi);
18c9b560
AZ
1763 gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1764 }
1765 return 0;
1766 }
1767
1768 return 1;
1769}
1770
c1713132
AZ
1771/* Disassemble system coprocessor instruction. Return nonzero if
1772 instruction is not defined. */
1773static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1774{
1775 uint32_t rd = (insn >> 12) & 0xf;
1776 uint32_t cp = (insn >> 8) & 0xf;
1777 if (IS_USER(s)) {
1778 return 1;
1779 }
1780
18c9b560 1781 if (insn & ARM_CP_RW_BIT) {
c1713132
AZ
1782 if (!env->cp[cp].cp_read)
1783 return 1;
1784 gen_op_movl_T0_im((uint32_t) s->pc);
b26eefb6 1785 gen_set_pc_T0();
c1713132
AZ
1786 gen_op_movl_T0_cp(insn);
1787 gen_movl_reg_T0(s, rd);
1788 } else {
1789 if (!env->cp[cp].cp_write)
1790 return 1;
1791 gen_op_movl_T0_im((uint32_t) s->pc);
b26eefb6 1792 gen_set_pc_T0();
c1713132
AZ
1793 gen_movl_T0_reg(s, rd);
1794 gen_op_movl_cp_T0(insn);
1795 }
1796 return 0;
1797}
1798
9ee6e8bb
PB
1799static int cp15_user_ok(uint32_t insn)
1800{
1801 int cpn = (insn >> 16) & 0xf;
1802 int cpm = insn & 0xf;
1803 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1804
1805 if (cpn == 13 && cpm == 0) {
1806 /* TLS register. */
1807 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1808 return 1;
1809 }
1810 if (cpn == 7) {
1811 /* ISB, DSB, DMB. */
1812 if ((cpm == 5 && op == 4)
1813 || (cpm == 10 && (op == 4 || op == 5)))
1814 return 1;
1815 }
1816 return 0;
1817}
1818
b5ff1b31
FB
1819/* Disassemble system coprocessor (cp15) instruction. Return nonzero if
1820 instruction is not defined. */
a90b7318 1821static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
b5ff1b31
FB
1822{
1823 uint32_t rd;
1824
9ee6e8bb
PB
1825 /* M profile cores use memory mapped registers instead of cp15. */
1826 if (arm_feature(env, ARM_FEATURE_M))
1827 return 1;
1828
1829 if ((insn & (1 << 25)) == 0) {
1830 if (insn & (1 << 20)) {
1831 /* mrrc */
1832 return 1;
1833 }
1834 /* mcrr. Used for block cache operations, so implement as no-op. */
1835 return 0;
1836 }
1837 if ((insn & (1 << 4)) == 0) {
1838 /* cdp */
1839 return 1;
1840 }
1841 if (IS_USER(s) && !cp15_user_ok(insn)) {
b5ff1b31
FB
1842 return 1;
1843 }
9332f9da
FB
1844 if ((insn & 0x0fff0fff) == 0x0e070f90
1845 || (insn & 0x0fff0fff) == 0x0e070f58) {
1846 /* Wait for interrupt. */
1847 gen_op_movl_T0_im((long)s->pc);
b26eefb6 1848 gen_set_pc_T0();
9ee6e8bb 1849 s->is_jmp = DISAS_WFI;
9332f9da
FB
1850 return 0;
1851 }
b5ff1b31 1852 rd = (insn >> 12) & 0xf;
18c9b560 1853 if (insn & ARM_CP_RW_BIT) {
b5ff1b31
FB
1854 gen_op_movl_T0_cp15(insn);
1855 /* If the destination register is r15 then sets condition codes. */
1856 if (rd != 15)
1857 gen_movl_reg_T0(s, rd);
1858 } else {
1859 gen_movl_T0_reg(s, rd);
1860 gen_op_movl_cp15_T0(insn);
a90b7318
AZ
1861 /* Normally we would always end the TB here, but Linux
1862 * arch/arm/mach-pxa/sleep.S expects two instructions following
1863 * an MMU enable to execute from cache. Imitate this behaviour. */
1864 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
1865 (insn & 0x0fff0fff) != 0x0e010f10)
1866 gen_lookup_tb(s);
b5ff1b31 1867 }
b5ff1b31
FB
1868 return 0;
1869}
1870
9ee6e8bb
PB
1871#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
1872#define VFP_SREG(insn, bigbit, smallbit) \
1873 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
1874#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
1875 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
1876 reg = (((insn) >> (bigbit)) & 0x0f) \
1877 | (((insn) >> ((smallbit) - 4)) & 0x10); \
1878 } else { \
1879 if (insn & (1 << (smallbit))) \
1880 return 1; \
1881 reg = ((insn) >> (bigbit)) & 0x0f; \
1882 }} while (0)
1883
1884#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
1885#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
1886#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
1887#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
1888#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
1889#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
1890
1891static inline int
1892vfp_enabled(CPUState * env)
1893{
1894 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
1895}
1896
b7bcbe95
FB
1897/* Disassemble a VFP instruction. Returns nonzero if an error occured
1898 (ie. an undefined instruction). */
1899static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
1900{
1901 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
1902 int dp, veclen;
1903
40f137e1
PB
1904 if (!arm_feature(env, ARM_FEATURE_VFP))
1905 return 1;
1906
9ee6e8bb
PB
1907 if (!vfp_enabled(env)) {
1908 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
1909 if ((insn & 0x0fe00fff) != 0x0ee00a10)
1910 return 1;
1911 rn = (insn >> 16) & 0xf;
9ee6e8bb
PB
1912 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
1913 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
40f137e1
PB
1914 return 1;
1915 }
b7bcbe95
FB
1916 dp = ((insn & 0xf00) == 0xb00);
1917 switch ((insn >> 24) & 0xf) {
1918 case 0xe:
1919 if (insn & (1 << 4)) {
1920 /* single register transfer */
b7bcbe95
FB
1921 rd = (insn >> 12) & 0xf;
1922 if (dp) {
9ee6e8bb
PB
1923 int size;
1924 int pass;
1925
1926 VFP_DREG_N(rn, insn);
1927 if (insn & 0xf)
b7bcbe95 1928 return 1;
9ee6e8bb
PB
1929 if (insn & 0x00c00060
1930 && !arm_feature(env, ARM_FEATURE_NEON))
1931 return 1;
1932
1933 pass = (insn >> 21) & 1;
1934 if (insn & (1 << 22)) {
1935 size = 0;
1936 offset = ((insn >> 5) & 3) * 8;
1937 } else if (insn & (1 << 5)) {
1938 size = 1;
1939 offset = (insn & (1 << 6)) ? 16 : 0;
1940 } else {
1941 size = 2;
1942 offset = 0;
1943 }
18c9b560 1944 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 1945 /* vfp->arm */
9ee6e8bb
PB
1946 switch (size) {
1947 case 0:
1948 NEON_GET_REG(T1, rn, pass);
1949 if (offset)
1950 gen_op_shrl_T1_im(offset);
1951 if (insn & (1 << 23))
b26eefb6 1952 gen_uxtb(cpu_T[1]);
9ee6e8bb 1953 else
b26eefb6 1954 gen_sxtb(cpu_T[1]);
9ee6e8bb
PB
1955 break;
1956 case 1:
1957 NEON_GET_REG(T1, rn, pass);
1958 if (insn & (1 << 23)) {
1959 if (offset) {
1960 gen_op_shrl_T1_im(16);
1961 } else {
b26eefb6 1962 gen_uxth(cpu_T[1]);
9ee6e8bb
PB
1963 }
1964 } else {
1965 if (offset) {
1966 gen_op_sarl_T1_im(16);
1967 } else {
b26eefb6 1968 gen_sxth(cpu_T[1]);
9ee6e8bb
PB
1969 }
1970 }
1971 break;
1972 case 2:
1973 NEON_GET_REG(T1, rn, pass);
1974 break;
1975 }
1976 gen_movl_reg_T1(s, rd);
b7bcbe95
FB
1977 } else {
1978 /* arm->vfp */
9ee6e8bb
PB
1979 gen_movl_T0_reg(s, rd);
1980 if (insn & (1 << 23)) {
1981 /* VDUP */
1982 if (size == 0) {
1983 gen_op_neon_dup_u8(0);
1984 } else if (size == 1) {
1985 gen_op_neon_dup_low16();
1986 }
1987 NEON_SET_REG(T0, rn, 0);
1988 NEON_SET_REG(T0, rn, 1);
1989 } else {
1990 /* VMOV */
1991 switch (size) {
1992 case 0:
1993 NEON_GET_REG(T2, rn, pass);
1994 gen_op_movl_T1_im(0xff);
1995 gen_op_andl_T0_T1();
1996 gen_op_neon_insert_elt(offset, ~(0xff << offset));
1997 NEON_SET_REG(T2, rn, pass);
1998 break;
1999 case 1:
2000 NEON_GET_REG(T2, rn, pass);
2001 gen_op_movl_T1_im(0xffff);
2002 gen_op_andl_T0_T1();
2003 bank_mask = offset ? 0xffff : 0xffff0000;
2004 gen_op_neon_insert_elt(offset, bank_mask);
2005 NEON_SET_REG(T2, rn, pass);
2006 break;
2007 case 2:
2008 NEON_SET_REG(T0, rn, pass);
2009 break;
2010 }
2011 }
b7bcbe95 2012 }
9ee6e8bb
PB
2013 } else { /* !dp */
2014 if ((insn & 0x6f) != 0x00)
2015 return 1;
2016 rn = VFP_SREG_N(insn);
18c9b560 2017 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
2018 /* vfp->arm */
2019 if (insn & (1 << 21)) {
2020 /* system register */
40f137e1 2021 rn >>= 1;
9ee6e8bb 2022
b7bcbe95 2023 switch (rn) {
40f137e1 2024 case ARM_VFP_FPSID:
9ee6e8bb
PB
2025 /* VFP2 allows access for FSID from userspace.
2026 VFP3 restricts all id registers to privileged
2027 accesses. */
2028 if (IS_USER(s)
2029 && arm_feature(env, ARM_FEATURE_VFP3))
2030 return 1;
2031 gen_op_vfp_movl_T0_xreg(rn);
2032 break;
40f137e1 2033 case ARM_VFP_FPEXC:
9ee6e8bb
PB
2034 if (IS_USER(s))
2035 return 1;
2036 gen_op_vfp_movl_T0_xreg(rn);
2037 break;
40f137e1
PB
2038 case ARM_VFP_FPINST:
2039 case ARM_VFP_FPINST2:
9ee6e8bb
PB
2040 /* Not present in VFP3. */
2041 if (IS_USER(s)
2042 || arm_feature(env, ARM_FEATURE_VFP3))
2043 return 1;
40f137e1 2044 gen_op_vfp_movl_T0_xreg(rn);
b7bcbe95 2045 break;
40f137e1 2046 case ARM_VFP_FPSCR:
b7bcbe95
FB
2047 if (rd == 15)
2048 gen_op_vfp_movl_T0_fpscr_flags();
2049 else
2050 gen_op_vfp_movl_T0_fpscr();
2051 break;
9ee6e8bb
PB
2052 case ARM_VFP_MVFR0:
2053 case ARM_VFP_MVFR1:
2054 if (IS_USER(s)
2055 || !arm_feature(env, ARM_FEATURE_VFP3))
2056 return 1;
2057 gen_op_vfp_movl_T0_xreg(rn);
2058 break;
b7bcbe95
FB
2059 default:
2060 return 1;
2061 }
2062 } else {
2063 gen_mov_F0_vreg(0, rn);
2064 gen_op_vfp_mrs();
2065 }
2066 if (rd == 15) {
b5ff1b31
FB
2067 /* Set the 4 flag bits in the CPSR. */
2068 gen_op_movl_cpsr_T0(0xf0000000);
b7bcbe95
FB
2069 } else
2070 gen_movl_reg_T0(s, rd);
2071 } else {
2072 /* arm->vfp */
2073 gen_movl_T0_reg(s, rd);
2074 if (insn & (1 << 21)) {
40f137e1 2075 rn >>= 1;
b7bcbe95
FB
2076 /* system register */
2077 switch (rn) {
40f137e1 2078 case ARM_VFP_FPSID:
9ee6e8bb
PB
2079 case ARM_VFP_MVFR0:
2080 case ARM_VFP_MVFR1:
b7bcbe95
FB
2081 /* Writes are ignored. */
2082 break;
40f137e1 2083 case ARM_VFP_FPSCR:
b7bcbe95 2084 gen_op_vfp_movl_fpscr_T0();
b5ff1b31 2085 gen_lookup_tb(s);
b7bcbe95 2086 break;
40f137e1 2087 case ARM_VFP_FPEXC:
9ee6e8bb
PB
2088 if (IS_USER(s))
2089 return 1;
40f137e1
PB
2090 gen_op_vfp_movl_xreg_T0(rn);
2091 gen_lookup_tb(s);
2092 break;
2093 case ARM_VFP_FPINST:
2094 case ARM_VFP_FPINST2:
2095 gen_op_vfp_movl_xreg_T0(rn);
2096 break;
b7bcbe95
FB
2097 default:
2098 return 1;
2099 }
2100 } else {
2101 gen_op_vfp_msr();
2102 gen_mov_vreg_F0(0, rn);
2103 }
2104 }
2105 }
2106 } else {
2107 /* data processing */
2108 /* The opcode is in bits 23, 21, 20 and 6. */
2109 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2110 if (dp) {
2111 if (op == 15) {
2112 /* rn is opcode */
2113 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2114 } else {
2115 /* rn is register number */
9ee6e8bb 2116 VFP_DREG_N(rn, insn);
b7bcbe95
FB
2117 }
2118
2119 if (op == 15 && (rn == 15 || rn > 17)) {
2120 /* Integer or single precision destination. */
9ee6e8bb 2121 rd = VFP_SREG_D(insn);
b7bcbe95 2122 } else {
9ee6e8bb 2123 VFP_DREG_D(rd, insn);
b7bcbe95
FB
2124 }
2125
2126 if (op == 15 && (rn == 16 || rn == 17)) {
2127 /* Integer source. */
2128 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2129 } else {
9ee6e8bb 2130 VFP_DREG_M(rm, insn);
b7bcbe95
FB
2131 }
2132 } else {
9ee6e8bb 2133 rn = VFP_SREG_N(insn);
b7bcbe95
FB
2134 if (op == 15 && rn == 15) {
2135 /* Double precision destination. */
9ee6e8bb
PB
2136 VFP_DREG_D(rd, insn);
2137 } else {
2138 rd = VFP_SREG_D(insn);
2139 }
2140 rm = VFP_SREG_M(insn);
b7bcbe95
FB
2141 }
2142
2143 veclen = env->vfp.vec_len;
2144 if (op == 15 && rn > 3)
2145 veclen = 0;
2146
2147 /* Shut up compiler warnings. */
2148 delta_m = 0;
2149 delta_d = 0;
2150 bank_mask = 0;
3b46e624 2151
b7bcbe95
FB
2152 if (veclen > 0) {
2153 if (dp)
2154 bank_mask = 0xc;
2155 else
2156 bank_mask = 0x18;
2157
2158 /* Figure out what type of vector operation this is. */
2159 if ((rd & bank_mask) == 0) {
2160 /* scalar */
2161 veclen = 0;
2162 } else {
2163 if (dp)
2164 delta_d = (env->vfp.vec_stride >> 1) + 1;
2165 else
2166 delta_d = env->vfp.vec_stride + 1;
2167
2168 if ((rm & bank_mask) == 0) {
2169 /* mixed scalar/vector */
2170 delta_m = 0;
2171 } else {
2172 /* vector */
2173 delta_m = delta_d;
2174 }
2175 }
2176 }
2177
2178 /* Load the initial operands. */
2179 if (op == 15) {
2180 switch (rn) {
2181 case 16:
2182 case 17:
2183 /* Integer source */
2184 gen_mov_F0_vreg(0, rm);
2185 break;
2186 case 8:
2187 case 9:
2188 /* Compare */
2189 gen_mov_F0_vreg(dp, rd);
2190 gen_mov_F1_vreg(dp, rm);
2191 break;
2192 case 10:
2193 case 11:
2194 /* Compare with zero */
2195 gen_mov_F0_vreg(dp, rd);
2196 gen_vfp_F1_ld0(dp);
2197 break;
9ee6e8bb
PB
2198 case 20:
2199 case 21:
2200 case 22:
2201 case 23:
2202 /* Source and destination the same. */
2203 gen_mov_F0_vreg(dp, rd);
2204 break;
b7bcbe95
FB
2205 default:
2206 /* One source operand. */
2207 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 2208 break;
b7bcbe95
FB
2209 }
2210 } else {
2211 /* Two source operands. */
2212 gen_mov_F0_vreg(dp, rn);
2213 gen_mov_F1_vreg(dp, rm);
2214 }
2215
2216 for (;;) {
2217 /* Perform the calculation. */
2218 switch (op) {
2219 case 0: /* mac: fd + (fn * fm) */
2220 gen_vfp_mul(dp);
2221 gen_mov_F1_vreg(dp, rd);
2222 gen_vfp_add(dp);
2223 break;
2224 case 1: /* nmac: fd - (fn * fm) */
2225 gen_vfp_mul(dp);
2226 gen_vfp_neg(dp);
2227 gen_mov_F1_vreg(dp, rd);
2228 gen_vfp_add(dp);
2229 break;
2230 case 2: /* msc: -fd + (fn * fm) */
2231 gen_vfp_mul(dp);
2232 gen_mov_F1_vreg(dp, rd);
2233 gen_vfp_sub(dp);
2234 break;
2235 case 3: /* nmsc: -fd - (fn * fm) */
2236 gen_vfp_mul(dp);
2237 gen_mov_F1_vreg(dp, rd);
2238 gen_vfp_add(dp);
2239 gen_vfp_neg(dp);
2240 break;
2241 case 4: /* mul: fn * fm */
2242 gen_vfp_mul(dp);
2243 break;
2244 case 5: /* nmul: -(fn * fm) */
2245 gen_vfp_mul(dp);
2246 gen_vfp_neg(dp);
2247 break;
2248 case 6: /* add: fn + fm */
2249 gen_vfp_add(dp);
2250 break;
2251 case 7: /* sub: fn - fm */
2252 gen_vfp_sub(dp);
2253 break;
2254 case 8: /* div: fn / fm */
2255 gen_vfp_div(dp);
2256 break;
9ee6e8bb
PB
2257 case 14: /* fconst */
2258 if (!arm_feature(env, ARM_FEATURE_VFP3))
2259 return 1;
2260
2261 n = (insn << 12) & 0x80000000;
2262 i = ((insn >> 12) & 0x70) | (insn & 0xf);
2263 if (dp) {
2264 if (i & 0x40)
2265 i |= 0x3f80;
2266 else
2267 i |= 0x4000;
2268 n |= i << 16;
2269 } else {
2270 if (i & 0x40)
2271 i |= 0x780;
2272 else
2273 i |= 0x800;
2274 n |= i << 19;
2275 }
2276 gen_vfp_fconst(dp, n);
2277 break;
b7bcbe95
FB
2278 case 15: /* extension space */
2279 switch (rn) {
2280 case 0: /* cpy */
2281 /* no-op */
2282 break;
2283 case 1: /* abs */
2284 gen_vfp_abs(dp);
2285 break;
2286 case 2: /* neg */
2287 gen_vfp_neg(dp);
2288 break;
2289 case 3: /* sqrt */
2290 gen_vfp_sqrt(dp);
2291 break;
2292 case 8: /* cmp */
2293 gen_vfp_cmp(dp);
2294 break;
2295 case 9: /* cmpe */
2296 gen_vfp_cmpe(dp);
2297 break;
2298 case 10: /* cmpz */
2299 gen_vfp_cmp(dp);
2300 break;
2301 case 11: /* cmpez */
2302 gen_vfp_F1_ld0(dp);
2303 gen_vfp_cmpe(dp);
2304 break;
2305 case 15: /* single<->double conversion */
2306 if (dp)
2307 gen_op_vfp_fcvtsd();
2308 else
2309 gen_op_vfp_fcvtds();
2310 break;
2311 case 16: /* fuito */
2312 gen_vfp_uito(dp);
2313 break;
2314 case 17: /* fsito */
2315 gen_vfp_sito(dp);
2316 break;
9ee6e8bb
PB
2317 case 20: /* fshto */
2318 if (!arm_feature(env, ARM_FEATURE_VFP3))
2319 return 1;
2320 gen_vfp_shto(dp, rm);
2321 break;
2322 case 21: /* fslto */
2323 if (!arm_feature(env, ARM_FEATURE_VFP3))
2324 return 1;
2325 gen_vfp_slto(dp, rm);
2326 break;
2327 case 22: /* fuhto */
2328 if (!arm_feature(env, ARM_FEATURE_VFP3))
2329 return 1;
2330 gen_vfp_uhto(dp, rm);
2331 break;
2332 case 23: /* fulto */
2333 if (!arm_feature(env, ARM_FEATURE_VFP3))
2334 return 1;
2335 gen_vfp_ulto(dp, rm);
2336 break;
b7bcbe95
FB
2337 case 24: /* ftoui */
2338 gen_vfp_toui(dp);
2339 break;
2340 case 25: /* ftouiz */
2341 gen_vfp_touiz(dp);
2342 break;
2343 case 26: /* ftosi */
2344 gen_vfp_tosi(dp);
2345 break;
2346 case 27: /* ftosiz */
2347 gen_vfp_tosiz(dp);
2348 break;
9ee6e8bb
PB
2349 case 28: /* ftosh */
2350 if (!arm_feature(env, ARM_FEATURE_VFP3))
2351 return 1;
2352 gen_vfp_tosh(dp, rm);
2353 break;
2354 case 29: /* ftosl */
2355 if (!arm_feature(env, ARM_FEATURE_VFP3))
2356 return 1;
2357 gen_vfp_tosl(dp, rm);
2358 break;
2359 case 30: /* ftouh */
2360 if (!arm_feature(env, ARM_FEATURE_VFP3))
2361 return 1;
2362 gen_vfp_touh(dp, rm);
2363 break;
2364 case 31: /* ftoul */
2365 if (!arm_feature(env, ARM_FEATURE_VFP3))
2366 return 1;
2367 gen_vfp_toul(dp, rm);
2368 break;
b7bcbe95
FB
2369 default: /* undefined */
2370 printf ("rn:%d\n", rn);
2371 return 1;
2372 }
2373 break;
2374 default: /* undefined */
2375 printf ("op:%d\n", op);
2376 return 1;
2377 }
2378
2379 /* Write back the result. */
2380 if (op == 15 && (rn >= 8 && rn <= 11))
2381 ; /* Comparison, do nothing. */
2382 else if (op == 15 && rn > 17)
2383 /* Integer result. */
2384 gen_mov_vreg_F0(0, rd);
2385 else if (op == 15 && rn == 15)
2386 /* conversion */
2387 gen_mov_vreg_F0(!dp, rd);
2388 else
2389 gen_mov_vreg_F0(dp, rd);
2390
2391 /* break out of the loop if we have finished */
2392 if (veclen == 0)
2393 break;
2394
2395 if (op == 15 && delta_m == 0) {
2396 /* single source one-many */
2397 while (veclen--) {
2398 rd = ((rd + delta_d) & (bank_mask - 1))
2399 | (rd & bank_mask);
2400 gen_mov_vreg_F0(dp, rd);
2401 }
2402 break;
2403 }
2404 /* Setup the next operands. */
2405 veclen--;
2406 rd = ((rd + delta_d) & (bank_mask - 1))
2407 | (rd & bank_mask);
2408
2409 if (op == 15) {
2410 /* One source operand. */
2411 rm = ((rm + delta_m) & (bank_mask - 1))
2412 | (rm & bank_mask);
2413 gen_mov_F0_vreg(dp, rm);
2414 } else {
2415 /* Two source operands. */
2416 rn = ((rn + delta_d) & (bank_mask - 1))
2417 | (rn & bank_mask);
2418 gen_mov_F0_vreg(dp, rn);
2419 if (delta_m) {
2420 rm = ((rm + delta_m) & (bank_mask - 1))
2421 | (rm & bank_mask);
2422 gen_mov_F1_vreg(dp, rm);
2423 }
2424 }
2425 }
2426 }
2427 break;
2428 case 0xc:
2429 case 0xd:
9ee6e8bb 2430 if (dp && (insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
2431 /* two-register transfer */
2432 rn = (insn >> 16) & 0xf;
2433 rd = (insn >> 12) & 0xf;
2434 if (dp) {
9ee6e8bb
PB
2435 VFP_DREG_M(rm, insn);
2436 } else {
2437 rm = VFP_SREG_M(insn);
2438 }
b7bcbe95 2439
18c9b560 2440 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
2441 /* vfp->arm */
2442 if (dp) {
2443 gen_mov_F0_vreg(1, rm);
2444 gen_op_vfp_mrrd();
2445 gen_movl_reg_T0(s, rd);
2446 gen_movl_reg_T1(s, rn);
2447 } else {
2448 gen_mov_F0_vreg(0, rm);
2449 gen_op_vfp_mrs();
2450 gen_movl_reg_T0(s, rn);
2451 gen_mov_F0_vreg(0, rm + 1);
2452 gen_op_vfp_mrs();
2453 gen_movl_reg_T0(s, rd);
2454 }
2455 } else {
2456 /* arm->vfp */
2457 if (dp) {
2458 gen_movl_T0_reg(s, rd);
2459 gen_movl_T1_reg(s, rn);
2460 gen_op_vfp_mdrr();
2461 gen_mov_vreg_F0(1, rm);
2462 } else {
2463 gen_movl_T0_reg(s, rn);
2464 gen_op_vfp_msr();
2465 gen_mov_vreg_F0(0, rm);
2466 gen_movl_T0_reg(s, rd);
2467 gen_op_vfp_msr();
2468 gen_mov_vreg_F0(0, rm + 1);
2469 }
2470 }
2471 } else {
2472 /* Load/store */
2473 rn = (insn >> 16) & 0xf;
2474 if (dp)
9ee6e8bb 2475 VFP_DREG_D(rd, insn);
b7bcbe95 2476 else
9ee6e8bb
PB
2477 rd = VFP_SREG_D(insn);
2478 if (s->thumb && rn == 15) {
2479 gen_op_movl_T1_im(s->pc & ~2);
2480 } else {
2481 gen_movl_T1_reg(s, rn);
2482 }
b7bcbe95
FB
2483 if ((insn & 0x01200000) == 0x01000000) {
2484 /* Single load/store */
2485 offset = (insn & 0xff) << 2;
2486 if ((insn & (1 << 23)) == 0)
2487 offset = -offset;
2488 gen_op_addl_T1_im(offset);
2489 if (insn & (1 << 20)) {
b5ff1b31 2490 gen_vfp_ld(s, dp);
b7bcbe95
FB
2491 gen_mov_vreg_F0(dp, rd);
2492 } else {
2493 gen_mov_F0_vreg(dp, rd);
b5ff1b31 2494 gen_vfp_st(s, dp);
b7bcbe95
FB
2495 }
2496 } else {
2497 /* load/store multiple */
2498 if (dp)
2499 n = (insn >> 1) & 0x7f;
2500 else
2501 n = insn & 0xff;
2502
2503 if (insn & (1 << 24)) /* pre-decrement */
2504 gen_op_addl_T1_im(-((insn & 0xff) << 2));
2505
2506 if (dp)
2507 offset = 8;
2508 else
2509 offset = 4;
2510 for (i = 0; i < n; i++) {
18c9b560 2511 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 2512 /* load */
b5ff1b31 2513 gen_vfp_ld(s, dp);
b7bcbe95
FB
2514 gen_mov_vreg_F0(dp, rd + i);
2515 } else {
2516 /* store */
2517 gen_mov_F0_vreg(dp, rd + i);
b5ff1b31 2518 gen_vfp_st(s, dp);
b7bcbe95
FB
2519 }
2520 gen_op_addl_T1_im(offset);
2521 }
2522 if (insn & (1 << 21)) {
2523 /* writeback */
2524 if (insn & (1 << 24))
2525 offset = -offset * n;
2526 else if (dp && (insn & 1))
2527 offset = 4;
2528 else
2529 offset = 0;
2530
2531 if (offset != 0)
2532 gen_op_addl_T1_im(offset);
2533 gen_movl_reg_T1(s, rn);
2534 }
2535 }
2536 }
2537 break;
2538 default:
2539 /* Should never happen. */
2540 return 1;
2541 }
2542 return 0;
2543}
2544
6e256c93 2545static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
c53be334 2546{
6e256c93
FB
2547 TranslationBlock *tb;
2548
2549 tb = s->tb;
2550 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe 2551 tcg_gen_goto_tb(n);
6e256c93 2552 gen_op_movl_T0_im(dest);
b26eefb6 2553 gen_set_pc_T0();
57fec1fe 2554 tcg_gen_exit_tb((long)tb + n);
6e256c93
FB
2555 } else {
2556 gen_op_movl_T0_im(dest);
b26eefb6 2557 gen_set_pc_T0();
57fec1fe 2558 tcg_gen_exit_tb(0);
6e256c93 2559 }
c53be334
FB
2560}
2561
8aaca4c0
FB
2562static inline void gen_jmp (DisasContext *s, uint32_t dest)
2563{
2564 if (__builtin_expect(s->singlestep_enabled, 0)) {
2565 /* An indirect jump so that we still trigger the debug exception. */
5899f386
FB
2566 if (s->thumb)
2567 dest |= 1;
8aaca4c0
FB
2568 gen_op_movl_T0_im(dest);
2569 gen_bx(s);
2570 } else {
6e256c93 2571 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
2572 s->is_jmp = DISAS_TB_JUMP;
2573 }
2574}
2575
b5ff1b31
FB
2576static inline void gen_mulxy(int x, int y)
2577{
ee097184 2578 if (x)
b26eefb6 2579 tcg_gen_sari_i32(cpu_T[0], cpu_T[0], 16);
b5ff1b31 2580 else
b26eefb6 2581 gen_sxth(cpu_T[0]);
ee097184 2582 if (y)
b5ff1b31
FB
2583 gen_op_sarl_T1_im(16);
2584 else
b26eefb6 2585 gen_sxth(cpu_T[1]);
b5ff1b31
FB
2586 gen_op_mul_T0_T1();
2587}
2588
2589/* Return the mask of PSR bits set by a MSR instruction. */
9ee6e8bb 2590static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
b5ff1b31
FB
2591 uint32_t mask;
2592
2593 mask = 0;
2594 if (flags & (1 << 0))
2595 mask |= 0xff;
2596 if (flags & (1 << 1))
2597 mask |= 0xff00;
2598 if (flags & (1 << 2))
2599 mask |= 0xff0000;
2600 if (flags & (1 << 3))
2601 mask |= 0xff000000;
9ee6e8bb 2602
2ae23e75 2603 /* Mask out undefined bits. */
9ee6e8bb
PB
2604 mask &= ~CPSR_RESERVED;
2605 if (!arm_feature(env, ARM_FEATURE_V6))
e160c51c 2606 mask &= ~(CPSR_E | CPSR_GE);
9ee6e8bb 2607 if (!arm_feature(env, ARM_FEATURE_THUMB2))
e160c51c 2608 mask &= ~CPSR_IT;
9ee6e8bb 2609 /* Mask out execution state bits. */
2ae23e75 2610 if (!spsr)
e160c51c 2611 mask &= ~CPSR_EXEC;
b5ff1b31
FB
2612 /* Mask out privileged bits. */
2613 if (IS_USER(s))
9ee6e8bb 2614 mask &= CPSR_USER;
b5ff1b31
FB
2615 return mask;
2616}
2617
2618/* Returns nonzero if access to the PSR is not permitted. */
2619static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2620{
2621 if (spsr) {
2622 /* ??? This is also undefined in system mode. */
2623 if (IS_USER(s))
2624 return 1;
2625 gen_op_movl_spsr_T0(mask);
2626 } else {
2627 gen_op_movl_cpsr_T0(mask);
2628 }
2629 gen_lookup_tb(s);
2630 return 0;
2631}
2632
9ee6e8bb 2633/* Generate an old-style exception return. */
b5ff1b31
FB
2634static void gen_exception_return(DisasContext *s)
2635{
b26eefb6 2636 gen_set_pc_T0();
b5ff1b31
FB
2637 gen_op_movl_T0_spsr();
2638 gen_op_movl_cpsr_T0(0xffffffff);
2639 s->is_jmp = DISAS_UPDATE;
2640}
2641
9ee6e8bb
PB
2642/* Generate a v6 exception return. */
2643static void gen_rfe(DisasContext *s)
2c0262af 2644{
9ee6e8bb
PB
2645 gen_op_movl_cpsr_T0(0xffffffff);
2646 gen_op_movl_T0_T2();
b26eefb6 2647 gen_set_pc_T0();
9ee6e8bb
PB
2648 s->is_jmp = DISAS_UPDATE;
2649}
3b46e624 2650
9ee6e8bb
PB
2651static inline void
2652gen_set_condexec (DisasContext *s)
2653{
2654 if (s->condexec_mask) {
2655 gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1));
2656 }
2657}
3b46e624 2658
9ee6e8bb
PB
2659static void gen_nop_hint(DisasContext *s, int val)
2660{
2661 switch (val) {
2662 case 3: /* wfi */
2663 gen_op_movl_T0_im((long)s->pc);
b26eefb6 2664 gen_set_pc_T0();
9ee6e8bb
PB
2665 s->is_jmp = DISAS_WFI;
2666 break;
2667 case 2: /* wfe */
2668 case 4: /* sev */
2669 /* TODO: Implement SEV and WFE. May help SMP performance. */
2670 default: /* nop */
2671 break;
2672 }
2673}
99c475ab 2674
9ee6e8bb
PB
2675/* Neon shift by constant. The actual ops are the same as used for variable
2676 shifts. [OP][U][SIZE] */
2677static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2678 { /* 0 */ /* VSHR */
2679 {
2680 gen_op_neon_shl_u8,
2681 gen_op_neon_shl_u16,
2682 gen_op_neon_shl_u32,
2683 gen_op_neon_shl_u64
2684 }, {
2685 gen_op_neon_shl_s8,
2686 gen_op_neon_shl_s16,
2687 gen_op_neon_shl_s32,
2688 gen_op_neon_shl_s64
2689 }
2690 }, { /* 1 */ /* VSRA */
2691 {
2692 gen_op_neon_shl_u8,
2693 gen_op_neon_shl_u16,
2694 gen_op_neon_shl_u32,
2695 gen_op_neon_shl_u64
2696 }, {
2697 gen_op_neon_shl_s8,
2698 gen_op_neon_shl_s16,
2699 gen_op_neon_shl_s32,
2700 gen_op_neon_shl_s64
2701 }
2702 }, { /* 2 */ /* VRSHR */
2703 {
2704 gen_op_neon_rshl_u8,
2705 gen_op_neon_rshl_u16,
2706 gen_op_neon_rshl_u32,
2707 gen_op_neon_rshl_u64
2708 }, {
2709 gen_op_neon_rshl_s8,
2710 gen_op_neon_rshl_s16,
2711 gen_op_neon_rshl_s32,
2712 gen_op_neon_rshl_s64
2713 }
2714 }, { /* 3 */ /* VRSRA */
2715 {
2716 gen_op_neon_rshl_u8,
2717 gen_op_neon_rshl_u16,
2718 gen_op_neon_rshl_u32,
2719 gen_op_neon_rshl_u64
2720 }, {
2721 gen_op_neon_rshl_s8,
2722 gen_op_neon_rshl_s16,
2723 gen_op_neon_rshl_s32,
2724 gen_op_neon_rshl_s64
2725 }
2726 }, { /* 4 */
2727 {
2728 NULL, NULL, NULL, NULL
2729 }, { /* VSRI */
2730 gen_op_neon_shl_u8,
2731 gen_op_neon_shl_u16,
2732 gen_op_neon_shl_u32,
2733 gen_op_neon_shl_u64,
2734 }
2735 }, { /* 5 */
2736 { /* VSHL */
2737 gen_op_neon_shl_u8,
2738 gen_op_neon_shl_u16,
2739 gen_op_neon_shl_u32,
2740 gen_op_neon_shl_u64,
2741 }, { /* VSLI */
2742 gen_op_neon_shl_u8,
2743 gen_op_neon_shl_u16,
2744 gen_op_neon_shl_u32,
2745 gen_op_neon_shl_u64,
2746 }
2747 }, { /* 6 */ /* VQSHL */
2748 {
2749 gen_op_neon_qshl_u8,
2750 gen_op_neon_qshl_u16,
2751 gen_op_neon_qshl_u32,
2752 gen_op_neon_qshl_u64
2753 }, {
2754 gen_op_neon_qshl_s8,
2755 gen_op_neon_qshl_s16,
2756 gen_op_neon_qshl_s32,
2757 gen_op_neon_qshl_s64
2758 }
2759 }, { /* 7 */ /* VQSHLU */
2760 {
2761 gen_op_neon_qshl_u8,
2762 gen_op_neon_qshl_u16,
2763 gen_op_neon_qshl_u32,
2764 gen_op_neon_qshl_u64
2765 }, {
2766 gen_op_neon_qshl_u8,
2767 gen_op_neon_qshl_u16,
2768 gen_op_neon_qshl_u32,
2769 gen_op_neon_qshl_u64
2770 }
99c475ab 2771 }
9ee6e8bb
PB
2772};
2773
2774/* [R][U][size - 1] */
2775static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2776 {
2777 {
2778 gen_op_neon_shl_u16,
2779 gen_op_neon_shl_u32,
2780 gen_op_neon_shl_u64
2781 }, {
2782 gen_op_neon_shl_s16,
2783 gen_op_neon_shl_s32,
2784 gen_op_neon_shl_s64
2785 }
2786 }, {
2787 {
2788 gen_op_neon_rshl_u16,
2789 gen_op_neon_rshl_u32,
2790 gen_op_neon_rshl_u64
2791 }, {
2792 gen_op_neon_rshl_s16,
2793 gen_op_neon_rshl_s32,
2794 gen_op_neon_rshl_s64
2795 }
2c0262af 2796 }
9ee6e8bb 2797};
99c475ab 2798
9ee6e8bb
PB
2799static inline void
2800gen_op_neon_narrow_u32 ()
2801{
2802 /* No-op. */
2803}
2804
2805static GenOpFunc *gen_neon_narrow[3] = {
2806 gen_op_neon_narrow_u8,
2807 gen_op_neon_narrow_u16,
2808 gen_op_neon_narrow_u32
2809};
2810
2811static GenOpFunc *gen_neon_narrow_satu[3] = {
2812 gen_op_neon_narrow_sat_u8,
2813 gen_op_neon_narrow_sat_u16,
2814 gen_op_neon_narrow_sat_u32
2815};
2816
2817static GenOpFunc *gen_neon_narrow_sats[3] = {
2818 gen_op_neon_narrow_sat_s8,
2819 gen_op_neon_narrow_sat_s16,
2820 gen_op_neon_narrow_sat_s32
2821};
2822
2823static inline int gen_neon_add(int size)
2824{
2825 switch (size) {
2826 case 0: gen_op_neon_add_u8(); break;
2827 case 1: gen_op_neon_add_u16(); break;
2828 case 2: gen_op_addl_T0_T1(); break;
2829 default: return 1;
2830 }
2831 return 0;
2832}
2833
2834/* 32-bit pairwise ops end up the same as the elementsise versions. */
2835#define gen_op_neon_pmax_s32 gen_op_neon_max_s32
2836#define gen_op_neon_pmax_u32 gen_op_neon_max_u32
2837#define gen_op_neon_pmin_s32 gen_op_neon_min_s32
2838#define gen_op_neon_pmin_u32 gen_op_neon_min_u32
2839
2840#define GEN_NEON_INTEGER_OP(name) do { \
2841 switch ((size << 1) | u) { \
2842 case 0: gen_op_neon_##name##_s8(); break; \
2843 case 1: gen_op_neon_##name##_u8(); break; \
2844 case 2: gen_op_neon_##name##_s16(); break; \
2845 case 3: gen_op_neon_##name##_u16(); break; \
2846 case 4: gen_op_neon_##name##_s32(); break; \
2847 case 5: gen_op_neon_##name##_u32(); break; \
2848 default: return 1; \
2849 }} while (0)
2850
2851static inline void
2852gen_neon_movl_scratch_T0(int scratch)
2853{
2854 uint32_t offset;
2855
2856 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2857 gen_op_neon_setreg_T0(offset);
2858}
2859
2860static inline void
2861gen_neon_movl_scratch_T1(int scratch)
2862{
2863 uint32_t offset;
2864
2865 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2866 gen_op_neon_setreg_T1(offset);
2867}
2868
2869static inline void
2870gen_neon_movl_T0_scratch(int scratch)
2871{
2872 uint32_t offset;
2873
2874 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2875 gen_op_neon_getreg_T0(offset);
2876}
2877
2878static inline void
2879gen_neon_movl_T1_scratch(int scratch)
2880{
2881 uint32_t offset;
2882
2883 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2884 gen_op_neon_getreg_T1(offset);
2885}
2886
2887static inline void gen_op_neon_widen_u32(void)
2888{
2889 gen_op_movl_T1_im(0);
2890}
2891
2892static inline void gen_neon_get_scalar(int size, int reg)
2893{
2894 if (size == 1) {
2895 NEON_GET_REG(T0, reg >> 1, reg & 1);
2896 } else {
2897 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
2898 if (reg & 1)
2899 gen_op_neon_dup_low16();
2900 else
2901 gen_op_neon_dup_high16();
2902 }
2903}
2904
2905static void gen_neon_unzip(int reg, int q, int tmp, int size)
2906{
2907 int n;
2908
2909 for (n = 0; n < q + 1; n += 2) {
2910 NEON_GET_REG(T0, reg, n);
2911 NEON_GET_REG(T0, reg, n + n);
2912 switch (size) {
2913 case 0: gen_op_neon_unzip_u8(); break;
2914 case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same. */
2915 case 2: /* no-op */; break;
2916 default: abort();
2917 }
2918 gen_neon_movl_scratch_T0(tmp + n);
2919 gen_neon_movl_scratch_T1(tmp + n + 1);
2920 }
2921}
2922
2923static struct {
2924 int nregs;
2925 int interleave;
2926 int spacing;
2927} neon_ls_element_type[11] = {
2928 {4, 4, 1},
2929 {4, 4, 2},
2930 {4, 1, 1},
2931 {4, 2, 1},
2932 {3, 3, 1},
2933 {3, 3, 2},
2934 {3, 1, 1},
2935 {1, 1, 1},
2936 {2, 2, 1},
2937 {2, 2, 2},
2938 {2, 1, 1}
2939};
2940
2941/* Translate a NEON load/store element instruction. Return nonzero if the
2942 instruction is invalid. */
2943static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
2944{
2945 int rd, rn, rm;
2946 int op;
2947 int nregs;
2948 int interleave;
2949 int stride;
2950 int size;
2951 int reg;
2952 int pass;
2953 int load;
2954 int shift;
2955 uint32_t mask;
2956 int n;
2957
2958 if (!vfp_enabled(env))
2959 return 1;
2960 VFP_DREG_D(rd, insn);
2961 rn = (insn >> 16) & 0xf;
2962 rm = insn & 0xf;
2963 load = (insn & (1 << 21)) != 0;
2964 if ((insn & (1 << 23)) == 0) {
2965 /* Load store all elements. */
2966 op = (insn >> 8) & 0xf;
2967 size = (insn >> 6) & 3;
2968 if (op > 10 || size == 3)
2969 return 1;
2970 nregs = neon_ls_element_type[op].nregs;
2971 interleave = neon_ls_element_type[op].interleave;
2972 gen_movl_T1_reg(s, rn);
2973 stride = (1 << size) * interleave;
2974 for (reg = 0; reg < nregs; reg++) {
2975 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
2976 gen_movl_T1_reg(s, rn);
2977 gen_op_addl_T1_im((1 << size) * reg);
2978 } else if (interleave == 2 && nregs == 4 && reg == 2) {
2979 gen_movl_T1_reg(s, rn);
2980 gen_op_addl_T1_im(1 << size);
2981 }
2982 for (pass = 0; pass < 2; pass++) {
2983 if (size == 2) {
2984 if (load) {
2985 gen_ldst(ldl, s);
2986 NEON_SET_REG(T0, rd, pass);
2987 } else {
2988 NEON_GET_REG(T0, rd, pass);
2989 gen_ldst(stl, s);
2990 }
2991 gen_op_addl_T1_im(stride);
2992 } else if (size == 1) {
2993 if (load) {
2994 gen_ldst(lduw, s);
2995 gen_op_addl_T1_im(stride);
2996 gen_op_movl_T2_T0();
2997 gen_ldst(lduw, s);
2998 gen_op_addl_T1_im(stride);
2999 gen_op_neon_insert_elt(16, 0xffff);
3000 NEON_SET_REG(T2, rd, pass);
3001 } else {
3002 NEON_GET_REG(T2, rd, pass);
3003 gen_op_movl_T0_T2();
3004 gen_ldst(stw, s);
3005 gen_op_addl_T1_im(stride);
3006 gen_op_neon_extract_elt(16, 0xffff0000);
3007 gen_ldst(stw, s);
3008 gen_op_addl_T1_im(stride);
3009 }
3010 } else /* size == 0 */ {
3011 if (load) {
3012 mask = 0xff;
3013 for (n = 0; n < 4; n++) {
3014 gen_ldst(ldub, s);
3015 gen_op_addl_T1_im(stride);
3016 if (n == 0) {
3017 gen_op_movl_T2_T0();
3018 } else {
3019 gen_op_neon_insert_elt(n * 8, ~mask);
3020 }
3021 mask <<= 8;
3022 }
3023 NEON_SET_REG(T2, rd, pass);
3024 } else {
3025 NEON_GET_REG(T2, rd, pass);
3026 mask = 0xff;
3027 for (n = 0; n < 4; n++) {
3028 if (n == 0) {
3029 gen_op_movl_T0_T2();
3030 } else {
3031 gen_op_neon_extract_elt(n * 8, mask);
3032 }
3033 gen_ldst(stb, s);
3034 gen_op_addl_T1_im(stride);
3035 mask <<= 8;
3036 }
3037 }
3038 }
3039 }
3040 rd += neon_ls_element_type[op].spacing;
3041 }
3042 stride = nregs * 8;
3043 } else {
3044 size = (insn >> 10) & 3;
3045 if (size == 3) {
3046 /* Load single element to all lanes. */
3047 if (!load)
3048 return 1;
3049 size = (insn >> 6) & 3;
3050 nregs = ((insn >> 8) & 3) + 1;
3051 stride = (insn & (1 << 5)) ? 2 : 1;
ff8263a9 3052 gen_movl_T1_reg(s, rn);
9ee6e8bb
PB
3053 for (reg = 0; reg < nregs; reg++) {
3054 switch (size) {
3055 case 0:
3056 gen_ldst(ldub, s);
3057 gen_op_neon_dup_u8(0);
3058 break;
3059 case 1:
3060 gen_ldst(lduw, s);
3061 gen_op_neon_dup_low16();
3062 break;
3063 case 2:
3064 gen_ldst(ldl, s);
3065 break;
3066 case 3:
3067 return 1;
99c475ab 3068 }
9ee6e8bb
PB
3069 gen_op_addl_T1_im(1 << size);
3070 NEON_SET_REG(T0, rd, 0);
3071 NEON_SET_REG(T0, rd, 1);
3072 rd += stride;
3073 }
3074 stride = (1 << size) * nregs;
3075 } else {
3076 /* Single element. */
3077 pass = (insn >> 7) & 1;
3078 switch (size) {
3079 case 0:
3080 shift = ((insn >> 5) & 3) * 8;
3081 mask = 0xff << shift;
3082 stride = 1;
3083 break;
3084 case 1:
3085 shift = ((insn >> 6) & 1) * 16;
3086 mask = shift ? 0xffff0000 : 0xffff;
3087 stride = (insn & (1 << 5)) ? 2 : 1;
3088 break;
3089 case 2:
3090 shift = 0;
3091 mask = 0xffffffff;
3092 stride = (insn & (1 << 6)) ? 2 : 1;
3093 break;
3094 default:
3095 abort();
3096 }
3097 nregs = ((insn >> 8) & 3) + 1;
3098 gen_movl_T1_reg(s, rn);
3099 for (reg = 0; reg < nregs; reg++) {
3100 if (load) {
3101 if (size != 2) {
3102 NEON_GET_REG(T2, rd, pass);
3103 }
3104 switch (size) {
3105 case 0:
3106 gen_ldst(ldub, s);
3107 break;
3108 case 1:
3109 gen_ldst(lduw, s);
3110 break;
3111 case 2:
3112 gen_ldst(ldl, s);
3113 NEON_SET_REG(T0, rd, pass);
3114 break;
3115 }
3116 if (size != 2) {
3117 gen_op_neon_insert_elt(shift, ~mask);
3118 NEON_SET_REG(T0, rd, pass);
3119 }
3120 } else { /* Store */
3121 if (size == 2) {
3122 NEON_GET_REG(T0, rd, pass);
3123 } else {
3124 NEON_GET_REG(T2, rd, pass);
3125 gen_op_neon_extract_elt(shift, mask);
3126 }
3127 switch (size) {
3128 case 0:
3129 gen_ldst(stb, s);
3130 break;
3131 case 1:
3132 gen_ldst(stw, s);
3133 break;
3134 case 2:
3135 gen_ldst(stl, s);
3136 break;
99c475ab 3137 }
99c475ab 3138 }
9ee6e8bb
PB
3139 rd += stride;
3140 gen_op_addl_T1_im(1 << size);
99c475ab 3141 }
9ee6e8bb 3142 stride = nregs * (1 << size);
99c475ab 3143 }
9ee6e8bb
PB
3144 }
3145 if (rm != 15) {
b26eefb6
PB
3146 TCGv base;
3147
3148 base = load_reg(s, rn);
9ee6e8bb 3149 if (rm == 13) {
b26eefb6 3150 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 3151 } else {
b26eefb6
PB
3152 TCGv index;
3153 index = load_reg(s, rm);
3154 tcg_gen_add_i32(base, base, index);
3155 dead_tmp(index);
9ee6e8bb 3156 }
b26eefb6 3157 store_reg(s, rn, base);
9ee6e8bb
PB
3158 }
3159 return 0;
3160}
3b46e624 3161
9ee6e8bb
PB
3162/* Translate a NEON data processing instruction. Return nonzero if the
3163 instruction is invalid.
3164 In general we process vectors in 32-bit chunks. This means we can reuse
3165 some of the scalar ops, and hopefully the code generated for 32-bit
3166 hosts won't be too awful. The downside is that the few 64-bit operations
3167 (mainly shifts) get complicated. */
2c0262af 3168
9ee6e8bb
PB
3169static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3170{
3171 int op;
3172 int q;
3173 int rd, rn, rm;
3174 int size;
3175 int shift;
3176 int pass;
3177 int count;
3178 int pairwise;
3179 int u;
3180 int n;
3181 uint32_t imm;
3182
3183 if (!vfp_enabled(env))
3184 return 1;
3185 q = (insn & (1 << 6)) != 0;
3186 u = (insn >> 24) & 1;
3187 VFP_DREG_D(rd, insn);
3188 VFP_DREG_N(rn, insn);
3189 VFP_DREG_M(rm, insn);
3190 size = (insn >> 20) & 3;
3191 if ((insn & (1 << 23)) == 0) {
3192 /* Three register same length. */
3193 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3194 if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3195 for (pass = 0; pass < (q ? 2 : 1); pass++) {
3196 NEON_GET_REG(T0, rm, pass * 2);
3197 NEON_GET_REG(T1, rm, pass * 2 + 1);
3198 gen_neon_movl_scratch_T0(0);
3199 gen_neon_movl_scratch_T1(1);
3200 NEON_GET_REG(T0, rn, pass * 2);
3201 NEON_GET_REG(T1, rn, pass * 2 + 1);
3202 switch (op) {
3203 case 1: /* VQADD */
3204 if (u) {
3205 gen_op_neon_addl_saturate_u64();
2c0262af 3206 } else {
9ee6e8bb 3207 gen_op_neon_addl_saturate_s64();
2c0262af 3208 }
9ee6e8bb
PB
3209 break;
3210 case 5: /* VQSUB */
3211 if (u) {
3212 gen_op_neon_subl_saturate_u64();
1e8d4eec 3213 } else {
9ee6e8bb 3214 gen_op_neon_subl_saturate_s64();
1e8d4eec 3215 }
9ee6e8bb
PB
3216 break;
3217 case 16:
3218 if (u) {
3219 gen_op_neon_subl_u64();
3220 } else {
3221 gen_op_neon_addl_u64();
3222 }
3223 break;
3224 default:
3225 abort();
2c0262af 3226 }
9ee6e8bb
PB
3227 NEON_SET_REG(T0, rd, pass * 2);
3228 NEON_SET_REG(T1, rd, pass * 2 + 1);
2c0262af 3229 }
9ee6e8bb 3230 return 0;
2c0262af 3231 }
9ee6e8bb
PB
3232 switch (op) {
3233 case 8: /* VSHL */
3234 case 9: /* VQSHL */
3235 case 10: /* VRSHL */
3236 case 11: /* VQSHL */
3237 /* Shift operations have Rn and Rm reversed. */
3238 {
3239 int tmp;
3240 tmp = rn;
3241 rn = rm;
3242 rm = tmp;
3243 pairwise = 0;
3244 }
2c0262af 3245 break;
9ee6e8bb
PB
3246 case 20: /* VPMAX */
3247 case 21: /* VPMIN */
3248 case 23: /* VPADD */
3249 pairwise = 1;
2c0262af 3250 break;
9ee6e8bb
PB
3251 case 26: /* VPADD (float) */
3252 pairwise = (u && size < 2);
2c0262af 3253 break;
9ee6e8bb
PB
3254 case 30: /* VPMIN/VPMAX (float) */
3255 pairwise = u;
2c0262af 3256 break;
9ee6e8bb
PB
3257 default:
3258 pairwise = 0;
2c0262af 3259 break;
9ee6e8bb
PB
3260 }
3261 for (pass = 0; pass < (q ? 4 : 2); pass++) {
3262
3263 if (pairwise) {
3264 /* Pairwise. */
3265 if (q)
3266 n = (pass & 1) * 2;
2c0262af 3267 else
9ee6e8bb
PB
3268 n = 0;
3269 if (pass < q + 1) {
3270 NEON_GET_REG(T0, rn, n);
3271 NEON_GET_REG(T1, rn, n + 1);
3272 } else {
3273 NEON_GET_REG(T0, rm, n);
3274 NEON_GET_REG(T1, rm, n + 1);
3275 }
3276 } else {
3277 /* Elementwise. */
3278 NEON_GET_REG(T0, rn, pass);
3279 NEON_GET_REG(T1, rm, pass);
3280 }
3281 switch (op) {
3282 case 0: /* VHADD */
3283 GEN_NEON_INTEGER_OP(hadd);
3284 break;
3285 case 1: /* VQADD */
3286 switch (size << 1| u) {
3287 case 0: gen_op_neon_qadd_s8(); break;
3288 case 1: gen_op_neon_qadd_u8(); break;
3289 case 2: gen_op_neon_qadd_s16(); break;
3290 case 3: gen_op_neon_qadd_u16(); break;
3291 case 4: gen_op_addl_T0_T1_saturate(); break;
3292 case 5: gen_op_addl_T0_T1_usaturate(); break;
3293 default: abort();
3294 }
2c0262af 3295 break;
9ee6e8bb
PB
3296 case 2: /* VRHADD */
3297 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 3298 break;
9ee6e8bb
PB
3299 case 3: /* Logic ops. */
3300 switch ((u << 2) | size) {
3301 case 0: /* VAND */
2c0262af 3302 gen_op_andl_T0_T1();
9ee6e8bb
PB
3303 break;
3304 case 1: /* BIC */
3305 gen_op_bicl_T0_T1();
3306 break;
3307 case 2: /* VORR */
3308 gen_op_orl_T0_T1();
3309 break;
3310 case 3: /* VORN */
3311 gen_op_notl_T1();
3312 gen_op_orl_T0_T1();
3313 break;
3314 case 4: /* VEOR */
3315 gen_op_xorl_T0_T1();
3316 break;
3317 case 5: /* VBSL */
3318 NEON_GET_REG(T2, rd, pass);
3319 gen_op_neon_bsl();
3320 break;
3321 case 6: /* VBIT */
3322 NEON_GET_REG(T2, rd, pass);
3323 gen_op_neon_bit();
3324 break;
3325 case 7: /* VBIF */
3326 NEON_GET_REG(T2, rd, pass);
3327 gen_op_neon_bif();
3328 break;
2c0262af
FB
3329 }
3330 break;
9ee6e8bb
PB
3331 case 4: /* VHSUB */
3332 GEN_NEON_INTEGER_OP(hsub);
3333 break;
3334 case 5: /* VQSUB */
3335 switch ((size << 1) | u) {
3336 case 0: gen_op_neon_qsub_s8(); break;
3337 case 1: gen_op_neon_qsub_u8(); break;
3338 case 2: gen_op_neon_qsub_s16(); break;
3339 case 3: gen_op_neon_qsub_u16(); break;
3340 case 4: gen_op_subl_T0_T1_saturate(); break;
3341 case 5: gen_op_subl_T0_T1_usaturate(); break;
3342 default: abort();
2c0262af
FB
3343 }
3344 break;
9ee6e8bb
PB
3345 case 6: /* VCGT */
3346 GEN_NEON_INTEGER_OP(cgt);
3347 break;
3348 case 7: /* VCGE */
3349 GEN_NEON_INTEGER_OP(cge);
3350 break;
3351 case 8: /* VSHL */
3352 switch ((size << 1) | u) {
3353 case 0: gen_op_neon_shl_s8(); break;
3354 case 1: gen_op_neon_shl_u8(); break;
3355 case 2: gen_op_neon_shl_s16(); break;
3356 case 3: gen_op_neon_shl_u16(); break;
3357 case 4: gen_op_neon_shl_s32(); break;
3358 case 5: gen_op_neon_shl_u32(); break;
3359#if 0
3360 /* ??? Implementing these is tricky because the vector ops work
3361 on 32-bit pieces. */
3362 case 6: gen_op_neon_shl_s64(); break;
3363 case 7: gen_op_neon_shl_u64(); break;
3364#else
3365 case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3366#endif
2c0262af
FB
3367 }
3368 break;
9ee6e8bb
PB
3369 case 9: /* VQSHL */
3370 switch ((size << 1) | u) {
3371 case 0: gen_op_neon_qshl_s8(); break;
3372 case 1: gen_op_neon_qshl_u8(); break;
3373 case 2: gen_op_neon_qshl_s16(); break;
3374 case 3: gen_op_neon_qshl_u16(); break;
3375 case 4: gen_op_neon_qshl_s32(); break;
3376 case 5: gen_op_neon_qshl_u32(); break;
3377#if 0
3378 /* ??? Implementing these is tricky because the vector ops work
3379 on 32-bit pieces. */
3380 case 6: gen_op_neon_qshl_s64(); break;
3381 case 7: gen_op_neon_qshl_u64(); break;
3382#else
3383 case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3384#endif
2c0262af
FB
3385 }
3386 break;
9ee6e8bb
PB
3387 case 10: /* VRSHL */
3388 switch ((size << 1) | u) {
3389 case 0: gen_op_neon_rshl_s8(); break;
3390 case 1: gen_op_neon_rshl_u8(); break;
3391 case 2: gen_op_neon_rshl_s16(); break;
3392 case 3: gen_op_neon_rshl_u16(); break;
3393 case 4: gen_op_neon_rshl_s32(); break;
3394 case 5: gen_op_neon_rshl_u32(); break;
3395#if 0
3396 /* ??? Implementing these is tricky because the vector ops work
3397 on 32-bit pieces. */
3398 case 6: gen_op_neon_rshl_s64(); break;
3399 case 7: gen_op_neon_rshl_u64(); break;
3400#else
3401 case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3402#endif
3403 }
2c0262af 3404 break;
9ee6e8bb
PB
3405 case 11: /* VQRSHL */
3406 switch ((size << 1) | u) {
3407 case 0: gen_op_neon_qrshl_s8(); break;
3408 case 1: gen_op_neon_qrshl_u8(); break;
3409 case 2: gen_op_neon_qrshl_s16(); break;
3410 case 3: gen_op_neon_qrshl_u16(); break;
3411 case 4: gen_op_neon_qrshl_s32(); break;
3412 case 5: gen_op_neon_qrshl_u32(); break;
3413#if 0
3414 /* ??? Implementing these is tricky because the vector ops work
3415 on 32-bit pieces. */
3416 case 6: gen_op_neon_qrshl_s64(); break;
3417 case 7: gen_op_neon_qrshl_u64(); break;
3418#else
3419 case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3420#endif
3421 }
3422 break;
3423 case 12: /* VMAX */
3424 GEN_NEON_INTEGER_OP(max);
3425 break;
3426 case 13: /* VMIN */
3427 GEN_NEON_INTEGER_OP(min);
3428 break;
3429 case 14: /* VABD */
3430 GEN_NEON_INTEGER_OP(abd);
3431 break;
3432 case 15: /* VABA */
3433 GEN_NEON_INTEGER_OP(abd);
3434 NEON_GET_REG(T1, rd, pass);
3435 gen_neon_add(size);
3436 break;
3437 case 16:
3438 if (!u) { /* VADD */
3439 if (gen_neon_add(size))
3440 return 1;
3441 } else { /* VSUB */
3442 switch (size) {
3443 case 0: gen_op_neon_sub_u8(); break;
3444 case 1: gen_op_neon_sub_u16(); break;
3445 case 2: gen_op_subl_T0_T1(); break;
3446 default: return 1;
3447 }
3448 }
3449 break;
3450 case 17:
3451 if (!u) { /* VTST */
3452 switch (size) {
3453 case 0: gen_op_neon_tst_u8(); break;
3454 case 1: gen_op_neon_tst_u16(); break;
3455 case 2: gen_op_neon_tst_u32(); break;
3456 default: return 1;
3457 }
3458 } else { /* VCEQ */
3459 switch (size) {
3460 case 0: gen_op_neon_ceq_u8(); break;
3461 case 1: gen_op_neon_ceq_u16(); break;
3462 case 2: gen_op_neon_ceq_u32(); break;
3463 default: return 1;
3464 }
3465 }
3466 break;
3467 case 18: /* Multiply. */
3468 switch (size) {
3469 case 0: gen_op_neon_mul_u8(); break;
3470 case 1: gen_op_neon_mul_u16(); break;
3471 case 2: gen_op_mul_T0_T1(); break;
3472 default: return 1;
3473 }
3474 NEON_GET_REG(T1, rd, pass);
3475 if (u) { /* VMLS */
3476 switch (size) {
3477 case 0: gen_op_neon_rsb_u8(); break;
3478 case 1: gen_op_neon_rsb_u16(); break;
3479 case 2: gen_op_rsbl_T0_T1(); break;
3480 default: return 1;
3481 }
3482 } else { /* VMLA */
3483 gen_neon_add(size);
3484 }
3485 break;
3486 case 19: /* VMUL */
3487 if (u) { /* polynomial */
3488 gen_op_neon_mul_p8();
3489 } else { /* Integer */
3490 switch (size) {
3491 case 0: gen_op_neon_mul_u8(); break;
3492 case 1: gen_op_neon_mul_u16(); break;
3493 case 2: gen_op_mul_T0_T1(); break;
3494 default: return 1;
3495 }
3496 }
3497 break;
3498 case 20: /* VPMAX */
3499 GEN_NEON_INTEGER_OP(pmax);
3500 break;
3501 case 21: /* VPMIN */
3502 GEN_NEON_INTEGER_OP(pmin);
3503 break;
3504 case 22: /* Hultiply high. */
3505 if (!u) { /* VQDMULH */
3506 switch (size) {
3507 case 1: gen_op_neon_qdmulh_s16(); break;
3508 case 2: gen_op_neon_qdmulh_s32(); break;
3509 default: return 1;
3510 }
3511 } else { /* VQRDHMUL */
3512 switch (size) {
3513 case 1: gen_op_neon_qrdmulh_s16(); break;
3514 case 2: gen_op_neon_qrdmulh_s32(); break;
3515 default: return 1;
3516 }
3517 }
3518 break;
3519 case 23: /* VPADD */
3520 if (u)
3521 return 1;
3522 switch (size) {
3523 case 0: gen_op_neon_padd_u8(); break;
3524 case 1: gen_op_neon_padd_u16(); break;
3525 case 2: gen_op_addl_T0_T1(); break;
3526 default: return 1;
3527 }
3528 break;
3529 case 26: /* Floating point arithnetic. */
3530 switch ((u << 2) | size) {
3531 case 0: /* VADD */
3532 gen_op_neon_add_f32();
3533 break;
3534 case 2: /* VSUB */
3535 gen_op_neon_sub_f32();
3536 break;
3537 case 4: /* VPADD */
3538 gen_op_neon_add_f32();
3539 break;
3540 case 6: /* VABD */
3541 gen_op_neon_abd_f32();
3542 break;
3543 default:
3544 return 1;
3545 }
3546 break;
3547 case 27: /* Float multiply. */
3548 gen_op_neon_mul_f32();
3549 if (!u) {
3550 NEON_GET_REG(T1, rd, pass);
3551 if (size == 0) {
3552 gen_op_neon_add_f32();
3553 } else {
3554 gen_op_neon_rsb_f32();
3555 }
3556 }
3557 break;
3558 case 28: /* Float compare. */
3559 if (!u) {
3560 gen_op_neon_ceq_f32();
b5ff1b31 3561 } else {
9ee6e8bb
PB
3562 if (size == 0)
3563 gen_op_neon_cge_f32();
3564 else
3565 gen_op_neon_cgt_f32();
b5ff1b31 3566 }
2c0262af 3567 break;
9ee6e8bb
PB
3568 case 29: /* Float compare absolute. */
3569 if (!u)
3570 return 1;
3571 if (size == 0)
3572 gen_op_neon_acge_f32();
3573 else
3574 gen_op_neon_acgt_f32();
2c0262af 3575 break;
9ee6e8bb
PB
3576 case 30: /* Float min/max. */
3577 if (size == 0)
3578 gen_op_neon_max_f32();
3579 else
3580 gen_op_neon_min_f32();
3581 break;
3582 case 31:
3583 if (size == 0)
3584 gen_op_neon_recps_f32();
3585 else
3586 gen_op_neon_rsqrts_f32();
2c0262af 3587 break;
9ee6e8bb
PB
3588 default:
3589 abort();
2c0262af 3590 }
9ee6e8bb
PB
3591 /* Save the result. For elementwise operations we can put it
3592 straight into the destination register. For pairwise operations
3593 we have to be careful to avoid clobbering the source operands. */
3594 if (pairwise && rd == rm) {
3595 gen_neon_movl_scratch_T0(pass);
3596 } else {
3597 NEON_SET_REG(T0, rd, pass);
3598 }
3599
3600 } /* for pass */
3601 if (pairwise && rd == rm) {
3602 for (pass = 0; pass < (q ? 4 : 2); pass++) {
3603 gen_neon_movl_T0_scratch(pass);
3604 NEON_SET_REG(T0, rd, pass);
3605 }
3606 }
3607 } else if (insn & (1 << 4)) {
3608 if ((insn & 0x00380080) != 0) {
3609 /* Two registers and shift. */
3610 op = (insn >> 8) & 0xf;
3611 if (insn & (1 << 7)) {
3612 /* 64-bit shift. */
3613 size = 3;
3614 } else {
3615 size = 2;
3616 while ((insn & (1 << (size + 19))) == 0)
3617 size--;
3618 }
3619 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3620 /* To avoid excessive dumplication of ops we implement shift
3621 by immediate using the variable shift operations. */
3622 if (op < 8) {
3623 /* Shift by immediate:
3624 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
3625 /* Right shifts are encoded as N - shift, where N is the
3626 element size in bits. */
3627 if (op <= 4)
3628 shift = shift - (1 << (size + 3));
3629 else
3630 shift++;
3631 if (size == 3) {
3632 count = q + 1;
3633 } else {
3634 count = q ? 4: 2;
3635 }
3636 switch (size) {
3637 case 0:
3638 imm = (uint8_t) shift;
3639 imm |= imm << 8;
3640 imm |= imm << 16;
3641 break;
3642 case 1:
3643 imm = (uint16_t) shift;
3644 imm |= imm << 16;
3645 break;
3646 case 2:
3647 case 3:
3648 imm = shift;
3649 break;
3650 default:
3651 abort();
3652 }
3653
3654 for (pass = 0; pass < count; pass++) {
3655 if (size < 3) {
3656 /* Operands in T0 and T1. */
3657 gen_op_movl_T1_im(imm);
3658 NEON_GET_REG(T0, rm, pass);
2c0262af 3659 } else {
9ee6e8bb
PB
3660 /* Operands in {T0, T1} and env->vfp.scratch. */
3661 gen_op_movl_T0_im(imm);
3662 gen_neon_movl_scratch_T0(0);
3663 gen_op_movl_T0_im((int32_t)imm >> 31);
3664 gen_neon_movl_scratch_T0(1);
3665 NEON_GET_REG(T0, rm, pass * 2);
3666 NEON_GET_REG(T1, rm, pass * 2 + 1);
3667 }
3668
3669 if (gen_neon_shift_im[op][u][size] == NULL)
3670 return 1;
3671 gen_neon_shift_im[op][u][size]();
3672
3673 if (op == 1 || op == 3) {
3674 /* Accumulate. */
3675 if (size == 3) {
3676 gen_neon_movl_scratch_T0(0);
3677 gen_neon_movl_scratch_T1(1);
3678 NEON_GET_REG(T0, rd, pass * 2);
3679 NEON_GET_REG(T1, rd, pass * 2 + 1);
3680 gen_op_neon_addl_u64();
3681 } else {
3682 NEON_GET_REG(T1, rd, pass);
3683 gen_neon_add(size);
99c475ab 3684 }
9ee6e8bb
PB
3685 } else if (op == 4 || (op == 5 && u)) {
3686 /* Insert */
3687 if (size == 3) {
3688 cpu_abort(env, "VS[LR]I.64 not implemented");
3689 }
3690 switch (size) {
3691 case 0:
3692 if (op == 4)
3693 imm = 0xff >> -shift;
3694 else
3695 imm = (uint8_t)(0xff << shift);
3696 imm |= imm << 8;
3697 imm |= imm << 16;
3698 break;
3699 case 1:
3700 if (op == 4)
3701 imm = 0xffff >> -shift;
3702 else
3703 imm = (uint16_t)(0xffff << shift);
3704 imm |= imm << 16;
3705 break;
3706 case 2:
3707 if (op == 4)
3708 imm = 0xffffffffu >> -shift;
3709 else
3710 imm = 0xffffffffu << shift;
3711 break;
3712 default:
3713 abort();
3714 }
3715 NEON_GET_REG(T1, rd, pass);
3716 gen_op_movl_T2_im(imm);
3717 gen_op_neon_bsl();
2c0262af 3718 }
9ee6e8bb
PB
3719 if (size == 3) {
3720 NEON_SET_REG(T0, rd, pass * 2);
3721 NEON_SET_REG(T1, rd, pass * 2 + 1);
3722 } else {
3723 NEON_SET_REG(T0, rd, pass);
3724 }
3725 } /* for pass */
3726 } else if (op < 10) {
3727 /* Shift by immedaiate and narrow:
3728 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
3729 shift = shift - (1 << (size + 3));
3730 size++;
3731 if (size == 3) {
3732 count = q + 1;
2c0262af 3733 } else {
9ee6e8bb
PB
3734 count = q ? 4: 2;
3735 }
3736 switch (size) {
3737 case 1:
3738 imm = (uint16_t) shift;
3739 imm |= imm << 16;
3740 break;
3741 case 2:
3742 case 3:
3743 imm = shift;
3744 break;
3745 default:
3746 abort();
3747 }
3748
3749 /* Processing MSB first means we need to do less shuffling at
3750 the end. */
3751 for (pass = count - 1; pass >= 0; pass--) {
3752 /* Avoid clobbering the second operand before it has been
3753 written. */
3754 n = pass;
3755 if (rd == rm)
3756 n ^= (count - 1);
3757 else
3758 n = pass;
3759
3760 if (size < 3) {
3761 /* Operands in T0 and T1. */
3762 gen_op_movl_T1_im(imm);
3763 NEON_GET_REG(T0, rm, n);
2c0262af 3764 } else {
9ee6e8bb
PB
3765 /* Operands in {T0, T1} and env->vfp.scratch. */
3766 gen_op_movl_T0_im(imm);
3767 gen_neon_movl_scratch_T0(0);
3768 gen_op_movl_T0_im((int32_t)imm >> 31);
3769 gen_neon_movl_scratch_T0(1);
3770 NEON_GET_REG(T0, rm, n * 2);
3771 NEON_GET_REG(T0, rm, n * 2 + 1);
3772 }
3b46e624 3773
9ee6e8bb
PB
3774 gen_neon_shift_im_narrow[q][u][size - 1]();
3775
3776 if (size < 3 && (pass & 1) == 0) {
3777 gen_neon_movl_scratch_T0(0);
3778 } else {
3779 uint32_t offset;
3780
3781 if (size < 3)
3782 gen_neon_movl_T1_scratch(0);
3783
3784 if (op == 8 && !u) {
3785 gen_neon_narrow[size - 1]();
99c475ab 3786 } else {
9ee6e8bb
PB
3787 if (op == 8)
3788 gen_neon_narrow_sats[size - 2]();
3789 else
3790 gen_neon_narrow_satu[size - 1]();
99c475ab 3791 }
9ee6e8bb
PB
3792 if (size == 3)
3793 offset = neon_reg_offset(rd, n);
3794 else
3795 offset = neon_reg_offset(rd, n >> 1);
3796 gen_op_neon_setreg_T0(offset);
3797 }
3798 } /* for pass */
3799 } else if (op == 10) {
3800 /* VSHLL */
3801 if (q)
3802 return 1;
3803 for (pass = 0; pass < 2; pass++) {
3804 /* Avoid clobbering the input operand. */
3805 if (rd == rm)
3806 n = 1 - pass;
3807 else
3808 n = pass;
3809
3810 NEON_GET_REG(T0, rm, n);
3811 GEN_NEON_INTEGER_OP(widen);
3812 if (shift != 0) {
3813 /* The shift is less than the width of the source
3814 type, so in some cases we can just
3815 shift the whole register. */
3816 if (size == 1 || (size == 0 && u)) {
3817 gen_op_shll_T0_im(shift);
3818 gen_op_shll_T1_im(shift);
3819 } else {
3820 switch (size) {
3821 case 0: gen_op_neon_shll_u16(shift); break;
3822 case 2: gen_op_neon_shll_u64(shift); break;
3823 default: abort();
3824 }
3825 }
3826 }
3827 NEON_SET_REG(T0, rd, n * 2);
3828 NEON_SET_REG(T1, rd, n * 2 + 1);
3829 }
3830 } else if (op == 15 || op == 16) {
3831 /* VCVT fixed-point. */
3832 for (pass = 0; pass < (q ? 4 : 2); pass++) {
3833 gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
3834 if (op & 1) {
3835 if (u)
3836 gen_op_vfp_ultos(shift);
3837 else
3838 gen_op_vfp_sltos(shift);
3839 } else {
3840 if (u)
3841 gen_op_vfp_touls(shift);
3842 else
3843 gen_op_vfp_tosls(shift);
2c0262af 3844 }
9ee6e8bb 3845 gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
2c0262af
FB
3846 }
3847 } else {
9ee6e8bb
PB
3848 return 1;
3849 }
3850 } else { /* (insn & 0x00380080) == 0 */
3851 int invert;
3852
3853 op = (insn >> 8) & 0xf;
3854 /* One register and immediate. */
3855 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
3856 invert = (insn & (1 << 5)) != 0;
3857 switch (op) {
3858 case 0: case 1:
3859 /* no-op */
3860 break;
3861 case 2: case 3:
3862 imm <<= 8;
3863 break;
3864 case 4: case 5:
3865 imm <<= 16;
3866 break;
3867 case 6: case 7:
3868 imm <<= 24;
3869 break;
3870 case 8: case 9:
3871 imm |= imm << 16;
3872 break;
3873 case 10: case 11:
3874 imm = (imm << 8) | (imm << 24);
3875 break;
3876 case 12:
3877 imm = (imm < 8) | 0xff;
3878 break;
3879 case 13:
3880 imm = (imm << 16) | 0xffff;
3881 break;
3882 case 14:
3883 imm |= (imm << 8) | (imm << 16) | (imm << 24);
3884 if (invert)
3885 imm = ~imm;
3886 break;
3887 case 15:
3888 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
3889 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
3890 break;
3891 }
3892 if (invert)
3893 imm = ~imm;
3894
3895 if (op != 14 || !invert)
3896 gen_op_movl_T1_im(imm);
3897
3898 for (pass = 0; pass < (q ? 4 : 2); pass++) {
3899 if (op & 1 && op < 12) {
3900 NEON_GET_REG(T0, rd, pass);
3901 if (invert) {
3902 /* The immediate value has already been inverted, so
3903 BIC becomes AND. */
3904 gen_op_andl_T0_T1();
3905 } else {
3906 gen_op_orl_T0_T1();
3907 }
3908 NEON_SET_REG(T0, rd, pass);
3909 } else {
3910 if (op == 14 && invert) {
3911 uint32_t tmp;
3912 tmp = 0;
3913 for (n = 0; n < 4; n++) {
3914 if (imm & (1 << (n + (pass & 1) * 4)))
3915 tmp |= 0xff << (n * 8);
3916 }
3917 gen_op_movl_T1_im(tmp);
3918 }
3919 /* VMOV, VMVN. */
3920 NEON_SET_REG(T1, rd, pass);
3921 }
3922 }
3923 }
3924 } else { /* (insn & 0x00800010 == 0x00800010) */
3925 if (size != 3) {
3926 op = (insn >> 8) & 0xf;
3927 if ((insn & (1 << 6)) == 0) {
3928 /* Three registers of different lengths. */
3929 int src1_wide;
3930 int src2_wide;
3931 int prewiden;
3932 /* prewiden, src1_wide, src2_wide */
3933 static const int neon_3reg_wide[16][3] = {
3934 {1, 0, 0}, /* VADDL */
3935 {1, 1, 0}, /* VADDW */
3936 {1, 0, 0}, /* VSUBL */
3937 {1, 1, 0}, /* VSUBW */
3938 {0, 1, 1}, /* VADDHN */
3939 {0, 0, 0}, /* VABAL */
3940 {0, 1, 1}, /* VSUBHN */
3941 {0, 0, 0}, /* VABDL */
3942 {0, 0, 0}, /* VMLAL */
3943 {0, 0, 0}, /* VQDMLAL */
3944 {0, 0, 0}, /* VMLSL */
3945 {0, 0, 0}, /* VQDMLSL */
3946 {0, 0, 0}, /* Integer VMULL */
3947 {0, 0, 0}, /* VQDMULL */
3948 {0, 0, 0} /* Polynomial VMULL */
3949 };
3950
3951 prewiden = neon_3reg_wide[op][0];
3952 src1_wide = neon_3reg_wide[op][1];
3953 src2_wide = neon_3reg_wide[op][2];
3954
3955 /* Avoid overlapping operands. Wide source operands are
3956 always aligned so will never overlap with wide
3957 destinations in problematic ways. */
3958 if (rd == rm) {
3959 NEON_GET_REG(T2, rm, 1);
3960 } else if (rd == rn) {
3961 NEON_GET_REG(T2, rn, 1);
3962 }
3963 for (pass = 0; pass < 2; pass++) {
3964 /* Load the second operand into env->vfp.scratch.
3965 Also widen narrow operands. */
3966 if (pass == 1 && rd == rm) {
3967 if (prewiden) {
3968 gen_op_movl_T0_T2();
3969 } else {
3970 gen_op_movl_T1_T2();
3971 }
3972 } else {
3973 if (src2_wide) {
3974 NEON_GET_REG(T0, rm, pass * 2);
3975 NEON_GET_REG(T1, rm, pass * 2 + 1);
3976 } else {
3977 if (prewiden) {
3978 NEON_GET_REG(T0, rm, pass);
3979 } else {
3980 NEON_GET_REG(T1, rm, pass);
3981 }
3982 }
3983 }
3984 if (prewiden && !src2_wide) {
3985 GEN_NEON_INTEGER_OP(widen);
3986 }
3987 if (prewiden || src2_wide) {
3988 gen_neon_movl_scratch_T0(0);
3989 gen_neon_movl_scratch_T1(1);
3990 }
3991
3992 /* Load the first operand. */
3993 if (pass == 1 && rd == rn) {
3994 gen_op_movl_T0_T2();
3995 } else {
3996 if (src1_wide) {
3997 NEON_GET_REG(T0, rn, pass * 2);
3998 NEON_GET_REG(T1, rn, pass * 2 + 1);
3999 } else {
4000 NEON_GET_REG(T0, rn, pass);
4001 }
4002 }
4003 if (prewiden && !src1_wide) {
4004 GEN_NEON_INTEGER_OP(widen);
4005 }
4006 switch (op) {
4007 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4008 switch (size) {
4009 case 0: gen_op_neon_addl_u16(); break;
4010 case 1: gen_op_neon_addl_u32(); break;
4011 case 2: gen_op_neon_addl_u64(); break;
4012 default: abort();
4013 }
4014 break;
4015 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4016 switch (size) {
4017 case 0: gen_op_neon_subl_u16(); break;
4018 case 1: gen_op_neon_subl_u32(); break;
4019 case 2: gen_op_neon_subl_u64(); break;
4020 default: abort();
4021 }
4022 break;
4023 case 5: case 7: /* VABAL, VABDL */
4024 switch ((size << 1) | u) {
4025 case 0: gen_op_neon_abdl_s16(); break;
4026 case 1: gen_op_neon_abdl_u16(); break;
4027 case 2: gen_op_neon_abdl_s32(); break;
4028 case 3: gen_op_neon_abdl_u32(); break;
4029 case 4: gen_op_neon_abdl_s64(); break;
4030 case 5: gen_op_neon_abdl_u64(); break;
4031 default: abort();
4032 }
4033 break;
4034 case 8: case 9: case 10: case 11: case 12: case 13:
4035 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4036 switch ((size << 1) | u) {
4037 case 0: gen_op_neon_mull_s8(); break;
4038 case 1: gen_op_neon_mull_u8(); break;
4039 case 2: gen_op_neon_mull_s16(); break;
4040 case 3: gen_op_neon_mull_u16(); break;
4041 case 4: gen_op_imull_T0_T1(); break;
4042 case 5: gen_op_mull_T0_T1(); break;
4043 default: abort();
4044 }
4045 break;
4046 case 14: /* Polynomial VMULL */
4047 cpu_abort(env, "Polynomial VMULL not implemented");
4048
4049 default: /* 15 is RESERVED. */
4050 return 1;
4051 }
4052 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4053 /* Accumulate. */
4054 if (op == 10 || op == 11) {
4055 switch (size) {
4056 case 0: gen_op_neon_negl_u16(); break;
4057 case 1: gen_op_neon_negl_u32(); break;
4058 case 2: gen_op_neon_negl_u64(); break;
4059 default: abort();
4060 }
4061 }
4062
4063 gen_neon_movl_scratch_T0(0);
4064 gen_neon_movl_scratch_T1(1);
4065
4066 if (op != 13) {
4067 NEON_GET_REG(T0, rd, pass * 2);
4068 NEON_GET_REG(T1, rd, pass * 2 + 1);
4069 }
4070
4071 switch (op) {
4072 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4073 switch (size) {
4074 case 0: gen_op_neon_addl_u16(); break;
4075 case 1: gen_op_neon_addl_u32(); break;
4076 case 2: gen_op_neon_addl_u64(); break;
4077 default: abort();
4078 }
4079 break;
4080 case 9: case 11: /* VQDMLAL, VQDMLSL */
4081 switch (size) {
4082 case 1: gen_op_neon_addl_saturate_s32(); break;
4083 case 2: gen_op_neon_addl_saturate_s64(); break;
4084 default: abort();
4085 }
4086 /* Fall through. */
4087 case 13: /* VQDMULL */
4088 switch (size) {
4089 case 1: gen_op_neon_addl_saturate_s32(); break;
4090 case 2: gen_op_neon_addl_saturate_s64(); break;
4091 default: abort();
4092 }
4093 break;
4094 default:
4095 abort();
4096 }
4097 NEON_SET_REG(T0, rd, pass * 2);
4098 NEON_SET_REG(T1, rd, pass * 2 + 1);
4099 } else if (op == 4 || op == 6) {
4100 /* Narrowing operation. */
4101 if (u) {
4102 switch (size) {
4103 case 0: gen_op_neon_narrow_high_u8(); break;
4104 case 1: gen_op_neon_narrow_high_u16(); break;
4105 case 2: gen_op_movl_T0_T1(); break;
4106 default: abort();
4107 }
4108 } else {
4109 switch (size) {
4110 case 0: gen_op_neon_narrow_high_round_u8(); break;
4111 case 1: gen_op_neon_narrow_high_round_u16(); break;
4112 case 2: gen_op_neon_narrow_high_round_u32(); break;
4113 default: abort();
4114 }
4115 }
4116 NEON_SET_REG(T0, rd, pass);
4117 } else {
4118 /* Write back the result. */
4119 NEON_SET_REG(T0, rd, pass * 2);
4120 NEON_SET_REG(T1, rd, pass * 2 + 1);
4121 }
4122 }
4123 } else {
4124 /* Two registers and a scalar. */
4125 switch (op) {
4126 case 0: /* Integer VMLA scalar */
4127 case 1: /* Float VMLA scalar */
4128 case 4: /* Integer VMLS scalar */
4129 case 5: /* Floating point VMLS scalar */
4130 case 8: /* Integer VMUL scalar */
4131 case 9: /* Floating point VMUL scalar */
4132 case 12: /* VQDMULH scalar */
4133 case 13: /* VQRDMULH scalar */
4134 gen_neon_get_scalar(size, rm);
4135 gen_op_movl_T2_T0();
4136 for (pass = 0; pass < (u ? 4 : 2); pass++) {
4137 if (pass != 0)
4138 gen_op_movl_T0_T2();
4139 NEON_GET_REG(T1, rn, pass);
4140 if (op == 12) {
4141 if (size == 1) {
4142 gen_op_neon_qdmulh_s16();
4143 } else {
4144 gen_op_neon_qdmulh_s32();
4145 }
4146 } else if (op == 13) {
4147 if (size == 1) {
4148 gen_op_neon_qrdmulh_s16();
4149 } else {
4150 gen_op_neon_qrdmulh_s32();
4151 }
4152 } else if (op & 1) {
4153 gen_op_neon_mul_f32();
4154 } else {
4155 switch (size) {
4156 case 0: gen_op_neon_mul_u8(); break;
4157 case 1: gen_op_neon_mul_u16(); break;
4158 case 2: gen_op_mul_T0_T1(); break;
4159 default: return 1;
4160 }
4161 }
4162 if (op < 8) {
4163 /* Accumulate. */
4164 NEON_GET_REG(T1, rd, pass);
4165 switch (op) {
4166 case 0:
4167 gen_neon_add(size);
4168 break;
4169 case 1:
4170 gen_op_neon_add_f32();
4171 break;
4172 case 4:
4173 switch (size) {
4174 case 0: gen_op_neon_rsb_u8(); break;
4175 case 1: gen_op_neon_rsb_u16(); break;
4176 case 2: gen_op_rsbl_T0_T1(); break;
4177 default: return 1;
4178 }
4179 break;
4180 case 5:
4181 gen_op_neon_rsb_f32();
4182 break;
4183 default:
4184 abort();
4185 }
4186 }
4187 NEON_SET_REG(T0, rd, pass);
4188 }
4189 break;
4190 case 2: /* VMLAL sclar */
4191 case 3: /* VQDMLAL scalar */
4192 case 6: /* VMLSL scalar */
4193 case 7: /* VQDMLSL scalar */
4194 case 10: /* VMULL scalar */
4195 case 11: /* VQDMULL scalar */
4196 if (rd == rn) {
4197 /* Save overlapping operands before they are
4198 clobbered. */
4199 NEON_GET_REG(T0, rn, 1);
4200 gen_neon_movl_scratch_T0(2);
4201 }
4202 gen_neon_get_scalar(size, rm);
4203 gen_op_movl_T2_T0();
4204 for (pass = 0; pass < 2; pass++) {
4205 if (pass != 0) {
4206 gen_op_movl_T0_T2();
4207 }
4208 if (pass != 0 && rd == rn) {
4209 gen_neon_movl_T1_scratch(2);
4210 } else {
4211 NEON_GET_REG(T1, rn, pass);
4212 }
4213 switch ((size << 1) | u) {
4214 case 0: gen_op_neon_mull_s8(); break;
4215 case 1: gen_op_neon_mull_u8(); break;
4216 case 2: gen_op_neon_mull_s16(); break;
4217 case 3: gen_op_neon_mull_u16(); break;
4218 case 4: gen_op_imull_T0_T1(); break;
4219 case 5: gen_op_mull_T0_T1(); break;
4220 default: abort();
4221 }
4222 if (op == 6 || op == 7) {
4223 switch (size) {
4224 case 0: gen_op_neon_negl_u16(); break;
4225 case 1: gen_op_neon_negl_u32(); break;
4226 case 2: gen_op_neon_negl_u64(); break;
4227 default: abort();
4228 }
4229 }
4230 gen_neon_movl_scratch_T0(0);
4231 gen_neon_movl_scratch_T1(1);
4232 NEON_GET_REG(T0, rd, pass * 2);
4233 NEON_GET_REG(T1, rd, pass * 2 + 1);
4234 switch (op) {
4235 case 2: case 6:
4236 switch (size) {
4237 case 0: gen_op_neon_addl_u16(); break;
4238 case 1: gen_op_neon_addl_u32(); break;
4239 case 2: gen_op_neon_addl_u64(); break;
4240 default: abort();
4241 }
4242 break;
4243 case 3: case 7:
4244 switch (size) {
4245 case 1:
4246 gen_op_neon_addl_saturate_s32();
4247 gen_op_neon_addl_saturate_s32();
4248 break;
4249 case 2:
4250 gen_op_neon_addl_saturate_s64();
4251 gen_op_neon_addl_saturate_s64();
4252 break;
4253 default: abort();
4254 }
4255 break;
4256 case 10:
4257 /* no-op */
4258 break;
4259 case 11:
4260 switch (size) {
4261 case 1: gen_op_neon_addl_saturate_s32(); break;
4262 case 2: gen_op_neon_addl_saturate_s64(); break;
4263 default: abort();
4264 }
4265 break;
4266 default:
4267 abort();
4268 }
4269 NEON_SET_REG(T0, rd, pass * 2);
4270 NEON_SET_REG(T1, rd, pass * 2 + 1);
4271 }
4272 break;
4273 default: /* 14 and 15 are RESERVED */
4274 return 1;
4275 }
4276 }
4277 } else { /* size == 3 */
4278 if (!u) {
4279 /* Extract. */
4280 int reg;
4281 imm = (insn >> 8) & 0xf;
4282 reg = rn;
4283 count = q ? 4 : 2;
4284 n = imm >> 2;
4285 NEON_GET_REG(T0, reg, n);
4286 for (pass = 0; pass < count; pass++) {
4287 n++;
4288 if (n > count) {
4289 reg = rm;
4290 n -= count;
4291 }
4292 if (imm & 3) {
4293 NEON_GET_REG(T1, reg, n);
4294 gen_op_neon_extract((insn << 3) & 0x1f);
4295 }
4296 /* ??? This is broken if rd and rm overlap */
4297 NEON_SET_REG(T0, rd, pass);
4298 if (imm & 3) {
4299 gen_op_movl_T0_T1();
4300 } else {
4301 NEON_GET_REG(T0, reg, n);
4302 }
4303 }
4304 } else if ((insn & (1 << 11)) == 0) {
4305 /* Two register misc. */
4306 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4307 size = (insn >> 18) & 3;
4308 switch (op) {
4309 case 0: /* VREV64 */
4310 if (size == 3)
4311 return 1;
4312 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4313 NEON_GET_REG(T0, rm, pass * 2);
4314 NEON_GET_REG(T1, rm, pass * 2 + 1);
4315 switch (size) {
4316 case 0: gen_op_rev_T0(); break;
4317 case 1: gen_op_revh_T0(); break;
4318 case 2: /* no-op */ break;
4319 default: abort();
4320 }
4321 NEON_SET_REG(T0, rd, pass * 2 + 1);
4322 if (size == 2) {
4323 NEON_SET_REG(T1, rd, pass * 2);
4324 } else {
4325 gen_op_movl_T0_T1();
4326 switch (size) {
4327 case 0: gen_op_rev_T0(); break;
4328 case 1: gen_op_revh_T0(); break;
4329 default: abort();
4330 }
4331 NEON_SET_REG(T0, rd, pass * 2);
4332 }
4333 }
4334 break;
4335 case 4: case 5: /* VPADDL */
4336 case 12: case 13: /* VPADAL */
4337 if (size < 2)
4338 goto elementwise;
4339 if (size == 3)
4340 return 1;
4341 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4342 NEON_GET_REG(T0, rm, pass * 2);
4343 NEON_GET_REG(T1, rm, pass * 2 + 1);
4344 if (op & 1)
4345 gen_op_neon_paddl_u32();
4346 else
4347 gen_op_neon_paddl_s32();
4348 if (op >= 12) {
4349 /* Accumulate. */
4350 gen_neon_movl_scratch_T0(0);
4351 gen_neon_movl_scratch_T1(1);
4352
4353 NEON_GET_REG(T0, rd, pass * 2);
4354 NEON_GET_REG(T1, rd, pass * 2 + 1);
4355 gen_op_neon_addl_u64();
4356 }
4357 NEON_SET_REG(T0, rd, pass * 2);
4358 NEON_SET_REG(T1, rd, pass * 2 + 1);
4359 }
4360 break;
4361 case 33: /* VTRN */
4362 if (size == 2) {
4363 for (n = 0; n < (q ? 4 : 2); n += 2) {
4364 NEON_GET_REG(T0, rm, n);
4365 NEON_GET_REG(T1, rd, n + 1);
4366 NEON_SET_REG(T1, rm, n);
4367 NEON_SET_REG(T0, rd, n + 1);
4368 }
4369 } else {
4370 goto elementwise;
4371 }
4372 break;
4373 case 34: /* VUZP */
4374 /* Reg Before After
4375 Rd A3 A2 A1 A0 B2 B0 A2 A0
4376 Rm B3 B2 B1 B0 B3 B1 A3 A1
4377 */
4378 if (size == 3)
4379 return 1;
4380 gen_neon_unzip(rd, q, 0, size);
4381 gen_neon_unzip(rm, q, 4, size);
4382 if (q) {
4383 static int unzip_order_q[8] =
4384 {0, 2, 4, 6, 1, 3, 5, 7};
4385 for (n = 0; n < 8; n++) {
4386 int reg = (n < 4) ? rd : rm;
4387 gen_neon_movl_T0_scratch(unzip_order_q[n]);
4388 NEON_SET_REG(T0, reg, n % 4);
4389 }
4390 } else {
4391 static int unzip_order[4] =
4392 {0, 4, 1, 5};
4393 for (n = 0; n < 4; n++) {
4394 int reg = (n < 2) ? rd : rm;
4395 gen_neon_movl_T0_scratch(unzip_order[n]);
4396 NEON_SET_REG(T0, reg, n % 2);
4397 }
4398 }
4399 break;
4400 case 35: /* VZIP */
4401 /* Reg Before After
4402 Rd A3 A2 A1 A0 B1 A1 B0 A0
4403 Rm B3 B2 B1 B0 B3 A3 B2 A2
4404 */
4405 if (size == 3)
4406 return 1;
4407 count = (q ? 4 : 2);
4408 for (n = 0; n < count; n++) {
4409 NEON_GET_REG(T0, rd, n);
4410 NEON_GET_REG(T1, rd, n);
4411 switch (size) {
4412 case 0: gen_op_neon_zip_u8(); break;
4413 case 1: gen_op_neon_zip_u16(); break;
4414 case 2: /* no-op */; break;
4415 default: abort();
4416 }
4417 gen_neon_movl_scratch_T0(n * 2);
4418 gen_neon_movl_scratch_T1(n * 2 + 1);
4419 }
4420 for (n = 0; n < count * 2; n++) {
4421 int reg = (n < count) ? rd : rm;
4422 gen_neon_movl_T0_scratch(n);
4423 NEON_SET_REG(T0, reg, n % count);
4424 }
4425 break;
4426 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4427 for (pass = 0; pass < 2; pass++) {
4428 if (rd == rm + 1) {
4429 n = 1 - pass;
4430 } else {
4431 n = pass;
4432 }
4433 NEON_GET_REG(T0, rm, n * 2);
4434 NEON_GET_REG(T1, rm, n * 2 + 1);
4435 if (op == 36 && q == 0) {
4436 switch (size) {
4437 case 0: gen_op_neon_narrow_u8(); break;
4438 case 1: gen_op_neon_narrow_u16(); break;
4439 case 2: /* no-op */ break;
4440 default: return 1;
4441 }
4442 } else if (q) {
4443 switch (size) {
4444 case 0: gen_op_neon_narrow_sat_u8(); break;
4445 case 1: gen_op_neon_narrow_sat_u16(); break;
4446 case 2: gen_op_neon_narrow_sat_u32(); break;
4447 default: return 1;
4448 }
4449 } else {
4450 switch (size) {
4451 case 0: gen_op_neon_narrow_sat_s8(); break;
4452 case 1: gen_op_neon_narrow_sat_s16(); break;
4453 case 2: gen_op_neon_narrow_sat_s32(); break;
4454 default: return 1;
4455 }
4456 }
4457 NEON_SET_REG(T0, rd, n);
4458 }
4459 break;
4460 case 38: /* VSHLL */
4461 if (q)
4462 return 1;
4463 if (rm == rd) {
4464 NEON_GET_REG(T2, rm, 1);
4465 }
4466 for (pass = 0; pass < 2; pass++) {
4467 if (pass == 1 && rm == rd) {
4468 gen_op_movl_T0_T2();
4469 } else {
4470 NEON_GET_REG(T0, rm, pass);
4471 }
4472 switch (size) {
4473 case 0: gen_op_neon_widen_high_u8(); break;
4474 case 1: gen_op_neon_widen_high_u16(); break;
4475 case 2:
4476 gen_op_movl_T1_T0();
4477 gen_op_movl_T0_im(0);
4478 break;
4479 default: return 1;
4480 }
4481 NEON_SET_REG(T0, rd, pass * 2);
4482 NEON_SET_REG(T1, rd, pass * 2 + 1);
4483 }
4484 break;
4485 default:
4486 elementwise:
4487 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4488 if (op == 30 || op == 31 || op >= 58) {
4489 gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4490 } else {
4491 NEON_GET_REG(T0, rm, pass);
4492 }
4493 switch (op) {
4494 case 1: /* VREV32 */
4495 switch (size) {
4496 case 0: gen_op_rev_T0(); break;
4497 case 1: gen_op_revh_T0(); break;
4498 default: return 1;
4499 }
4500 break;
4501 case 2: /* VREV16 */
4502 if (size != 0)
4503 return 1;
4504 gen_op_rev16_T0();
4505 break;
4506 case 4: case 5: /* VPADDL */
4507 case 12: case 13: /* VPADAL */
4508 switch ((size << 1) | (op & 1)) {
4509 case 0: gen_op_neon_paddl_s8(); break;
4510 case 1: gen_op_neon_paddl_u8(); break;
4511 case 2: gen_op_neon_paddl_s16(); break;
4512 case 3: gen_op_neon_paddl_u16(); break;
4513 default: abort();
4514 }
4515 if (op >= 12) {
4516 /* Accumulate */
4517 NEON_GET_REG(T1, rd, pass);
4518 switch (size) {
4519 case 0: gen_op_neon_add_u16(); break;
4520 case 1: gen_op_addl_T0_T1(); break;
4521 default: abort();
4522 }
4523 }
4524 break;
4525 case 8: /* CLS */
4526 switch (size) {
4527 case 0: gen_op_neon_cls_s8(); break;
4528 case 1: gen_op_neon_cls_s16(); break;
4529 case 2: gen_op_neon_cls_s32(); break;
4530 default: return 1;
4531 }
4532 break;
4533 case 9: /* CLZ */
4534 switch (size) {
4535 case 0: gen_op_neon_clz_u8(); break;
4536 case 1: gen_op_neon_clz_u16(); break;
1497c961 4537 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
9ee6e8bb
PB
4538 default: return 1;
4539 }
4540 break;
4541 case 10: /* CNT */
4542 if (size != 0)
4543 return 1;
4544 gen_op_neon_cnt_u8();
4545 break;
4546 case 11: /* VNOT */
4547 if (size != 0)
4548 return 1;
4549 gen_op_notl_T0();
4550 break;
4551 case 14: /* VQABS */
4552 switch (size) {
4553 case 0: gen_op_neon_qabs_s8(); break;
4554 case 1: gen_op_neon_qabs_s16(); break;
4555 case 2: gen_op_neon_qabs_s32(); break;
4556 default: return 1;
4557 }
4558 break;
4559 case 15: /* VQNEG */
4560 switch (size) {
4561 case 0: gen_op_neon_qneg_s8(); break;
4562 case 1: gen_op_neon_qneg_s16(); break;
4563 case 2: gen_op_neon_qneg_s32(); break;
4564 default: return 1;
4565 }
4566 break;
4567 case 16: case 19: /* VCGT #0, VCLE #0 */
4568 gen_op_movl_T1_im(0);
4569 switch(size) {
4570 case 0: gen_op_neon_cgt_s8(); break;
4571 case 1: gen_op_neon_cgt_s16(); break;
4572 case 2: gen_op_neon_cgt_s32(); break;
4573 default: return 1;
4574 }
4575 if (op == 19)
4576 gen_op_notl_T0();
4577 break;
4578 case 17: case 20: /* VCGE #0, VCLT #0 */
4579 gen_op_movl_T1_im(0);
4580 switch(size) {
4581 case 0: gen_op_neon_cge_s8(); break;
4582 case 1: gen_op_neon_cge_s16(); break;
4583 case 2: gen_op_neon_cge_s32(); break;
4584 default: return 1;
4585 }
4586 if (op == 20)
4587 gen_op_notl_T0();
4588 break;
4589 case 18: /* VCEQ #0 */
4590 gen_op_movl_T1_im(0);
4591 switch(size) {
4592 case 0: gen_op_neon_ceq_u8(); break;
4593 case 1: gen_op_neon_ceq_u16(); break;
4594 case 2: gen_op_neon_ceq_u32(); break;
4595 default: return 1;
4596 }
4597 break;
4598 case 22: /* VABS */
4599 switch(size) {
4600 case 0: gen_op_neon_abs_s8(); break;
4601 case 1: gen_op_neon_abs_s16(); break;
4602 case 2: gen_op_neon_abs_s32(); break;
4603 default: return 1;
4604 }
4605 break;
4606 case 23: /* VNEG */
4607 gen_op_movl_T1_im(0);
4608 switch(size) {
4609 case 0: gen_op_neon_rsb_u8(); break;
4610 case 1: gen_op_neon_rsb_u16(); break;
4611 case 2: gen_op_rsbl_T0_T1(); break;
4612 default: return 1;
4613 }
4614 break;
4615 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4616 gen_op_movl_T1_im(0);
4617 gen_op_neon_cgt_f32();
4618 if (op == 27)
4619 gen_op_notl_T0();
4620 break;
4621 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4622 gen_op_movl_T1_im(0);
4623 gen_op_neon_cge_f32();
4624 if (op == 28)
4625 gen_op_notl_T0();
4626 break;
4627 case 26: /* Float VCEQ #0 */
4628 gen_op_movl_T1_im(0);
4629 gen_op_neon_ceq_f32();
4630 break;
4631 case 30: /* Float VABS */
4632 gen_op_vfp_abss();
4633 break;
4634 case 31: /* Float VNEG */
4635 gen_op_vfp_negs();
4636 break;
4637 case 32: /* VSWP */
4638 NEON_GET_REG(T1, rd, pass);
4639 NEON_SET_REG(T1, rm, pass);
4640 break;
4641 case 33: /* VTRN */
4642 NEON_GET_REG(T1, rd, pass);
4643 switch (size) {
4644 case 0: gen_op_neon_trn_u8(); break;
4645 case 1: gen_op_neon_trn_u16(); break;
4646 case 2: abort();
4647 default: return 1;
4648 }
4649 NEON_SET_REG(T1, rm, pass);
4650 break;
4651 case 56: /* Integer VRECPE */
4652 gen_op_neon_recpe_u32();
4653 break;
4654 case 57: /* Integer VRSQRTE */
4655 gen_op_neon_rsqrte_u32();
4656 break;
4657 case 58: /* Float VRECPE */
4658 gen_op_neon_recpe_f32();
4659 break;
4660 case 59: /* Float VRSQRTE */
4661 gen_op_neon_rsqrte_f32();
4662 break;
4663 case 60: /* VCVT.F32.S32 */
4664 gen_op_vfp_tosizs();
4665 break;
4666 case 61: /* VCVT.F32.U32 */
4667 gen_op_vfp_touizs();
4668 break;
4669 case 62: /* VCVT.S32.F32 */
4670 gen_op_vfp_sitos();
4671 break;
4672 case 63: /* VCVT.U32.F32 */
4673 gen_op_vfp_uitos();
4674 break;
4675 default:
4676 /* Reserved: 21, 29, 39-56 */
4677 return 1;
4678 }
4679 if (op == 30 || op == 31 || op >= 58) {
4680 gen_op_vfp_setreg_F0s(neon_reg_offset(rm, pass));
4681 } else {
4682 NEON_SET_REG(T0, rd, pass);
4683 }
4684 }
4685 break;
4686 }
4687 } else if ((insn & (1 << 10)) == 0) {
4688 /* VTBL, VTBX. */
4689 n = (insn >> 5) & 0x18;
4690 NEON_GET_REG(T1, rm, 0);
4691 if (insn & (1 << 6)) {
4692 NEON_GET_REG(T0, rd, 0);
4693 } else {
4694 gen_op_movl_T0_im(0);
4695 }
4696 gen_op_neon_tbl(rn, n);
4697 gen_op_movl_T2_T0();
4698 NEON_GET_REG(T1, rm, 1);
4699 if (insn & (1 << 6)) {
4700 NEON_GET_REG(T0, rd, 0);
4701 } else {
4702 gen_op_movl_T0_im(0);
4703 }
4704 gen_op_neon_tbl(rn, n);
4705 NEON_SET_REG(T2, rd, 0);
4706 NEON_SET_REG(T0, rd, 1);
4707 } else if ((insn & 0x380) == 0) {
4708 /* VDUP */
4709 if (insn & (1 << 19)) {
4710 NEON_SET_REG(T0, rm, 1);
4711 } else {
4712 NEON_SET_REG(T0, rm, 0);
4713 }
4714 if (insn & (1 << 16)) {
4715 gen_op_neon_dup_u8(((insn >> 17) & 3) * 8);
4716 } else if (insn & (1 << 17)) {
4717 if ((insn >> 18) & 1)
4718 gen_op_neon_dup_high16();
4719 else
4720 gen_op_neon_dup_low16();
4721 }
4722 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4723 NEON_SET_REG(T0, rd, pass);
4724 }
4725 } else {
4726 return 1;
4727 }
4728 }
4729 }
4730 return 0;
4731}
4732
4733static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
4734{
4735 int cpnum;
4736
4737 cpnum = (insn >> 8) & 0xf;
4738 if (arm_feature(env, ARM_FEATURE_XSCALE)
4739 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
4740 return 1;
4741
4742 switch (cpnum) {
4743 case 0:
4744 case 1:
4745 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4746 return disas_iwmmxt_insn(env, s, insn);
4747 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
4748 return disas_dsp_insn(env, s, insn);
4749 }
4750 return 1;
4751 case 10:
4752 case 11:
4753 return disas_vfp_insn (env, s, insn);
4754 case 15:
4755 return disas_cp15_insn (env, s, insn);
4756 default:
4757 /* Unknown coprocessor. See if the board has hooked it. */
4758 return disas_cp_insn (env, s, insn);
4759 }
4760}
4761
4762static void disas_arm_insn(CPUState * env, DisasContext *s)
4763{
4764 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
b26eefb6 4765 TCGv tmp;
9ee6e8bb
PB
4766
4767 insn = ldl_code(s->pc);
4768 s->pc += 4;
4769
4770 /* M variants do not implement ARM mode. */
4771 if (IS_M(env))
4772 goto illegal_op;
4773 cond = insn >> 28;
4774 if (cond == 0xf){
4775 /* Unconditional instructions. */
4776 if (((insn >> 25) & 7) == 1) {
4777 /* NEON Data processing. */
4778 if (!arm_feature(env, ARM_FEATURE_NEON))
4779 goto illegal_op;
4780
4781 if (disas_neon_data_insn(env, s, insn))
4782 goto illegal_op;
4783 return;
4784 }
4785 if ((insn & 0x0f100000) == 0x04000000) {
4786 /* NEON load/store. */
4787 if (!arm_feature(env, ARM_FEATURE_NEON))
4788 goto illegal_op;
4789
4790 if (disas_neon_ls_insn(env, s, insn))
4791 goto illegal_op;
4792 return;
4793 }
4794 if ((insn & 0x0d70f000) == 0x0550f000)
4795 return; /* PLD */
4796 else if ((insn & 0x0ffffdff) == 0x01010000) {
4797 ARCH(6);
4798 /* setend */
4799 if (insn & (1 << 9)) {
4800 /* BE8 mode not implemented. */
4801 goto illegal_op;
4802 }
4803 return;
4804 } else if ((insn & 0x0fffff00) == 0x057ff000) {
4805 switch ((insn >> 4) & 0xf) {
4806 case 1: /* clrex */
4807 ARCH(6K);
4808 gen_op_clrex();
4809 return;
4810 case 4: /* dsb */
4811 case 5: /* dmb */
4812 case 6: /* isb */
4813 ARCH(7);
4814 /* We don't emulate caches so these are a no-op. */
4815 return;
4816 default:
4817 goto illegal_op;
4818 }
4819 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
4820 /* srs */
4821 uint32_t offset;
4822 if (IS_USER(s))
4823 goto illegal_op;
4824 ARCH(6);
4825 op1 = (insn & 0x1f);
4826 if (op1 == (env->uncached_cpsr & CPSR_M)) {
4827 gen_movl_T1_reg(s, 13);
4828 } else {
4829 gen_op_movl_T1_r13_banked(op1);
4830 }
4831 i = (insn >> 23) & 3;
4832 switch (i) {
4833 case 0: offset = -4; break; /* DA */
4834 case 1: offset = -8; break; /* DB */
4835 case 2: offset = 0; break; /* IA */
4836 case 3: offset = 4; break; /* IB */
4837 default: abort();
4838 }
4839 if (offset)
4840 gen_op_addl_T1_im(offset);
4841 gen_movl_T0_reg(s, 14);
4842 gen_ldst(stl, s);
4843 gen_op_movl_T0_cpsr();
4844 gen_op_addl_T1_im(4);
4845 gen_ldst(stl, s);
4846 if (insn & (1 << 21)) {
4847 /* Base writeback. */
4848 switch (i) {
4849 case 0: offset = -8; break;
4850 case 1: offset = -4; break;
4851 case 2: offset = 4; break;
4852 case 3: offset = 0; break;
4853 default: abort();
4854 }
4855 if (offset)
4856 gen_op_addl_T1_im(offset);
4857 if (op1 == (env->uncached_cpsr & CPSR_M)) {
4858 gen_movl_reg_T1(s, 13);
4859 } else {
4860 gen_op_movl_r13_T1_banked(op1);
4861 }
4862 }
4863 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
4864 /* rfe */
4865 uint32_t offset;
4866 if (IS_USER(s))
4867 goto illegal_op;
4868 ARCH(6);
4869 rn = (insn >> 16) & 0xf;
4870 gen_movl_T1_reg(s, rn);
4871 i = (insn >> 23) & 3;
4872 switch (i) {
4873 case 0: offset = 0; break; /* DA */
4874 case 1: offset = -4; break; /* DB */
4875 case 2: offset = 4; break; /* IA */
4876 case 3: offset = 8; break; /* IB */
4877 default: abort();
4878 }
4879 if (offset)
4880 gen_op_addl_T1_im(offset);
4881 /* Load CPSR into T2 and PC into T0. */
4882 gen_ldst(ldl, s);
4883 gen_op_movl_T2_T0();
4884 gen_op_addl_T1_im(-4);
4885 gen_ldst(ldl, s);
4886 if (insn & (1 << 21)) {
4887 /* Base writeback. */
4888 switch (i) {
4889 case 0: offset = -4; break;
4890 case 1: offset = 0; break;
4891 case 2: offset = 8; break;
4892 case 3: offset = 4; break;
4893 default: abort();
4894 }
4895 if (offset)
4896 gen_op_addl_T1_im(offset);
4897 gen_movl_reg_T1(s, rn);
4898 }
4899 gen_rfe(s);
4900 } else if ((insn & 0x0e000000) == 0x0a000000) {
4901 /* branch link and change to thumb (blx <offset>) */
4902 int32_t offset;
4903
4904 val = (uint32_t)s->pc;
4905 gen_op_movl_T0_im(val);
4906 gen_movl_reg_T0(s, 14);
4907 /* Sign-extend the 24-bit offset */
4908 offset = (((int32_t)insn) << 8) >> 8;
4909 /* offset * 4 + bit24 * 2 + (thumb bit) */
4910 val += (offset << 2) | ((insn >> 23) & 2) | 1;
4911 /* pipeline offset */
4912 val += 4;
4913 gen_op_movl_T0_im(val);
4914 gen_bx(s);
4915 return;
4916 } else if ((insn & 0x0e000f00) == 0x0c000100) {
4917 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4918 /* iWMMXt register transfer. */
4919 if (env->cp15.c15_cpar & (1 << 1))
4920 if (!disas_iwmmxt_insn(env, s, insn))
4921 return;
4922 }
4923 } else if ((insn & 0x0fe00000) == 0x0c400000) {
4924 /* Coprocessor double register transfer. */
4925 } else if ((insn & 0x0f000010) == 0x0e000010) {
4926 /* Additional coprocessor register transfer. */
4927 } else if ((insn & 0x0ff10010) == 0x01000000) {
4928 uint32_t mask;
4929 uint32_t val;
4930 /* cps (privileged) */
4931 if (IS_USER(s))
4932 return;
4933 mask = val = 0;
4934 if (insn & (1 << 19)) {
4935 if (insn & (1 << 8))
4936 mask |= CPSR_A;
4937 if (insn & (1 << 7))
4938 mask |= CPSR_I;
4939 if (insn & (1 << 6))
4940 mask |= CPSR_F;
4941 if (insn & (1 << 18))
4942 val |= mask;
4943 }
4944 if (insn & (1 << 14)) {
4945 mask |= CPSR_M;
4946 val |= (insn & 0x1f);
4947 }
4948 if (mask) {
4949 gen_op_movl_T0_im(val);
4950 gen_set_psr_T0(s, mask, 0);
4951 }
4952 return;
4953 }
4954 goto illegal_op;
4955 }
4956 if (cond != 0xe) {
4957 /* if not always execute, we generate a conditional jump to
4958 next instruction */
4959 s->condlabel = gen_new_label();
4960 gen_test_cc[cond ^ 1](s->condlabel);
4961 s->condjmp = 1;
4962 }
4963 if ((insn & 0x0f900000) == 0x03000000) {
4964 if ((insn & (1 << 21)) == 0) {
4965 ARCH(6T2);
4966 rd = (insn >> 12) & 0xf;
4967 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
4968 if ((insn & (1 << 22)) == 0) {
4969 /* MOVW */
4970 gen_op_movl_T0_im(val);
4971 } else {
4972 /* MOVT */
4973 gen_movl_T0_reg(s, rd);
4974 gen_op_movl_T1_im(0xffff);
4975 gen_op_andl_T0_T1();
4976 gen_op_movl_T1_im(val << 16);
4977 gen_op_orl_T0_T1();
4978 }
4979 gen_movl_reg_T0(s, rd);
4980 } else {
4981 if (((insn >> 12) & 0xf) != 0xf)
4982 goto illegal_op;
4983 if (((insn >> 16) & 0xf) == 0) {
4984 gen_nop_hint(s, insn & 0xff);
4985 } else {
4986 /* CPSR = immediate */
4987 val = insn & 0xff;
4988 shift = ((insn >> 8) & 0xf) * 2;
4989 if (shift)
4990 val = (val >> shift) | (val << (32 - shift));
4991 gen_op_movl_T0_im(val);
4992 i = ((insn & (1 << 22)) != 0);
4993 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
4994 goto illegal_op;
4995 }
4996 }
4997 } else if ((insn & 0x0f900000) == 0x01000000
4998 && (insn & 0x00000090) != 0x00000090) {
4999 /* miscellaneous instructions */
5000 op1 = (insn >> 21) & 3;
5001 sh = (insn >> 4) & 0xf;
5002 rm = insn & 0xf;
5003 switch (sh) {
5004 case 0x0: /* move program status register */
5005 if (op1 & 1) {
5006 /* PSR = reg */
5007 gen_movl_T0_reg(s, rm);
5008 i = ((op1 & 2) != 0);
5009 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5010 goto illegal_op;
5011 } else {
5012 /* reg = PSR */
5013 rd = (insn >> 12) & 0xf;
5014 if (op1 & 2) {
5015 if (IS_USER(s))
5016 goto illegal_op;
5017 gen_op_movl_T0_spsr();
5018 } else {
5019 gen_op_movl_T0_cpsr();
5020 }
5021 gen_movl_reg_T0(s, rd);
5022 }
5023 break;
5024 case 0x1:
5025 if (op1 == 1) {
5026 /* branch/exchange thumb (bx). */
5027 gen_movl_T0_reg(s, rm);
5028 gen_bx(s);
5029 } else if (op1 == 3) {
5030 /* clz */
5031 rd = (insn >> 12) & 0xf;
1497c961
PB
5032 tmp = load_reg(s, rm);
5033 gen_helper_clz(tmp, tmp);
5034 store_reg(s, rd, tmp);
9ee6e8bb
PB
5035 } else {
5036 goto illegal_op;
5037 }
5038 break;
5039 case 0x2:
5040 if (op1 == 1) {
5041 ARCH(5J); /* bxj */
5042 /* Trivial implementation equivalent to bx. */
5043 gen_movl_T0_reg(s, rm);
5044 gen_bx(s);
5045 } else {
5046 goto illegal_op;
5047 }
5048 break;
5049 case 0x3:
5050 if (op1 != 1)
5051 goto illegal_op;
5052
5053 /* branch link/exchange thumb (blx) */
5054 val = (uint32_t)s->pc;
5055 gen_op_movl_T1_im(val);
5056 gen_movl_T0_reg(s, rm);
5057 gen_movl_reg_T1(s, 14);
5058 gen_bx(s);
5059 break;
5060 case 0x5: /* saturating add/subtract */
5061 rd = (insn >> 12) & 0xf;
5062 rn = (insn >> 16) & 0xf;
5063 gen_movl_T0_reg(s, rm);
5064 gen_movl_T1_reg(s, rn);
5065 if (op1 & 2)
1497c961 5066 gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
9ee6e8bb
PB
5067 if (op1 & 1)
5068 gen_op_subl_T0_T1_saturate();
5069 else
5070 gen_op_addl_T0_T1_saturate();
5071 gen_movl_reg_T0(s, rd);
5072 break;
5073 case 7: /* bkpt */
5074 gen_set_condexec(s);
5075 gen_op_movl_T0_im((long)s->pc - 4);
b26eefb6 5076 gen_set_pc_T0();
9ee6e8bb
PB
5077 gen_op_bkpt();
5078 s->is_jmp = DISAS_JUMP;
5079 break;
5080 case 0x8: /* signed multiply */
5081 case 0xa:
5082 case 0xc:
5083 case 0xe:
5084 rs = (insn >> 8) & 0xf;
5085 rn = (insn >> 12) & 0xf;
5086 rd = (insn >> 16) & 0xf;
5087 if (op1 == 1) {
5088 /* (32 * 16) >> 16 */
5089 gen_movl_T0_reg(s, rm);
5090 gen_movl_T1_reg(s, rs);
5091 if (sh & 4)
5092 gen_op_sarl_T1_im(16);
5093 else
b26eefb6 5094 gen_sxth(cpu_T[1]);
9ee6e8bb
PB
5095 gen_op_imulw_T0_T1();
5096 if ((sh & 2) == 0) {
5097 gen_movl_T1_reg(s, rn);
5098 gen_op_addl_T0_T1_setq();
5099 }
5100 gen_movl_reg_T0(s, rd);
5101 } else {
5102 /* 16 * 16 */
5103 gen_movl_T0_reg(s, rm);
5104 gen_movl_T1_reg(s, rs);
5105 gen_mulxy(sh & 2, sh & 4);
5106 if (op1 == 2) {
5107 gen_op_signbit_T1_T0();
5108 gen_op_addq_T0_T1(rn, rd);
5109 gen_movl_reg_T0(s, rn);
5110 gen_movl_reg_T1(s, rd);
5111 } else {
5112 if (op1 == 0) {
5113 gen_movl_T1_reg(s, rn);
5114 gen_op_addl_T0_T1_setq();
5115 }
5116 gen_movl_reg_T0(s, rd);
5117 }
5118 }
5119 break;
5120 default:
5121 goto illegal_op;
5122 }
5123 } else if (((insn & 0x0e000000) == 0 &&
5124 (insn & 0x00000090) != 0x90) ||
5125 ((insn & 0x0e000000) == (1 << 25))) {
5126 int set_cc, logic_cc, shiftop;
5127
5128 op1 = (insn >> 21) & 0xf;
5129 set_cc = (insn >> 20) & 1;
5130 logic_cc = table_logic_cc[op1] & set_cc;
5131
5132 /* data processing instruction */
5133 if (insn & (1 << 25)) {
5134 /* immediate operand */
5135 val = insn & 0xff;
5136 shift = ((insn >> 8) & 0xf) * 2;
5137 if (shift)
5138 val = (val >> shift) | (val << (32 - shift));
5139 gen_op_movl_T1_im(val);
5140 if (logic_cc && shift)
b26eefb6 5141 gen_set_CF_bit31(cpu_T[1]);
9ee6e8bb
PB
5142 } else {
5143 /* register */
5144 rm = (insn) & 0xf;
5145 gen_movl_T1_reg(s, rm);
5146 shiftop = (insn >> 5) & 3;
5147 if (!(insn & (1 << 4))) {
5148 shift = (insn >> 7) & 0x1f;
9a119ff6 5149 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
9ee6e8bb
PB
5150 } else {
5151 rs = (insn >> 8) & 0xf;
5152 gen_movl_T0_reg(s, rs);
5153 if (logic_cc) {
5154 gen_shift_T1_T0_cc[shiftop]();
5155 } else {
5156 gen_shift_T1_T0[shiftop]();
5157 }
5158 }
5159 }
5160 if (op1 != 0x0f && op1 != 0x0d) {
5161 rn = (insn >> 16) & 0xf;
5162 gen_movl_T0_reg(s, rn);
5163 }
5164 rd = (insn >> 12) & 0xf;
5165 switch(op1) {
5166 case 0x00:
5167 gen_op_andl_T0_T1();
5168 gen_movl_reg_T0(s, rd);
5169 if (logic_cc)
5170 gen_op_logic_T0_cc();
5171 break;
5172 case 0x01:
5173 gen_op_xorl_T0_T1();
5174 gen_movl_reg_T0(s, rd);
5175 if (logic_cc)
5176 gen_op_logic_T0_cc();
5177 break;
5178 case 0x02:
5179 if (set_cc && rd == 15) {
5180 /* SUBS r15, ... is used for exception return. */
5181 if (IS_USER(s))
5182 goto illegal_op;
5183 gen_op_subl_T0_T1_cc();
5184 gen_exception_return(s);
5185 } else {
5186 if (set_cc)
5187 gen_op_subl_T0_T1_cc();
5188 else
5189 gen_op_subl_T0_T1();
5190 gen_movl_reg_T0(s, rd);
5191 }
5192 break;
5193 case 0x03:
5194 if (set_cc)
5195 gen_op_rsbl_T0_T1_cc();
5196 else
5197 gen_op_rsbl_T0_T1();
5198 gen_movl_reg_T0(s, rd);
5199 break;
5200 case 0x04:
5201 if (set_cc)
5202 gen_op_addl_T0_T1_cc();
5203 else
5204 gen_op_addl_T0_T1();
5205 gen_movl_reg_T0(s, rd);
5206 break;
5207 case 0x05:
5208 if (set_cc)
5209 gen_op_adcl_T0_T1_cc();
5210 else
b26eefb6 5211 gen_adc_T0_T1();
9ee6e8bb
PB
5212 gen_movl_reg_T0(s, rd);
5213 break;
5214 case 0x06:
5215 if (set_cc)
5216 gen_op_sbcl_T0_T1_cc();
5217 else
5218 gen_op_sbcl_T0_T1();
5219 gen_movl_reg_T0(s, rd);
5220 break;
5221 case 0x07:
5222 if (set_cc)
5223 gen_op_rscl_T0_T1_cc();
5224 else
5225 gen_op_rscl_T0_T1();
5226 gen_movl_reg_T0(s, rd);
5227 break;
5228 case 0x08:
5229 if (set_cc) {
5230 gen_op_andl_T0_T1();
5231 gen_op_logic_T0_cc();
5232 }
5233 break;
5234 case 0x09:
5235 if (set_cc) {
5236 gen_op_xorl_T0_T1();
5237 gen_op_logic_T0_cc();
5238 }
5239 break;
5240 case 0x0a:
5241 if (set_cc) {
5242 gen_op_subl_T0_T1_cc();
5243 }
5244 break;
5245 case 0x0b:
5246 if (set_cc) {
5247 gen_op_addl_T0_T1_cc();
5248 }
5249 break;
5250 case 0x0c:
5251 gen_op_orl_T0_T1();
5252 gen_movl_reg_T0(s, rd);
5253 if (logic_cc)
5254 gen_op_logic_T0_cc();
5255 break;
5256 case 0x0d:
5257 if (logic_cc && rd == 15) {
5258 /* MOVS r15, ... is used for exception return. */
5259 if (IS_USER(s))
5260 goto illegal_op;
5261 gen_op_movl_T0_T1();
5262 gen_exception_return(s);
5263 } else {
5264 gen_movl_reg_T1(s, rd);
5265 if (logic_cc)
5266 gen_op_logic_T1_cc();
5267 }
5268 break;
5269 case 0x0e:
5270 gen_op_bicl_T0_T1();
5271 gen_movl_reg_T0(s, rd);
5272 if (logic_cc)
5273 gen_op_logic_T0_cc();
5274 break;
5275 default:
5276 case 0x0f:
5277 gen_op_notl_T1();
5278 gen_movl_reg_T1(s, rd);
5279 if (logic_cc)
5280 gen_op_logic_T1_cc();
5281 break;
5282 }
5283 } else {
5284 /* other instructions */
5285 op1 = (insn >> 24) & 0xf;
5286 switch(op1) {
5287 case 0x0:
5288 case 0x1:
5289 /* multiplies, extra load/stores */
5290 sh = (insn >> 5) & 3;
5291 if (sh == 0) {
5292 if (op1 == 0x0) {
5293 rd = (insn >> 16) & 0xf;
5294 rn = (insn >> 12) & 0xf;
5295 rs = (insn >> 8) & 0xf;
5296 rm = (insn) & 0xf;
5297 op1 = (insn >> 20) & 0xf;
5298 switch (op1) {
5299 case 0: case 1: case 2: case 3: case 6:
5300 /* 32 bit mul */
5301 gen_movl_T0_reg(s, rs);
5302 gen_movl_T1_reg(s, rm);
5303 gen_op_mul_T0_T1();
5304 if (insn & (1 << 22)) {
5305 /* Subtract (mls) */
5306 ARCH(6T2);
5307 gen_movl_T1_reg(s, rn);
5308 gen_op_rsbl_T0_T1();
5309 } else if (insn & (1 << 21)) {
5310 /* Add */
5311 gen_movl_T1_reg(s, rn);
5312 gen_op_addl_T0_T1();
5313 }
5314 if (insn & (1 << 20))
5315 gen_op_logic_T0_cc();
5316 gen_movl_reg_T0(s, rd);
5317 break;
5318 default:
5319 /* 64 bit mul */
5320 gen_movl_T0_reg(s, rs);
5321 gen_movl_T1_reg(s, rm);
5322 if (insn & (1 << 22))
5323 gen_op_imull_T0_T1();
5324 else
5325 gen_op_mull_T0_T1();
5326 if (insn & (1 << 21)) /* mult accumulate */
5327 gen_op_addq_T0_T1(rn, rd);
5328 if (!(insn & (1 << 23))) { /* double accumulate */
5329 ARCH(6);
5330 gen_op_addq_lo_T0_T1(rn);
5331 gen_op_addq_lo_T0_T1(rd);
5332 }
5333 if (insn & (1 << 20))
5334 gen_op_logicq_cc();
5335 gen_movl_reg_T0(s, rn);
5336 gen_movl_reg_T1(s, rd);
5337 break;
5338 }
5339 } else {
5340 rn = (insn >> 16) & 0xf;
5341 rd = (insn >> 12) & 0xf;
5342 if (insn & (1 << 23)) {
5343 /* load/store exclusive */
5344 gen_movl_T1_reg(s, rn);
5345 if (insn & (1 << 20)) {
5346 gen_ldst(ldlex, s);
5347 } else {
5348 rm = insn & 0xf;
5349 gen_movl_T0_reg(s, rm);
5350 gen_ldst(stlex, s);
5351 }
5352 gen_movl_reg_T0(s, rd);
5353 } else {
5354 /* SWP instruction */
5355 rm = (insn) & 0xf;
5356
5357 gen_movl_T0_reg(s, rm);
5358 gen_movl_T1_reg(s, rn);
5359 if (insn & (1 << 22)) {
5360 gen_ldst(swpb, s);
5361 } else {
5362 gen_ldst(swpl, s);
5363 }
5364 gen_movl_reg_T0(s, rd);
5365 }
5366 }
5367 } else {
5368 int address_offset;
5369 int load;
5370 /* Misc load/store */
5371 rn = (insn >> 16) & 0xf;
5372 rd = (insn >> 12) & 0xf;
5373 gen_movl_T1_reg(s, rn);
5374 if (insn & (1 << 24))
5375 gen_add_datah_offset(s, insn, 0);
5376 address_offset = 0;
5377 if (insn & (1 << 20)) {
5378 /* load */
5379 switch(sh) {
5380 case 1:
5381 gen_ldst(lduw, s);
5382 break;
5383 case 2:
5384 gen_ldst(ldsb, s);
5385 break;
5386 default:
5387 case 3:
5388 gen_ldst(ldsw, s);
5389 break;
5390 }
5391 load = 1;
5392 } else if (sh & 2) {
5393 /* doubleword */
5394 if (sh & 1) {
5395 /* store */
5396 gen_movl_T0_reg(s, rd);
5397 gen_ldst(stl, s);
5398 gen_op_addl_T1_im(4);
5399 gen_movl_T0_reg(s, rd + 1);
5400 gen_ldst(stl, s);
5401 load = 0;
5402 } else {
5403 /* load */
5404 gen_ldst(ldl, s);
5405 gen_movl_reg_T0(s, rd);
5406 gen_op_addl_T1_im(4);
5407 gen_ldst(ldl, s);
5408 rd++;
5409 load = 1;
5410 }
5411 address_offset = -4;
5412 } else {
5413 /* store */
5414 gen_movl_T0_reg(s, rd);
5415 gen_ldst(stw, s);
5416 load = 0;
5417 }
5418 /* Perform base writeback before the loaded value to
5419 ensure correct behavior with overlapping index registers.
5420 ldrd with base writeback is is undefined if the
5421 destination and index registers overlap. */
5422 if (!(insn & (1 << 24))) {
5423 gen_add_datah_offset(s, insn, address_offset);
5424 gen_movl_reg_T1(s, rn);
5425 } else if (insn & (1 << 21)) {
5426 if (address_offset)
5427 gen_op_addl_T1_im(address_offset);
5428 gen_movl_reg_T1(s, rn);
5429 }
5430 if (load) {
5431 /* Complete the load. */
5432 gen_movl_reg_T0(s, rd);
5433 }
5434 }
5435 break;
5436 case 0x4:
5437 case 0x5:
5438 goto do_ldst;
5439 case 0x6:
5440 case 0x7:
5441 if (insn & (1 << 4)) {
5442 ARCH(6);
5443 /* Armv6 Media instructions. */
5444 rm = insn & 0xf;
5445 rn = (insn >> 16) & 0xf;
2c0262af 5446 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
5447 rs = (insn >> 8) & 0xf;
5448 switch ((insn >> 23) & 3) {
5449 case 0: /* Parallel add/subtract. */
5450 op1 = (insn >> 20) & 7;
5451 gen_movl_T0_reg(s, rn);
5452 gen_movl_T1_reg(s, rm);
5453 sh = (insn >> 5) & 7;
5454 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
5455 goto illegal_op;
5456 gen_arm_parallel_addsub[op1][sh]();
5457 gen_movl_reg_T0(s, rd);
5458 break;
5459 case 1:
5460 if ((insn & 0x00700020) == 0) {
5461 /* Hafword pack. */
5462 gen_movl_T0_reg(s, rn);
5463 gen_movl_T1_reg(s, rm);
5464 shift = (insn >> 7) & 0x1f;
5465 if (shift)
5466 gen_op_shll_T1_im(shift);
5467 if (insn & (1 << 6))
5468 gen_op_pkhtb_T0_T1();
5469 else
5470 gen_op_pkhbt_T0_T1();
5471 gen_movl_reg_T0(s, rd);
5472 } else if ((insn & 0x00200020) == 0x00200000) {
5473 /* [us]sat */
5474 gen_movl_T1_reg(s, rm);
5475 shift = (insn >> 7) & 0x1f;
5476 if (insn & (1 << 6)) {
5477 if (shift == 0)
5478 shift = 31;
5479 gen_op_sarl_T1_im(shift);
5480 } else {
5481 gen_op_shll_T1_im(shift);
5482 }
5483 sh = (insn >> 16) & 0x1f;
5484 if (sh != 0) {
5485 if (insn & (1 << 22))
5486 gen_op_usat_T1(sh);
5487 else
5488 gen_op_ssat_T1(sh);
5489 }
5490 gen_movl_T1_reg(s, rd);
5491 } else if ((insn & 0x00300fe0) == 0x00200f20) {
5492 /* [us]sat16 */
5493 gen_movl_T1_reg(s, rm);
5494 sh = (insn >> 16) & 0x1f;
5495 if (sh != 0) {
5496 if (insn & (1 << 22))
5497 gen_op_usat16_T1(sh);
5498 else
5499 gen_op_ssat16_T1(sh);
5500 }
5501 gen_movl_T1_reg(s, rd);
5502 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
5503 /* Select bytes. */
5504 gen_movl_T0_reg(s, rn);
5505 gen_movl_T1_reg(s, rm);
5506 gen_op_sel_T0_T1();
5507 gen_movl_reg_T0(s, rd);
5508 } else if ((insn & 0x000003e0) == 0x00000060) {
5509 gen_movl_T1_reg(s, rm);
5510 shift = (insn >> 10) & 3;
5511 /* ??? In many cases it's not neccessary to do a
5512 rotate, a shift is sufficient. */
5513 if (shift != 0)
5514 gen_op_rorl_T1_im(shift * 8);
5515 op1 = (insn >> 20) & 7;
5516 switch (op1) {
b26eefb6
PB
5517 case 0: gen_sxtb16(cpu_T[1]); break;
5518 case 2: gen_sxtb(cpu_T[1]); break;
5519 case 3: gen_sxth(cpu_T[1]); break;
5520 case 4: gen_uxtb16(cpu_T[1]); break;
5521 case 6: gen_uxtb(cpu_T[1]); break;
5522 case 7: gen_uxth(cpu_T[1]); break;
9ee6e8bb
PB
5523 default: goto illegal_op;
5524 }
5525 if (rn != 15) {
b26eefb6 5526 tmp = load_reg(s, rn);
9ee6e8bb 5527 if ((op1 & 3) == 0) {
b26eefb6 5528 gen_add16(cpu_T[1], tmp);
9ee6e8bb 5529 } else {
b26eefb6
PB
5530 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
5531 dead_tmp(tmp);
9ee6e8bb
PB
5532 }
5533 }
5534 gen_movl_reg_T1(s, rd);
5535 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
5536 /* rev */
5537 gen_movl_T0_reg(s, rm);
5538 if (insn & (1 << 22)) {
5539 if (insn & (1 << 7)) {
5540 gen_op_revsh_T0();
5541 } else {
5542 ARCH(6T2);
5543 gen_op_rbit_T0();
5544 }
5545 } else {
5546 if (insn & (1 << 7))
5547 gen_op_rev16_T0();
5548 else
5549 gen_op_rev_T0();
5550 }
5551 gen_movl_reg_T0(s, rd);
5552 } else {
5553 goto illegal_op;
5554 }
5555 break;
5556 case 2: /* Multiplies (Type 3). */
5557 gen_movl_T0_reg(s, rm);
5558 gen_movl_T1_reg(s, rs);
5559 if (insn & (1 << 20)) {
5560 /* Signed multiply most significant [accumulate]. */
5561 gen_op_imull_T0_T1();
5562 if (insn & (1 << 5))
5563 gen_op_roundqd_T0_T1();
5564 else
5565 gen_op_movl_T0_T1();
5566 if (rn != 15) {
5567 gen_movl_T1_reg(s, rn);
5568 if (insn & (1 << 6)) {
5569 gen_op_addl_T0_T1();
5570 } else {
5571 gen_op_rsbl_T0_T1();
5572 }
5573 }
5574 gen_movl_reg_T0(s, rd);
5575 } else {
5576 if (insn & (1 << 5))
5577 gen_op_swap_half_T1();
5578 gen_op_mul_dual_T0_T1();
5579 if (insn & (1 << 22)) {
5580 if (insn & (1 << 6)) {
5581 /* smlald */
5582 gen_op_addq_T0_T1_dual(rn, rd);
5583 } else {
5584 /* smlsld */
5585 gen_op_subq_T0_T1_dual(rn, rd);
5586 }
5587 } else {
5588 /* This addition cannot overflow. */
5589 if (insn & (1 << 6)) {
5590 /* sm[ul]sd */
5591 gen_op_subl_T0_T1();
5592 } else {
5593 /* sm[ul]ad */
5594 gen_op_addl_T0_T1();
5595 }
5596 if (rn != 15)
5597 {
5598 gen_movl_T1_reg(s, rn);
5599 gen_op_addl_T0_T1_setq();
5600 }
5601 gen_movl_reg_T0(s, rd);
5602 }
5603 }
5604 break;
5605 case 3:
5606 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
5607 switch (op1) {
5608 case 0: /* Unsigned sum of absolute differences. */
5609 goto illegal_op;
5610 gen_movl_T0_reg(s, rm);
5611 gen_movl_T1_reg(s, rs);
5612 gen_op_usad8_T0_T1();
5613 if (rn != 15) {
5614 gen_movl_T1_reg(s, rn);
5615 gen_op_addl_T0_T1();
5616 }
5617 gen_movl_reg_T0(s, rd);
5618 break;
5619 case 0x20: case 0x24: case 0x28: case 0x2c:
5620 /* Bitfield insert/clear. */
5621 ARCH(6T2);
5622 shift = (insn >> 7) & 0x1f;
5623 i = (insn >> 16) & 0x1f;
5624 i = i + 1 - shift;
5625 if (rm == 15) {
5626 gen_op_movl_T1_im(0);
5627 } else {
5628 gen_movl_T1_reg(s, rm);
5629 }
5630 if (i != 32) {
5631 gen_movl_T0_reg(s, rd);
5632 gen_op_bfi_T1_T0(shift, ((1u << i) - 1) << shift);
5633 }
5634 gen_movl_reg_T1(s, rd);
5635 break;
5636 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
5637 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
5638 gen_movl_T1_reg(s, rm);
5639 shift = (insn >> 7) & 0x1f;
5640 i = ((insn >> 16) & 0x1f) + 1;
5641 if (shift + i > 32)
5642 goto illegal_op;
5643 if (i < 32) {
5644 if (op1 & 0x20) {
5645 gen_op_ubfx_T1(shift, (1u << i) - 1);
5646 } else {
5647 gen_op_sbfx_T1(shift, i);
5648 }
5649 }
5650 gen_movl_reg_T1(s, rd);
5651 break;
5652 default:
5653 goto illegal_op;
5654 }
5655 break;
5656 }
5657 break;
5658 }
5659 do_ldst:
5660 /* Check for undefined extension instructions
5661 * per the ARM Bible IE:
5662 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
5663 */
5664 sh = (0xf << 20) | (0xf << 4);
5665 if (op1 == 0x7 && ((insn & sh) == sh))
5666 {
5667 goto illegal_op;
5668 }
5669 /* load/store byte/word */
5670 rn = (insn >> 16) & 0xf;
5671 rd = (insn >> 12) & 0xf;
5672 gen_movl_T1_reg(s, rn);
5673 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
5674 if (insn & (1 << 24))
5675 gen_add_data_offset(s, insn);
5676 if (insn & (1 << 20)) {
5677 /* load */
5678 s->is_mem = 1;
5679#if defined(CONFIG_USER_ONLY)
5680 if (insn & (1 << 22))
5681 gen_op_ldub_raw();
5682 else
5683 gen_op_ldl_raw();
5684#else
5685 if (insn & (1 << 22)) {
5686 if (i)
5687 gen_op_ldub_user();
5688 else
5689 gen_op_ldub_kernel();
5690 } else {
5691 if (i)
5692 gen_op_ldl_user();
5693 else
5694 gen_op_ldl_kernel();
5695 }
5696#endif
5697 } else {
5698 /* store */
5699 gen_movl_T0_reg(s, rd);
5700#if defined(CONFIG_USER_ONLY)
5701 if (insn & (1 << 22))
5702 gen_op_stb_raw();
5703 else
5704 gen_op_stl_raw();
5705#else
5706 if (insn & (1 << 22)) {
5707 if (i)
5708 gen_op_stb_user();
5709 else
5710 gen_op_stb_kernel();
5711 } else {
5712 if (i)
5713 gen_op_stl_user();
5714 else
5715 gen_op_stl_kernel();
5716 }
5717#endif
5718 }
5719 if (!(insn & (1 << 24))) {
5720 gen_add_data_offset(s, insn);
5721 gen_movl_reg_T1(s, rn);
5722 } else if (insn & (1 << 21))
5723 gen_movl_reg_T1(s, rn); {
5724 }
5725 if (insn & (1 << 20)) {
5726 /* Complete the load. */
5727 if (rd == 15)
5728 gen_bx(s);
5729 else
5730 gen_movl_reg_T0(s, rd);
5731 }
5732 break;
5733 case 0x08:
5734 case 0x09:
5735 {
5736 int j, n, user, loaded_base;
5737 /* load/store multiple words */
5738 /* XXX: store correct base if write back */
5739 user = 0;
5740 if (insn & (1 << 22)) {
5741 if (IS_USER(s))
5742 goto illegal_op; /* only usable in supervisor mode */
5743
5744 if ((insn & (1 << 15)) == 0)
5745 user = 1;
5746 }
5747 rn = (insn >> 16) & 0xf;
5748 gen_movl_T1_reg(s, rn);
5749
5750 /* compute total size */
5751 loaded_base = 0;
5752 n = 0;
5753 for(i=0;i<16;i++) {
5754 if (insn & (1 << i))
5755 n++;
5756 }
5757 /* XXX: test invalid n == 0 case ? */
5758 if (insn & (1 << 23)) {
5759 if (insn & (1 << 24)) {
5760 /* pre increment */
5761 gen_op_addl_T1_im(4);
5762 } else {
5763 /* post increment */
5764 }
5765 } else {
5766 if (insn & (1 << 24)) {
5767 /* pre decrement */
5768 gen_op_addl_T1_im(-(n * 4));
5769 } else {
5770 /* post decrement */
5771 if (n != 1)
5772 gen_op_addl_T1_im(-((n - 1) * 4));
5773 }
5774 }
5775 j = 0;
5776 for(i=0;i<16;i++) {
5777 if (insn & (1 << i)) {
5778 if (insn & (1 << 20)) {
5779 /* load */
5780 gen_ldst(ldl, s);
5781 if (i == 15) {
5782 gen_bx(s);
5783 } else if (user) {
5784 gen_op_movl_user_T0(i);
5785 } else if (i == rn) {
5786 gen_op_movl_T2_T0();
5787 loaded_base = 1;
5788 } else {
5789 gen_movl_reg_T0(s, i);
5790 }
5791 } else {
5792 /* store */
5793 if (i == 15) {
5794 /* special case: r15 = PC + 8 */
5795 val = (long)s->pc + 4;
b26eefb6 5796 gen_op_movl_T0_im(val);
9ee6e8bb
PB
5797 } else if (user) {
5798 gen_op_movl_T0_user(i);
5799 } else {
5800 gen_movl_T0_reg(s, i);
5801 }
5802 gen_ldst(stl, s);
5803 }
5804 j++;
5805 /* no need to add after the last transfer */
5806 if (j != n)
5807 gen_op_addl_T1_im(4);
5808 }
5809 }
5810 if (insn & (1 << 21)) {
5811 /* write back */
5812 if (insn & (1 << 23)) {
5813 if (insn & (1 << 24)) {
5814 /* pre increment */
5815 } else {
5816 /* post increment */
5817 gen_op_addl_T1_im(4);
5818 }
5819 } else {
5820 if (insn & (1 << 24)) {
5821 /* pre decrement */
5822 if (n != 1)
5823 gen_op_addl_T1_im(-((n - 1) * 4));
5824 } else {
5825 /* post decrement */
5826 gen_op_addl_T1_im(-(n * 4));
5827 }
5828 }
5829 gen_movl_reg_T1(s, rn);
5830 }
5831 if (loaded_base) {
5832 gen_op_movl_T0_T2();
5833 gen_movl_reg_T0(s, rn);
5834 }
5835 if ((insn & (1 << 22)) && !user) {
5836 /* Restore CPSR from SPSR. */
5837 gen_op_movl_T0_spsr();
5838 gen_op_movl_cpsr_T0(0xffffffff);
5839 s->is_jmp = DISAS_UPDATE;
5840 }
5841 }
5842 break;
5843 case 0xa:
5844 case 0xb:
5845 {
5846 int32_t offset;
5847
5848 /* branch (and link) */
5849 val = (int32_t)s->pc;
5850 if (insn & (1 << 24)) {
5851 gen_op_movl_T0_im(val);
b26eefb6 5852 gen_movl_reg_T0(s, 14);
9ee6e8bb
PB
5853 }
5854 offset = (((int32_t)insn << 8) >> 8);
5855 val += (offset << 2) + 4;
5856 gen_jmp(s, val);
5857 }
5858 break;
5859 case 0xc:
5860 case 0xd:
5861 case 0xe:
5862 /* Coprocessor. */
5863 if (disas_coproc_insn(env, s, insn))
5864 goto illegal_op;
5865 break;
5866 case 0xf:
5867 /* swi */
5868 gen_op_movl_T0_im((long)s->pc);
b26eefb6 5869 gen_set_pc_T0();
9ee6e8bb
PB
5870 s->is_jmp = DISAS_SWI;
5871 break;
5872 default:
5873 illegal_op:
5874 gen_set_condexec(s);
5875 gen_op_movl_T0_im((long)s->pc - 4);
b26eefb6 5876 gen_set_pc_T0();
9ee6e8bb
PB
5877 gen_op_undef_insn();
5878 s->is_jmp = DISAS_JUMP;
5879 break;
5880 }
5881 }
5882}
5883
5884/* Return true if this is a Thumb-2 logical op. */
5885static int
5886thumb2_logic_op(int op)
5887{
5888 return (op < 8);
5889}
5890
5891/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
5892 then set condition code flags based on the result of the operation.
5893 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
5894 to the high bit of T1.
5895 Returns zero if the opcode is valid. */
5896
5897static int
5898gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
5899{
5900 int logic_cc;
5901
5902 logic_cc = 0;
5903 switch (op) {
5904 case 0: /* and */
5905 gen_op_andl_T0_T1();
5906 logic_cc = conds;
5907 break;
5908 case 1: /* bic */
5909 gen_op_bicl_T0_T1();
5910 logic_cc = conds;
5911 break;
5912 case 2: /* orr */
5913 gen_op_orl_T0_T1();
5914 logic_cc = conds;
5915 break;
5916 case 3: /* orn */
5917 gen_op_notl_T1();
5918 gen_op_orl_T0_T1();
5919 logic_cc = conds;
5920 break;
5921 case 4: /* eor */
5922 gen_op_xorl_T0_T1();
5923 logic_cc = conds;
5924 break;
5925 case 8: /* add */
5926 if (conds)
5927 gen_op_addl_T0_T1_cc();
5928 else
5929 gen_op_addl_T0_T1();
5930 break;
5931 case 10: /* adc */
5932 if (conds)
5933 gen_op_adcl_T0_T1_cc();
5934 else
b26eefb6 5935 gen_adc_T0_T1();
9ee6e8bb
PB
5936 break;
5937 case 11: /* sbc */
5938 if (conds)
5939 gen_op_sbcl_T0_T1_cc();
5940 else
5941 gen_op_sbcl_T0_T1();
5942 break;
5943 case 13: /* sub */
5944 if (conds)
5945 gen_op_subl_T0_T1_cc();
5946 else
5947 gen_op_subl_T0_T1();
5948 break;
5949 case 14: /* rsb */
5950 if (conds)
5951 gen_op_rsbl_T0_T1_cc();
5952 else
5953 gen_op_rsbl_T0_T1();
5954 break;
5955 default: /* 5, 6, 7, 9, 12, 15. */
5956 return 1;
5957 }
5958 if (logic_cc) {
5959 gen_op_logic_T0_cc();
5960 if (shifter_out)
b26eefb6 5961 gen_set_CF_bit31(cpu_T[1]);
9ee6e8bb
PB
5962 }
5963 return 0;
5964}
5965
5966/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
5967 is not legal. */
5968static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
5969{
5970 uint32_t insn, imm, shift, offset, addr;
5971 uint32_t rd, rn, rm, rs;
b26eefb6 5972 TCGv tmp;
9ee6e8bb
PB
5973 int op;
5974 int shiftop;
5975 int conds;
5976 int logic_cc;
5977
5978 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
5979 || arm_feature (env, ARM_FEATURE_M))) {
5980 /* Thumb-1 cores may need to tread bl and blx as a pair of
5981 16-bit instructions to get correct prefetch abort behavior. */
5982 insn = insn_hw1;
5983 if ((insn & (1 << 12)) == 0) {
5984 /* Second half of blx. */
5985 offset = ((insn & 0x7ff) << 1);
5986 gen_movl_T0_reg(s, 14);
5987 gen_op_movl_T1_im(offset);
5988 gen_op_addl_T0_T1();
5989 gen_op_movl_T1_im(0xfffffffc);
5990 gen_op_andl_T0_T1();
5991
5992 addr = (uint32_t)s->pc;
5993 gen_op_movl_T1_im(addr | 1);
5994 gen_movl_reg_T1(s, 14);
5995 gen_bx(s);
5996 return 0;
5997 }
5998 if (insn & (1 << 11)) {
5999 /* Second half of bl. */
6000 offset = ((insn & 0x7ff) << 1) | 1;
6001 gen_movl_T0_reg(s, 14);
6002 gen_op_movl_T1_im(offset);
6003 gen_op_addl_T0_T1();
6004
6005 addr = (uint32_t)s->pc;
6006 gen_op_movl_T1_im(addr | 1);
6007 gen_movl_reg_T1(s, 14);
6008 gen_bx(s);
6009 return 0;
6010 }
6011 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6012 /* Instruction spans a page boundary. Implement it as two
6013 16-bit instructions in case the second half causes an
6014 prefetch abort. */
6015 offset = ((int32_t)insn << 21) >> 9;
6016 addr = s->pc + 2 + offset;
6017 gen_op_movl_T0_im(addr);
6018 gen_movl_reg_T0(s, 14);
6019 return 0;
6020 }
6021 /* Fall through to 32-bit decode. */
6022 }
6023
6024 insn = lduw_code(s->pc);
6025 s->pc += 2;
6026 insn |= (uint32_t)insn_hw1 << 16;
6027
6028 if ((insn & 0xf800e800) != 0xf000e800) {
6029 ARCH(6T2);
6030 }
6031
6032 rn = (insn >> 16) & 0xf;
6033 rs = (insn >> 12) & 0xf;
6034 rd = (insn >> 8) & 0xf;
6035 rm = insn & 0xf;
6036 switch ((insn >> 25) & 0xf) {
6037 case 0: case 1: case 2: case 3:
6038 /* 16-bit instructions. Should never happen. */
6039 abort();
6040 case 4:
6041 if (insn & (1 << 22)) {
6042 /* Other load/store, table branch. */
6043 if (insn & 0x01200000) {
6044 /* Load/store doubleword. */
6045 if (rn == 15) {
6046 gen_op_movl_T1_im(s->pc & ~3);
6047 } else {
6048 gen_movl_T1_reg(s, rn);
6049 }
6050 offset = (insn & 0xff) * 4;
6051 if ((insn & (1 << 23)) == 0)
6052 offset = -offset;
6053 if (insn & (1 << 24)) {
6054 gen_op_addl_T1_im(offset);
6055 offset = 0;
6056 }
6057 if (insn & (1 << 20)) {
6058 /* ldrd */
6059 gen_ldst(ldl, s);
6060 gen_movl_reg_T0(s, rs);
6061 gen_op_addl_T1_im(4);
6062 gen_ldst(ldl, s);
6063 gen_movl_reg_T0(s, rd);
6064 } else {
6065 /* strd */
6066 gen_movl_T0_reg(s, rs);
6067 gen_ldst(stl, s);
6068 gen_op_addl_T1_im(4);
6069 gen_movl_T0_reg(s, rd);
6070 gen_ldst(stl, s);
6071 }
6072 if (insn & (1 << 21)) {
6073 /* Base writeback. */
6074 if (rn == 15)
6075 goto illegal_op;
6076 gen_op_addl_T1_im(offset - 4);
6077 gen_movl_reg_T1(s, rn);
6078 }
6079 } else if ((insn & (1 << 23)) == 0) {
6080 /* Load/store exclusive word. */
6081 gen_movl_T0_reg(s, rd);
2c0262af 6082 gen_movl_T1_reg(s, rn);
2c0262af 6083 if (insn & (1 << 20)) {
9ee6e8bb
PB
6084 gen_ldst(ldlex, s);
6085 } else {
6086 gen_ldst(stlex, s);
6087 }
6088 gen_movl_reg_T0(s, rd);
6089 } else if ((insn & (1 << 6)) == 0) {
6090 /* Table Branch. */
6091 if (rn == 15) {
6092 gen_op_movl_T1_im(s->pc);
6093 } else {
6094 gen_movl_T1_reg(s, rn);
6095 }
b26eefb6
PB
6096 tmp = load_reg(s, rm);
6097 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
9ee6e8bb
PB
6098 if (insn & (1 << 4)) {
6099 /* tbh */
b26eefb6
PB
6100 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6101 dead_tmp(tmp);
9ee6e8bb
PB
6102 gen_ldst(lduw, s);
6103 } else { /* tbb */
b26eefb6 6104 dead_tmp(tmp);
9ee6e8bb
PB
6105 gen_ldst(ldub, s);
6106 }
6107 gen_op_jmp_T0_im(s->pc);
6108 s->is_jmp = DISAS_JUMP;
6109 } else {
6110 /* Load/store exclusive byte/halfword/doubleword. */
6111 op = (insn >> 4) & 0x3;
6112 gen_movl_T1_reg(s, rn);
6113 if (insn & (1 << 20)) {
6114 switch (op) {
6115 case 0:
6116 gen_ldst(ldbex, s);
6117 break;
2c0262af 6118 case 1:
9ee6e8bb 6119 gen_ldst(ldwex, s);
2c0262af 6120 break;
9ee6e8bb
PB
6121 case 3:
6122 gen_ldst(ldqex, s);
6123 gen_movl_reg_T1(s, rd);
2c0262af
FB
6124 break;
6125 default:
9ee6e8bb
PB
6126 goto illegal_op;
6127 }
6128 gen_movl_reg_T0(s, rs);
6129 } else {
6130 gen_movl_T0_reg(s, rs);
6131 switch (op) {
6132 case 0:
6133 gen_ldst(stbex, s);
6134 break;
6135 case 1:
6136 gen_ldst(stwex, s);
6137 break;
2c0262af 6138 case 3:
9ee6e8bb
PB
6139 gen_movl_T2_reg(s, rd);
6140 gen_ldst(stqex, s);
2c0262af 6141 break;
9ee6e8bb
PB
6142 default:
6143 goto illegal_op;
2c0262af 6144 }
9ee6e8bb
PB
6145 gen_movl_reg_T0(s, rm);
6146 }
6147 }
6148 } else {
6149 /* Load/store multiple, RFE, SRS. */
6150 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
6151 /* Not available in user mode. */
6152 if (!IS_USER(s))
6153 goto illegal_op;
6154 if (insn & (1 << 20)) {
6155 /* rfe */
6156 gen_movl_T1_reg(s, rn);
6157 if (insn & (1 << 24)) {
99c475ab 6158 gen_op_addl_T1_im(4);
9ee6e8bb
PB
6159 } else {
6160 gen_op_addl_T1_im(-4);
6161 }
6162 /* Load CPSR into T2 and PC into T0. */
6163 gen_ldst(ldl, s);
6164 gen_op_movl_T2_T0();
6165 gen_op_addl_T1_im(-4);
6166 gen_ldst(ldl, s);
6167 if (insn & (1 << 21)) {
6168 /* Base writeback. */
6169 if (insn & (1 << 24))
6170 gen_op_addl_T1_im(8);
6171 gen_movl_reg_T1(s, rn);
6172 }
6173 gen_rfe(s);
6174 } else {
6175 /* srs */
6176 op = (insn & 0x1f);
6177 if (op == (env->uncached_cpsr & CPSR_M)) {
6178 gen_movl_T1_reg(s, 13);
6179 } else {
6180 gen_op_movl_T1_r13_banked(op);
6181 }
6182 if ((insn & (1 << 24)) == 0) {
6183 gen_op_addl_T1_im(-8);
6184 }
6185 gen_movl_T0_reg(s, 14);
6186 gen_ldst(stl, s);
6187 gen_op_movl_T0_cpsr();
6188 gen_op_addl_T1_im(4);
6189 gen_ldst(stl, s);
6190 if (insn & (1 << 21)) {
6191 if ((insn & (1 << 24)) == 0) {
6192 gen_op_addl_T1_im(-4);
6193 } else {
6194 gen_op_addl_T1_im(4);
6195 }
6196 if (op == (env->uncached_cpsr & CPSR_M)) {
6197 gen_movl_reg_T1(s, 13);
6198 } else {
6199 gen_op_movl_r13_T1_banked(op);
6200 }
6201 }
6202 }
6203 } else {
6204 int i;
6205 /* Load/store multiple. */
6206 gen_movl_T1_reg(s, rn);
6207 offset = 0;
6208 for (i = 0; i < 16; i++) {
6209 if (insn & (1 << i))
6210 offset += 4;
6211 }
6212 if (insn & (1 << 24)) {
6213 gen_op_addl_T1_im(-offset);
6214 }
6215
6216 for (i = 0; i < 16; i++) {
6217 if ((insn & (1 << i)) == 0)
6218 continue;
6219 if (insn & (1 << 20)) {
6220 /* Load. */
6221 gen_ldst(ldl, s);
6222 if (i == 15) {
6223 gen_bx(s);
6224 } else {
6225 gen_movl_reg_T0(s, i);
6226 }
6227 } else {
6228 /* Store. */
6229 gen_movl_T0_reg(s, i);
b5ff1b31 6230 gen_ldst(stl, s);
9ee6e8bb
PB
6231 }
6232 gen_op_addl_T1_im(4);
6233 }
6234 if (insn & (1 << 21)) {
6235 /* Base register writeback. */
6236 if (insn & (1 << 24)) {
6237 gen_op_addl_T1_im(-offset);
6238 }
6239 /* Fault if writeback register is in register list. */
6240 if (insn & (1 << rn))
6241 goto illegal_op;
6242 gen_movl_reg_T1(s, rn);
6243 }
6244 }
6245 }
6246 break;
6247 case 5: /* Data processing register constant shift. */
6248 if (rn == 15)
6249 gen_op_movl_T0_im(0);
6250 else
6251 gen_movl_T0_reg(s, rn);
6252 gen_movl_T1_reg(s, rm);
6253 op = (insn >> 21) & 0xf;
6254 shiftop = (insn >> 4) & 3;
6255 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6256 conds = (insn & (1 << 20)) != 0;
6257 logic_cc = (conds && thumb2_logic_op(op));
9a119ff6 6258 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
9ee6e8bb
PB
6259 if (gen_thumb2_data_op(s, op, conds, 0))
6260 goto illegal_op;
6261 if (rd != 15)
6262 gen_movl_reg_T0(s, rd);
6263 break;
6264 case 13: /* Misc data processing. */
6265 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
6266 if (op < 4 && (insn & 0xf000) != 0xf000)
6267 goto illegal_op;
6268 switch (op) {
6269 case 0: /* Register controlled shift. */
6270 gen_movl_T0_reg(s, rm);
6271 gen_movl_T1_reg(s, rn);
6272 if ((insn & 0x70) != 0)
6273 goto illegal_op;
6274 op = (insn >> 21) & 3;
6275 if (insn & (1 << 20)) {
6276 gen_shift_T1_T0_cc[op]();
6277 gen_op_logic_T1_cc();
6278 } else {
6279 gen_shift_T1_T0[op]();
6280 }
6281 gen_movl_reg_T1(s, rd);
6282 break;
6283 case 1: /* Sign/zero extend. */
6284 gen_movl_T1_reg(s, rm);
6285 shift = (insn >> 4) & 3;
6286 /* ??? In many cases it's not neccessary to do a
6287 rotate, a shift is sufficient. */
6288 if (shift != 0)
6289 gen_op_rorl_T1_im(shift * 8);
6290 op = (insn >> 20) & 7;
6291 switch (op) {
b26eefb6
PB
6292 case 0: gen_sxth(cpu_T[1]); break;
6293 case 1: gen_uxth(cpu_T[1]); break;
6294 case 2: gen_sxtb16(cpu_T[1]); break;
6295 case 3: gen_uxtb16(cpu_T[1]); break;
6296 case 4: gen_sxtb(cpu_T[1]); break;
6297 case 5: gen_uxtb(cpu_T[1]); break;
9ee6e8bb
PB
6298 default: goto illegal_op;
6299 }
6300 if (rn != 15) {
b26eefb6 6301 tmp = load_reg(s, rn);
9ee6e8bb 6302 if ((op >> 1) == 1) {
b26eefb6 6303 gen_add16(cpu_T[1], tmp);
9ee6e8bb 6304 } else {
b26eefb6
PB
6305 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6306 dead_tmp(tmp);
9ee6e8bb
PB
6307 }
6308 }
6309 gen_movl_reg_T1(s, rd);
6310 break;
6311 case 2: /* SIMD add/subtract. */
6312 op = (insn >> 20) & 7;
6313 shift = (insn >> 4) & 7;
6314 if ((op & 3) == 3 || (shift & 3) == 3)
6315 goto illegal_op;
6316 gen_movl_T0_reg(s, rn);
6317 gen_movl_T1_reg(s, rm);
6318 gen_thumb2_parallel_addsub[op][shift]();
6319 gen_movl_reg_T0(s, rd);
6320 break;
6321 case 3: /* Other data processing. */
6322 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
6323 if (op < 4) {
6324 /* Saturating add/subtract. */
6325 gen_movl_T0_reg(s, rm);
6326 gen_movl_T1_reg(s, rn);
6327 if (op & 2)
1497c961 6328 gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
9ee6e8bb
PB
6329 if (op & 1)
6330 gen_op_subl_T0_T1_saturate();
6331 else
6332 gen_op_addl_T0_T1_saturate();
6333 } else {
6334 gen_movl_T0_reg(s, rn);
6335 switch (op) {
6336 case 0x0a: /* rbit */
6337 gen_op_rbit_T0();
6338 break;
6339 case 0x08: /* rev */
6340 gen_op_rev_T0();
6341 break;
6342 case 0x09: /* rev16 */
6343 gen_op_rev16_T0();
6344 break;
6345 case 0x0b: /* revsh */
6346 gen_op_revsh_T0();
6347 break;
6348 case 0x10: /* sel */
6349 gen_movl_T1_reg(s, rm);
6350 gen_op_sel_T0_T1();
6351 break;
6352 case 0x18: /* clz */
1497c961 6353 gen_helper_clz(cpu_T[0], cpu_T[0]);
9ee6e8bb
PB
6354 break;
6355 default:
6356 goto illegal_op;
6357 }
6358 }
6359 gen_movl_reg_T0(s, rd);
6360 break;
6361 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
6362 op = (insn >> 4) & 0xf;
6363 gen_movl_T0_reg(s, rn);
6364 gen_movl_T1_reg(s, rm);
6365 switch ((insn >> 20) & 7) {
6366 case 0: /* 32 x 32 -> 32 */
6367 gen_op_mul_T0_T1();
6368 if (rs != 15) {
6369 gen_movl_T1_reg(s, rs);
6370 if (op)
6371 gen_op_rsbl_T0_T1();
6372 else
6373 gen_op_addl_T0_T1();
6374 }
6375 gen_movl_reg_T0(s, rd);
6376 break;
6377 case 1: /* 16 x 16 -> 32 */
6378 gen_mulxy(op & 2, op & 1);
6379 if (rs != 15) {
6380 gen_movl_T1_reg(s, rs);
6381 gen_op_addl_T0_T1_setq();
6382 }
6383 gen_movl_reg_T0(s, rd);
6384 break;
6385 case 2: /* Dual multiply add. */
6386 case 4: /* Dual multiply subtract. */
6387 if (op)
6388 gen_op_swap_half_T1();
6389 gen_op_mul_dual_T0_T1();
6390 /* This addition cannot overflow. */
6391 if (insn & (1 << 22)) {
6392 gen_op_subl_T0_T1();
6393 } else {
6394 gen_op_addl_T0_T1();
6395 }
6396 if (rs != 15)
6397 {
6398 gen_movl_T1_reg(s, rs);
6399 gen_op_addl_T0_T1_setq();
6400 }
6401 gen_movl_reg_T0(s, rd);
6402 break;
6403 case 3: /* 32 * 16 -> 32msb */
6404 if (op)
6405 gen_op_sarl_T1_im(16);
6406 else
b26eefb6 6407 gen_sxth(cpu_T[1]);
9ee6e8bb
PB
6408 gen_op_imulw_T0_T1();
6409 if (rs != 15)
6410 {
6411 gen_movl_T1_reg(s, rs);
6412 gen_op_addl_T0_T1_setq();
6413 }
6414 gen_movl_reg_T0(s, rd);
6415 break;
6416 case 5: case 6: /* 32 * 32 -> 32msb */
6417 gen_op_imull_T0_T1();
6418 if (insn & (1 << 5))
6419 gen_op_roundqd_T0_T1();
6420 else
6421 gen_op_movl_T0_T1();
6422 if (rs != 15) {
6423 gen_movl_T1_reg(s, rs);
6424 if (insn & (1 << 21)) {
6425 gen_op_addl_T0_T1();
99c475ab 6426 } else {
9ee6e8bb 6427 gen_op_rsbl_T0_T1();
99c475ab 6428 }
2c0262af 6429 }
9ee6e8bb
PB
6430 gen_movl_reg_T0(s, rd);
6431 break;
6432 case 7: /* Unsigned sum of absolute differences. */
6433 gen_op_usad8_T0_T1();
6434 if (rs != 15) {
6435 gen_movl_T1_reg(s, rs);
6436 gen_op_addl_T0_T1();
5fd46862 6437 }
9ee6e8bb
PB
6438 gen_movl_reg_T0(s, rd);
6439 break;
2c0262af
FB
6440 }
6441 break;
9ee6e8bb
PB
6442 case 6: case 7: /* 64-bit multiply, Divide. */
6443 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
6444 gen_movl_T0_reg(s, rn);
6445 gen_movl_T1_reg(s, rm);
6446 if ((op & 0x50) == 0x10) {
6447 /* sdiv, udiv */
6448 if (!arm_feature(env, ARM_FEATURE_DIV))
6449 goto illegal_op;
6450 if (op & 0x20)
6451 gen_op_udivl_T0_T1();
2c0262af 6452 else
9ee6e8bb
PB
6453 gen_op_sdivl_T0_T1();
6454 gen_movl_reg_T0(s, rd);
6455 } else if ((op & 0xe) == 0xc) {
6456 /* Dual multiply accumulate long. */
6457 if (op & 1)
6458 gen_op_swap_half_T1();
6459 gen_op_mul_dual_T0_T1();
6460 if (op & 0x10) {
6461 gen_op_subl_T0_T1();
b5ff1b31 6462 } else {
9ee6e8bb 6463 gen_op_addl_T0_T1();
b5ff1b31 6464 }
9ee6e8bb
PB
6465 gen_op_signbit_T1_T0();
6466 gen_op_addq_T0_T1(rs, rd);
6467 gen_movl_reg_T0(s, rs);
6468 gen_movl_reg_T1(s, rd);
2c0262af 6469 } else {
9ee6e8bb
PB
6470 if (op & 0x20) {
6471 /* Unsigned 64-bit multiply */
6472 gen_op_mull_T0_T1();
b5ff1b31 6473 } else {
9ee6e8bb
PB
6474 if (op & 8) {
6475 /* smlalxy */
6476 gen_mulxy(op & 2, op & 1);
6477 gen_op_signbit_T1_T0();
6478 } else {
6479 /* Signed 64-bit multiply */
6480 gen_op_imull_T0_T1();
6481 }
b5ff1b31 6482 }
9ee6e8bb
PB
6483 if (op & 4) {
6484 /* umaal */
6485 gen_op_addq_lo_T0_T1(rs);
6486 gen_op_addq_lo_T0_T1(rd);
6487 } else if (op & 0x40) {
6488 /* 64-bit accumulate. */
6489 gen_op_addq_T0_T1(rs, rd);
6490 }
6491 gen_movl_reg_T0(s, rs);
6492 gen_movl_reg_T1(s, rd);
5fd46862 6493 }
2c0262af 6494 break;
9ee6e8bb
PB
6495 }
6496 break;
6497 case 6: case 7: case 14: case 15:
6498 /* Coprocessor. */
6499 if (((insn >> 24) & 3) == 3) {
6500 /* Translate into the equivalent ARM encoding. */
6501 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
6502 if (disas_neon_data_insn(env, s, insn))
6503 goto illegal_op;
6504 } else {
6505 if (insn & (1 << 28))
6506 goto illegal_op;
6507 if (disas_coproc_insn (env, s, insn))
6508 goto illegal_op;
6509 }
6510 break;
6511 case 8: case 9: case 10: case 11:
6512 if (insn & (1 << 15)) {
6513 /* Branches, misc control. */
6514 if (insn & 0x5000) {
6515 /* Unconditional branch. */
6516 /* signextend(hw1[10:0]) -> offset[:12]. */
6517 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
6518 /* hw1[10:0] -> offset[11:1]. */
6519 offset |= (insn & 0x7ff) << 1;
6520 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
6521 offset[24:22] already have the same value because of the
6522 sign extension above. */
6523 offset ^= ((~insn) & (1 << 13)) << 10;
6524 offset ^= ((~insn) & (1 << 11)) << 11;
6525
6526 addr = s->pc;
6527 if (insn & (1 << 14)) {
6528 /* Branch and link. */
6529 gen_op_movl_T1_im(addr | 1);
6530 gen_movl_reg_T1(s, 14);
b5ff1b31 6531 }
3b46e624 6532
9ee6e8bb
PB
6533 addr += offset;
6534 if (insn & (1 << 12)) {
6535 /* b/bl */
6536 gen_jmp(s, addr);
6537 } else {
6538 /* blx */
6539 addr &= ~(uint32_t)2;
6540 gen_op_movl_T0_im(addr);
6541 gen_bx(s);
2c0262af 6542 }
9ee6e8bb
PB
6543 } else if (((insn >> 23) & 7) == 7) {
6544 /* Misc control */
6545 if (insn & (1 << 13))
6546 goto illegal_op;
6547
6548 if (insn & (1 << 26)) {
6549 /* Secure monitor call (v6Z) */
6550 goto illegal_op; /* not implemented. */
2c0262af 6551 } else {
9ee6e8bb
PB
6552 op = (insn >> 20) & 7;
6553 switch (op) {
6554 case 0: /* msr cpsr. */
6555 if (IS_M(env)) {
6556 gen_op_v7m_msr_T0(insn & 0xff);
6557 gen_movl_reg_T0(s, rn);
6558 gen_lookup_tb(s);
6559 break;
6560 }
6561 /* fall through */
6562 case 1: /* msr spsr. */
6563 if (IS_M(env))
6564 goto illegal_op;
6565 gen_movl_T0_reg(s, rn);
6566 if (gen_set_psr_T0(s,
6567 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
6568 op == 1))
6569 goto illegal_op;
6570 break;
6571 case 2: /* cps, nop-hint. */
6572 if (((insn >> 8) & 7) == 0) {
6573 gen_nop_hint(s, insn & 0xff);
6574 }
6575 /* Implemented as NOP in user mode. */
6576 if (IS_USER(s))
6577 break;
6578 offset = 0;
6579 imm = 0;
6580 if (insn & (1 << 10)) {
6581 if (insn & (1 << 7))
6582 offset |= CPSR_A;
6583 if (insn & (1 << 6))
6584 offset |= CPSR_I;
6585 if (insn & (1 << 5))
6586 offset |= CPSR_F;
6587 if (insn & (1 << 9))
6588 imm = CPSR_A | CPSR_I | CPSR_F;
6589 }
6590 if (insn & (1 << 8)) {
6591 offset |= 0x1f;
6592 imm |= (insn & 0x1f);
6593 }
6594 if (offset) {
6595 gen_op_movl_T0_im(imm);
6596 gen_set_psr_T0(s, offset, 0);
6597 }
6598 break;
6599 case 3: /* Special control operations. */
6600 op = (insn >> 4) & 0xf;
6601 switch (op) {
6602 case 2: /* clrex */
6603 gen_op_clrex();
6604 break;
6605 case 4: /* dsb */
6606 case 5: /* dmb */
6607 case 6: /* isb */
6608 /* These execute as NOPs. */
6609 ARCH(7);
6610 break;
6611 default:
6612 goto illegal_op;
6613 }
6614 break;
6615 case 4: /* bxj */
6616 /* Trivial implementation equivalent to bx. */
6617 gen_movl_T0_reg(s, rn);
6618 gen_bx(s);
6619 break;
6620 case 5: /* Exception return. */
6621 /* Unpredictable in user mode. */
6622 goto illegal_op;
6623 case 6: /* mrs cpsr. */
6624 if (IS_M(env)) {
6625 gen_op_v7m_mrs_T0(insn & 0xff);
6626 } else {
6627 gen_op_movl_T0_cpsr();
6628 }
6629 gen_movl_reg_T0(s, rd);
6630 break;
6631 case 7: /* mrs spsr. */
6632 /* Not accessible in user mode. */
6633 if (IS_USER(s) || IS_M(env))
6634 goto illegal_op;
6635 gen_op_movl_T0_spsr();
6636 gen_movl_reg_T0(s, rd);
6637 break;
2c0262af
FB
6638 }
6639 }
9ee6e8bb
PB
6640 } else {
6641 /* Conditional branch. */
6642 op = (insn >> 22) & 0xf;
6643 /* Generate a conditional jump to next instruction. */
6644 s->condlabel = gen_new_label();
6645 gen_test_cc[op ^ 1](s->condlabel);
6646 s->condjmp = 1;
6647
6648 /* offset[11:1] = insn[10:0] */
6649 offset = (insn & 0x7ff) << 1;
6650 /* offset[17:12] = insn[21:16]. */
6651 offset |= (insn & 0x003f0000) >> 4;
6652 /* offset[31:20] = insn[26]. */
6653 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
6654 /* offset[18] = insn[13]. */
6655 offset |= (insn & (1 << 13)) << 5;
6656 /* offset[19] = insn[11]. */
6657 offset |= (insn & (1 << 11)) << 8;
6658
6659 /* jump to the offset */
6660 addr = s->pc + offset;
6661 gen_jmp(s, addr);
6662 }
6663 } else {
6664 /* Data processing immediate. */
6665 if (insn & (1 << 25)) {
6666 if (insn & (1 << 24)) {
6667 if (insn & (1 << 20))
6668 goto illegal_op;
6669 /* Bitfield/Saturate. */
6670 op = (insn >> 21) & 7;
6671 imm = insn & 0x1f;
6672 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6673 if (rn == 15)
6674 gen_op_movl_T1_im(0);
6675 else
6676 gen_movl_T1_reg(s, rn);
6677 switch (op) {
6678 case 2: /* Signed bitfield extract. */
6679 imm++;
6680 if (shift + imm > 32)
6681 goto illegal_op;
6682 if (imm < 32)
6683 gen_op_sbfx_T1(shift, imm);
6684 break;
6685 case 6: /* Unsigned bitfield extract. */
6686 imm++;
6687 if (shift + imm > 32)
6688 goto illegal_op;
6689 if (imm < 32)
6690 gen_op_ubfx_T1(shift, (1u << imm) - 1);
6691 break;
6692 case 3: /* Bitfield insert/clear. */
6693 if (imm < shift)
6694 goto illegal_op;
6695 imm = imm + 1 - shift;
6696 if (imm != 32) {
6697 gen_movl_T0_reg(s, rd);
6698 gen_op_bfi_T1_T0(shift, ((1u << imm) - 1) << shift);
6699 }
6700 break;
6701 case 7:
6702 goto illegal_op;
6703 default: /* Saturate. */
6704 gen_movl_T1_reg(s, rn);
6705 if (shift) {
6706 if (op & 1)
6707 gen_op_sarl_T1_im(shift);
6708 else
6709 gen_op_shll_T1_im(shift);
6710 }
6711 if (op & 4) {
6712 /* Unsigned. */
6713 gen_op_ssat_T1(imm);
6714 if ((op & 1) && shift == 0)
6715 gen_op_usat16_T1(imm);
6716 else
6717 gen_op_usat_T1(imm);
2c0262af 6718 } else {
9ee6e8bb
PB
6719 /* Signed. */
6720 gen_op_ssat_T1(imm);
6721 if ((op & 1) && shift == 0)
6722 gen_op_ssat16_T1(imm);
6723 else
6724 gen_op_ssat_T1(imm);
2c0262af 6725 }
9ee6e8bb 6726 break;
2c0262af 6727 }
9ee6e8bb
PB
6728 gen_movl_reg_T1(s, rd);
6729 } else {
6730 imm = ((insn & 0x04000000) >> 15)
6731 | ((insn & 0x7000) >> 4) | (insn & 0xff);
6732 if (insn & (1 << 22)) {
6733 /* 16-bit immediate. */
6734 imm |= (insn >> 4) & 0xf000;
6735 if (insn & (1 << 23)) {
6736 /* movt */
6737 gen_movl_T0_reg(s, rd);
6738 gen_op_movtop_T0_im(imm << 16);
2c0262af 6739 } else {
9ee6e8bb
PB
6740 /* movw */
6741 gen_op_movl_T0_im(imm);
2c0262af
FB
6742 }
6743 } else {
9ee6e8bb
PB
6744 /* Add/sub 12-bit immediate. */
6745 if (rn == 15) {
6746 addr = s->pc & ~(uint32_t)3;
6747 if (insn & (1 << 23))
6748 addr -= imm;
6749 else
6750 addr += imm;
6751 gen_op_movl_T0_im(addr);
2c0262af 6752 } else {
9ee6e8bb
PB
6753 gen_movl_T0_reg(s, rn);
6754 gen_op_movl_T1_im(imm);
6755 if (insn & (1 << 23))
6756 gen_op_subl_T0_T1();
6757 else
6758 gen_op_addl_T0_T1();
2c0262af 6759 }
9ee6e8bb
PB
6760 }
6761 gen_movl_reg_T0(s, rd);
191abaa2 6762 }
9ee6e8bb
PB
6763 } else {
6764 int shifter_out = 0;
6765 /* modified 12-bit immediate. */
6766 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
6767 imm = (insn & 0xff);
6768 switch (shift) {
6769 case 0: /* XY */
6770 /* Nothing to do. */
6771 break;
6772 case 1: /* 00XY00XY */
6773 imm |= imm << 16;
6774 break;
6775 case 2: /* XY00XY00 */
6776 imm |= imm << 16;
6777 imm <<= 8;
6778 break;
6779 case 3: /* XYXYXYXY */
6780 imm |= imm << 16;
6781 imm |= imm << 8;
6782 break;
6783 default: /* Rotated constant. */
6784 shift = (shift << 1) | (imm >> 7);
6785 imm |= 0x80;
6786 imm = imm << (32 - shift);
6787 shifter_out = 1;
6788 break;
b5ff1b31 6789 }
9ee6e8bb
PB
6790 gen_op_movl_T1_im(imm);
6791 rn = (insn >> 16) & 0xf;
6792 if (rn == 15)
6793 gen_op_movl_T0_im(0);
6794 else
6795 gen_movl_T0_reg(s, rn);
6796 op = (insn >> 21) & 0xf;
6797 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
6798 shifter_out))
6799 goto illegal_op;
6800 rd = (insn >> 8) & 0xf;
6801 if (rd != 15) {
6802 gen_movl_reg_T0(s, rd);
2c0262af 6803 }
2c0262af 6804 }
9ee6e8bb
PB
6805 }
6806 break;
6807 case 12: /* Load/store single data item. */
6808 {
6809 int postinc = 0;
6810 int writeback = 0;
6811 if ((insn & 0x01100000) == 0x01000000) {
6812 if (disas_neon_ls_insn(env, s, insn))
c1713132 6813 goto illegal_op;
9ee6e8bb
PB
6814 break;
6815 }
6816 if (rn == 15) {
6817 /* PC relative. */
6818 /* s->pc has already been incremented by 4. */
6819 imm = s->pc & 0xfffffffc;
6820 if (insn & (1 << 23))
6821 imm += insn & 0xfff;
6822 else
6823 imm -= insn & 0xfff;
6824 gen_op_movl_T1_im(imm);
6825 } else {
6826 gen_movl_T1_reg(s, rn);
6827 if (insn & (1 << 23)) {
6828 /* Positive offset. */
6829 imm = insn & 0xfff;
6830 gen_op_addl_T1_im(imm);
6831 } else {
6832 op = (insn >> 8) & 7;
6833 imm = insn & 0xff;
6834 switch (op) {
6835 case 0: case 8: /* Shifted Register. */
6836 shift = (insn >> 4) & 0xf;
6837 if (shift > 3)
18c9b560 6838 goto illegal_op;
b26eefb6 6839 tmp = load_reg(s, rm);
9ee6e8bb 6840 if (shift)
b26eefb6
PB
6841 tcg_gen_shli_i32(tmp, tmp, shift);
6842 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6843 dead_tmp(tmp);
9ee6e8bb
PB
6844 break;
6845 case 4: /* Negative offset. */
6846 gen_op_addl_T1_im(-imm);
6847 break;
6848 case 6: /* User privilege. */
6849 gen_op_addl_T1_im(imm);
6850 break;
6851 case 1: /* Post-decrement. */
6852 imm = -imm;
6853 /* Fall through. */
6854 case 3: /* Post-increment. */
9ee6e8bb
PB
6855 postinc = 1;
6856 writeback = 1;
6857 break;
6858 case 5: /* Pre-decrement. */
6859 imm = -imm;
6860 /* Fall through. */
6861 case 7: /* Pre-increment. */
6862 gen_op_addl_T1_im(imm);
6863 writeback = 1;
6864 break;
6865 default:
b7bcbe95 6866 goto illegal_op;
9ee6e8bb
PB
6867 }
6868 }
6869 }
6870 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
6871 if (insn & (1 << 20)) {
6872 /* Load. */
6873 if (rs == 15 && op != 2) {
6874 if (op & 2)
b5ff1b31 6875 goto illegal_op;
9ee6e8bb
PB
6876 /* Memory hint. Implemented as NOP. */
6877 } else {
6878 switch (op) {
6879 case 0: gen_ldst(ldub, s); break;
6880 case 4: gen_ldst(ldsb, s); break;
6881 case 1: gen_ldst(lduw, s); break;
6882 case 5: gen_ldst(ldsw, s); break;
6883 case 2: gen_ldst(ldl, s); break;
6884 default: goto illegal_op;
6885 }
6886 if (rs == 15) {
6887 gen_bx(s);
6888 } else {
6889 gen_movl_reg_T0(s, rs);
6890 }
6891 }
6892 } else {
6893 /* Store. */
6894 if (rs == 15)
b7bcbe95 6895 goto illegal_op;
9ee6e8bb
PB
6896 gen_movl_T0_reg(s, rs);
6897 switch (op) {
6898 case 0: gen_ldst(stb, s); break;
6899 case 1: gen_ldst(stw, s); break;
6900 case 2: gen_ldst(stl, s); break;
6901 default: goto illegal_op;
b7bcbe95 6902 }
2c0262af 6903 }
9ee6e8bb
PB
6904 if (postinc)
6905 gen_op_addl_T1_im(imm);
6906 if (writeback)
6907 gen_movl_reg_T1(s, rn);
6908 }
6909 break;
6910 default:
6911 goto illegal_op;
2c0262af 6912 }
9ee6e8bb
PB
6913 return 0;
6914illegal_op:
6915 return 1;
2c0262af
FB
6916}
6917
9ee6e8bb 6918static void disas_thumb_insn(CPUState *env, DisasContext *s)
99c475ab
FB
6919{
6920 uint32_t val, insn, op, rm, rn, rd, shift, cond;
6921 int32_t offset;
6922 int i;
b26eefb6 6923 TCGv tmp;
99c475ab 6924
9ee6e8bb
PB
6925 if (s->condexec_mask) {
6926 cond = s->condexec_cond;
6927 s->condlabel = gen_new_label();
6928 gen_test_cc[cond ^ 1](s->condlabel);
6929 s->condjmp = 1;
6930 }
6931
b5ff1b31 6932 insn = lduw_code(s->pc);
99c475ab 6933 s->pc += 2;
b5ff1b31 6934
99c475ab
FB
6935 switch (insn >> 12) {
6936 case 0: case 1:
6937 rd = insn & 7;
6938 op = (insn >> 11) & 3;
6939 if (op == 3) {
6940 /* add/subtract */
6941 rn = (insn >> 3) & 7;
6942 gen_movl_T0_reg(s, rn);
6943 if (insn & (1 << 10)) {
6944 /* immediate */
6945 gen_op_movl_T1_im((insn >> 6) & 7);
6946 } else {
6947 /* reg */
6948 rm = (insn >> 6) & 7;
6949 gen_movl_T1_reg(s, rm);
6950 }
9ee6e8bb
PB
6951 if (insn & (1 << 9)) {
6952 if (s->condexec_mask)
6953 gen_op_subl_T0_T1();
6954 else
6955 gen_op_subl_T0_T1_cc();
6956 } else {
6957 if (s->condexec_mask)
6958 gen_op_addl_T0_T1();
6959 else
6960 gen_op_addl_T0_T1_cc();
6961 }
99c475ab
FB
6962 gen_movl_reg_T0(s, rd);
6963 } else {
6964 /* shift immediate */
6965 rm = (insn >> 3) & 7;
6966 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
6967 tmp = load_reg(s, rm);
6968 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
6969 if (!s->condexec_mask)
6970 gen_logic_CC(tmp);
6971 store_reg(s, rd, tmp);
99c475ab
FB
6972 }
6973 break;
6974 case 2: case 3:
6975 /* arithmetic large immediate */
6976 op = (insn >> 11) & 3;
6977 rd = (insn >> 8) & 0x7;
6978 if (op == 0) {
6979 gen_op_movl_T0_im(insn & 0xff);
6980 } else {
6981 gen_movl_T0_reg(s, rd);
6982 gen_op_movl_T1_im(insn & 0xff);
6983 }
6984 switch (op) {
6985 case 0: /* mov */
9ee6e8bb
PB
6986 if (!s->condexec_mask)
6987 gen_op_logic_T0_cc();
99c475ab
FB
6988 break;
6989 case 1: /* cmp */
6990 gen_op_subl_T0_T1_cc();
6991 break;
6992 case 2: /* add */
9ee6e8bb
PB
6993 if (s->condexec_mask)
6994 gen_op_addl_T0_T1();
6995 else
6996 gen_op_addl_T0_T1_cc();
99c475ab
FB
6997 break;
6998 case 3: /* sub */
9ee6e8bb
PB
6999 if (s->condexec_mask)
7000 gen_op_subl_T0_T1();
7001 else
7002 gen_op_subl_T0_T1_cc();
99c475ab
FB
7003 break;
7004 }
7005 if (op != 1)
7006 gen_movl_reg_T0(s, rd);
7007 break;
7008 case 4:
7009 if (insn & (1 << 11)) {
7010 rd = (insn >> 8) & 7;
5899f386
FB
7011 /* load pc-relative. Bit 1 of PC is ignored. */
7012 val = s->pc + 2 + ((insn & 0xff) * 4);
7013 val &= ~(uint32_t)2;
99c475ab 7014 gen_op_movl_T1_im(val);
b5ff1b31 7015 gen_ldst(ldl, s);
99c475ab
FB
7016 gen_movl_reg_T0(s, rd);
7017 break;
7018 }
7019 if (insn & (1 << 10)) {
7020 /* data processing extended or blx */
7021 rd = (insn & 7) | ((insn >> 4) & 8);
7022 rm = (insn >> 3) & 0xf;
7023 op = (insn >> 8) & 3;
7024 switch (op) {
7025 case 0: /* add */
7026 gen_movl_T0_reg(s, rd);
7027 gen_movl_T1_reg(s, rm);
7028 gen_op_addl_T0_T1();
7029 gen_movl_reg_T0(s, rd);
7030 break;
7031 case 1: /* cmp */
7032 gen_movl_T0_reg(s, rd);
7033 gen_movl_T1_reg(s, rm);
7034 gen_op_subl_T0_T1_cc();
7035 break;
7036 case 2: /* mov/cpy */
7037 gen_movl_T0_reg(s, rm);
7038 gen_movl_reg_T0(s, rd);
7039 break;
7040 case 3:/* branch [and link] exchange thumb register */
7041 if (insn & (1 << 7)) {
7042 val = (uint32_t)s->pc | 1;
7043 gen_op_movl_T1_im(val);
7044 gen_movl_reg_T1(s, 14);
7045 }
7046 gen_movl_T0_reg(s, rm);
7047 gen_bx(s);
7048 break;
7049 }
7050 break;
7051 }
7052
7053 /* data processing register */
7054 rd = insn & 7;
7055 rm = (insn >> 3) & 7;
7056 op = (insn >> 6) & 0xf;
7057 if (op == 2 || op == 3 || op == 4 || op == 7) {
7058 /* the shift/rotate ops want the operands backwards */
7059 val = rm;
7060 rm = rd;
7061 rd = val;
7062 val = 1;
7063 } else {
7064 val = 0;
7065 }
7066
7067 if (op == 9) /* neg */
7068 gen_op_movl_T0_im(0);
7069 else if (op != 0xf) /* mvn doesn't read its first operand */
7070 gen_movl_T0_reg(s, rd);
7071
7072 gen_movl_T1_reg(s, rm);
5899f386 7073 switch (op) {
99c475ab
FB
7074 case 0x0: /* and */
7075 gen_op_andl_T0_T1();
9ee6e8bb
PB
7076 if (!s->condexec_mask)
7077 gen_op_logic_T0_cc();
99c475ab
FB
7078 break;
7079 case 0x1: /* eor */
7080 gen_op_xorl_T0_T1();
9ee6e8bb
PB
7081 if (!s->condexec_mask)
7082 gen_op_logic_T0_cc();
99c475ab
FB
7083 break;
7084 case 0x2: /* lsl */
9ee6e8bb
PB
7085 if (s->condexec_mask) {
7086 gen_op_shll_T1_T0();
7087 } else {
7088 gen_op_shll_T1_T0_cc();
7089 gen_op_logic_T1_cc();
7090 }
99c475ab
FB
7091 break;
7092 case 0x3: /* lsr */
9ee6e8bb
PB
7093 if (s->condexec_mask) {
7094 gen_op_shrl_T1_T0();
7095 } else {
7096 gen_op_shrl_T1_T0_cc();
7097 gen_op_logic_T1_cc();
7098 }
99c475ab
FB
7099 break;
7100 case 0x4: /* asr */
9ee6e8bb
PB
7101 if (s->condexec_mask) {
7102 gen_op_sarl_T1_T0();
7103 } else {
7104 gen_op_sarl_T1_T0_cc();
7105 gen_op_logic_T1_cc();
7106 }
99c475ab
FB
7107 break;
7108 case 0x5: /* adc */
9ee6e8bb 7109 if (s->condexec_mask)
b26eefb6 7110 gen_adc_T0_T1();
9ee6e8bb
PB
7111 else
7112 gen_op_adcl_T0_T1_cc();
99c475ab
FB
7113 break;
7114 case 0x6: /* sbc */
9ee6e8bb
PB
7115 if (s->condexec_mask)
7116 gen_op_sbcl_T0_T1();
7117 else
7118 gen_op_sbcl_T0_T1_cc();
99c475ab
FB
7119 break;
7120 case 0x7: /* ror */
9ee6e8bb
PB
7121 if (s->condexec_mask) {
7122 gen_op_rorl_T1_T0();
7123 } else {
7124 gen_op_rorl_T1_T0_cc();
7125 gen_op_logic_T1_cc();
7126 }
99c475ab
FB
7127 break;
7128 case 0x8: /* tst */
7129 gen_op_andl_T0_T1();
7130 gen_op_logic_T0_cc();
7131 rd = 16;
5899f386 7132 break;
99c475ab 7133 case 0x9: /* neg */
9ee6e8bb
PB
7134 if (s->condexec_mask)
7135 gen_op_subl_T0_T1();
7136 else
7137 gen_op_subl_T0_T1_cc();
99c475ab
FB
7138 break;
7139 case 0xa: /* cmp */
7140 gen_op_subl_T0_T1_cc();
7141 rd = 16;
7142 break;
7143 case 0xb: /* cmn */
7144 gen_op_addl_T0_T1_cc();
7145 rd = 16;
7146 break;
7147 case 0xc: /* orr */
7148 gen_op_orl_T0_T1();
9ee6e8bb
PB
7149 if (!s->condexec_mask)
7150 gen_op_logic_T0_cc();
99c475ab
FB
7151 break;
7152 case 0xd: /* mul */
7153 gen_op_mull_T0_T1();
9ee6e8bb
PB
7154 if (!s->condexec_mask)
7155 gen_op_logic_T0_cc();
99c475ab
FB
7156 break;
7157 case 0xe: /* bic */
7158 gen_op_bicl_T0_T1();
9ee6e8bb
PB
7159 if (!s->condexec_mask)
7160 gen_op_logic_T0_cc();
99c475ab
FB
7161 break;
7162 case 0xf: /* mvn */
7163 gen_op_notl_T1();
9ee6e8bb
PB
7164 if (!s->condexec_mask)
7165 gen_op_logic_T1_cc();
99c475ab 7166 val = 1;
5899f386 7167 rm = rd;
99c475ab
FB
7168 break;
7169 }
7170 if (rd != 16) {
7171 if (val)
5899f386 7172 gen_movl_reg_T1(s, rm);
99c475ab
FB
7173 else
7174 gen_movl_reg_T0(s, rd);
7175 }
7176 break;
7177
7178 case 5:
7179 /* load/store register offset. */
7180 rd = insn & 7;
7181 rn = (insn >> 3) & 7;
7182 rm = (insn >> 6) & 7;
7183 op = (insn >> 9) & 7;
7184 gen_movl_T1_reg(s, rn);
b26eefb6
PB
7185 tmp = load_reg(s, rm);
7186 tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
7187 dead_tmp(tmp);
99c475ab
FB
7188
7189 if (op < 3) /* store */
7190 gen_movl_T0_reg(s, rd);
7191
7192 switch (op) {
7193 case 0: /* str */
b5ff1b31 7194 gen_ldst(stl, s);
99c475ab
FB
7195 break;
7196 case 1: /* strh */
b5ff1b31 7197 gen_ldst(stw, s);
99c475ab
FB
7198 break;
7199 case 2: /* strb */
b5ff1b31 7200 gen_ldst(stb, s);
99c475ab
FB
7201 break;
7202 case 3: /* ldrsb */
b5ff1b31 7203 gen_ldst(ldsb, s);
99c475ab
FB
7204 break;
7205 case 4: /* ldr */
b5ff1b31 7206 gen_ldst(ldl, s);
99c475ab
FB
7207 break;
7208 case 5: /* ldrh */
b5ff1b31 7209 gen_ldst(lduw, s);
99c475ab
FB
7210 break;
7211 case 6: /* ldrb */
b5ff1b31 7212 gen_ldst(ldub, s);
99c475ab
FB
7213 break;
7214 case 7: /* ldrsh */
b5ff1b31 7215 gen_ldst(ldsw, s);
99c475ab
FB
7216 break;
7217 }
7218 if (op >= 3) /* load */
7219 gen_movl_reg_T0(s, rd);
7220 break;
7221
7222 case 6:
7223 /* load/store word immediate offset */
7224 rd = insn & 7;
7225 rn = (insn >> 3) & 7;
7226 gen_movl_T1_reg(s, rn);
7227 val = (insn >> 4) & 0x7c;
b26eefb6 7228 tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
99c475ab
FB
7229
7230 if (insn & (1 << 11)) {
7231 /* load */
b5ff1b31 7232 gen_ldst(ldl, s);
99c475ab
FB
7233 gen_movl_reg_T0(s, rd);
7234 } else {
7235 /* store */
7236 gen_movl_T0_reg(s, rd);
b5ff1b31 7237 gen_ldst(stl, s);
99c475ab
FB
7238 }
7239 break;
7240
7241 case 7:
7242 /* load/store byte immediate offset */
7243 rd = insn & 7;
7244 rn = (insn >> 3) & 7;
7245 gen_movl_T1_reg(s, rn);
7246 val = (insn >> 6) & 0x1f;
b26eefb6 7247 tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
99c475ab
FB
7248
7249 if (insn & (1 << 11)) {
7250 /* load */
b5ff1b31 7251 gen_ldst(ldub, s);
99c475ab
FB
7252 gen_movl_reg_T0(s, rd);
7253 } else {
7254 /* store */
7255 gen_movl_T0_reg(s, rd);
b5ff1b31 7256 gen_ldst(stb, s);
99c475ab
FB
7257 }
7258 break;
7259
7260 case 8:
7261 /* load/store halfword immediate offset */
7262 rd = insn & 7;
7263 rn = (insn >> 3) & 7;
7264 gen_movl_T1_reg(s, rn);
7265 val = (insn >> 5) & 0x3e;
b26eefb6 7266 tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
99c475ab
FB
7267
7268 if (insn & (1 << 11)) {
7269 /* load */
b5ff1b31 7270 gen_ldst(lduw, s);
99c475ab
FB
7271 gen_movl_reg_T0(s, rd);
7272 } else {
7273 /* store */
7274 gen_movl_T0_reg(s, rd);
b5ff1b31 7275 gen_ldst(stw, s);
99c475ab
FB
7276 }
7277 break;
7278
7279 case 9:
7280 /* load/store from stack */
7281 rd = (insn >> 8) & 7;
7282 gen_movl_T1_reg(s, 13);
7283 val = (insn & 0xff) * 4;
b26eefb6 7284 tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
99c475ab
FB
7285
7286 if (insn & (1 << 11)) {
7287 /* load */
b5ff1b31 7288 gen_ldst(ldl, s);
99c475ab
FB
7289 gen_movl_reg_T0(s, rd);
7290 } else {
7291 /* store */
7292 gen_movl_T0_reg(s, rd);
b5ff1b31 7293 gen_ldst(stl, s);
99c475ab
FB
7294 }
7295 break;
7296
7297 case 10:
7298 /* add to high reg */
7299 rd = (insn >> 8) & 7;
5899f386
FB
7300 if (insn & (1 << 11)) {
7301 /* SP */
7302 gen_movl_T0_reg(s, 13);
7303 } else {
7304 /* PC. bit 1 is ignored. */
7305 gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
7306 }
99c475ab
FB
7307 val = (insn & 0xff) * 4;
7308 gen_op_movl_T1_im(val);
7309 gen_op_addl_T0_T1();
7310 gen_movl_reg_T0(s, rd);
7311 break;
7312
7313 case 11:
7314 /* misc */
7315 op = (insn >> 8) & 0xf;
7316 switch (op) {
7317 case 0:
7318 /* adjust stack pointer */
b26eefb6 7319 tmp = load_reg(s, 13);
99c475ab
FB
7320 val = (insn & 0x7f) * 4;
7321 if (insn & (1 << 7))
7322 val = -(int32_t)val;
b26eefb6
PB
7323 tcg_gen_addi_i32(tmp, tmp, val);
7324 store_reg(s, 13, tmp);
99c475ab
FB
7325 break;
7326
9ee6e8bb
PB
7327 case 2: /* sign/zero extend. */
7328 ARCH(6);
7329 rd = insn & 7;
7330 rm = (insn >> 3) & 7;
7331 gen_movl_T1_reg(s, rm);
7332 switch ((insn >> 6) & 3) {
b26eefb6
PB
7333 case 0: gen_sxth(cpu_T[1]); break;
7334 case 1: gen_sxtb(cpu_T[1]); break;
7335 case 2: gen_uxth(cpu_T[1]); break;
7336 case 3: gen_uxtb(cpu_T[1]); break;
9ee6e8bb
PB
7337 }
7338 gen_movl_reg_T1(s, rd);
7339 break;
99c475ab
FB
7340 case 4: case 5: case 0xc: case 0xd:
7341 /* push/pop */
7342 gen_movl_T1_reg(s, 13);
5899f386
FB
7343 if (insn & (1 << 8))
7344 offset = 4;
99c475ab 7345 else
5899f386
FB
7346 offset = 0;
7347 for (i = 0; i < 8; i++) {
7348 if (insn & (1 << i))
7349 offset += 4;
7350 }
7351 if ((insn & (1 << 11)) == 0) {
b26eefb6 7352 gen_op_addl_T1_im(-offset);
5899f386 7353 }
99c475ab
FB
7354 for (i = 0; i < 8; i++) {
7355 if (insn & (1 << i)) {
7356 if (insn & (1 << 11)) {
7357 /* pop */
b5ff1b31 7358 gen_ldst(ldl, s);
99c475ab
FB
7359 gen_movl_reg_T0(s, i);
7360 } else {
7361 /* push */
7362 gen_movl_T0_reg(s, i);
b5ff1b31 7363 gen_ldst(stl, s);
99c475ab 7364 }
5899f386 7365 /* advance to the next address. */
b26eefb6 7366 gen_op_addl_T1_im(4);
99c475ab
FB
7367 }
7368 }
7369 if (insn & (1 << 8)) {
7370 if (insn & (1 << 11)) {
7371 /* pop pc */
b5ff1b31 7372 gen_ldst(ldl, s);
99c475ab
FB
7373 /* don't set the pc until the rest of the instruction
7374 has completed */
7375 } else {
7376 /* push lr */
7377 gen_movl_T0_reg(s, 14);
b5ff1b31 7378 gen_ldst(stl, s);
99c475ab 7379 }
b26eefb6 7380 gen_op_addl_T1_im(4);
99c475ab 7381 }
5899f386 7382 if ((insn & (1 << 11)) == 0) {
b26eefb6 7383 gen_op_addl_T1_im(-offset);
5899f386 7384 }
99c475ab
FB
7385 /* write back the new stack pointer */
7386 gen_movl_reg_T1(s, 13);
7387 /* set the new PC value */
7388 if ((insn & 0x0900) == 0x0900)
7389 gen_bx(s);
7390 break;
7391
9ee6e8bb
PB
7392 case 1: case 3: case 9: case 11: /* czb */
7393 rm = insn & 7;
7394 gen_movl_T0_reg(s, rm);
7395 s->condlabel = gen_new_label();
7396 s->condjmp = 1;
7397 if (insn & (1 << 11))
7398 gen_op_testn_T0(s->condlabel);
7399 else
7400 gen_op_test_T0(s->condlabel);
7401
7402 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
7403 val = (uint32_t)s->pc + 2;
7404 val += offset;
7405 gen_jmp(s, val);
7406 break;
7407
7408 case 15: /* IT, nop-hint. */
7409 if ((insn & 0xf) == 0) {
7410 gen_nop_hint(s, (insn >> 4) & 0xf);
7411 break;
7412 }
7413 /* If Then. */
7414 s->condexec_cond = (insn >> 4) & 0xe;
7415 s->condexec_mask = insn & 0x1f;
7416 /* No actual code generated for this insn, just setup state. */
7417 break;
7418
06c949e6 7419 case 0xe: /* bkpt */
9ee6e8bb 7420 gen_set_condexec(s);
06c949e6 7421 gen_op_movl_T0_im((long)s->pc - 2);
b26eefb6 7422 gen_set_pc_T0();
06c949e6
PB
7423 gen_op_bkpt();
7424 s->is_jmp = DISAS_JUMP;
7425 break;
7426
9ee6e8bb
PB
7427 case 0xa: /* rev */
7428 ARCH(6);
7429 rn = (insn >> 3) & 0x7;
7430 rd = insn & 0x7;
7431 gen_movl_T0_reg(s, rn);
7432 switch ((insn >> 6) & 3) {
7433 case 0: gen_op_rev_T0(); break;
7434 case 1: gen_op_rev16_T0(); break;
7435 case 3: gen_op_revsh_T0(); break;
7436 default: goto illegal_op;
7437 }
7438 gen_movl_reg_T0(s, rd);
7439 break;
7440
7441 case 6: /* cps */
7442 ARCH(6);
7443 if (IS_USER(s))
7444 break;
7445 if (IS_M(env)) {
7446 val = (insn & (1 << 4)) != 0;
7447 gen_op_movl_T0_im(val);
7448 /* PRIMASK */
7449 if (insn & 1)
7450 gen_op_v7m_msr_T0(16);
7451 /* FAULTMASK */
7452 if (insn & 2)
7453 gen_op_v7m_msr_T0(17);
7454
7455 gen_lookup_tb(s);
7456 } else {
7457 if (insn & (1 << 4))
7458 shift = CPSR_A | CPSR_I | CPSR_F;
7459 else
7460 shift = 0;
7461
7462 val = ((insn & 7) << 6) & shift;
7463 gen_op_movl_T0_im(val);
7464 gen_set_psr_T0(s, shift, 0);
7465 }
7466 break;
7467
99c475ab
FB
7468 default:
7469 goto undef;
7470 }
7471 break;
7472
7473 case 12:
7474 /* load/store multiple */
7475 rn = (insn >> 8) & 0x7;
7476 gen_movl_T1_reg(s, rn);
99c475ab
FB
7477 for (i = 0; i < 8; i++) {
7478 if (insn & (1 << i)) {
99c475ab
FB
7479 if (insn & (1 << 11)) {
7480 /* load */
b5ff1b31 7481 gen_ldst(ldl, s);
99c475ab
FB
7482 gen_movl_reg_T0(s, i);
7483 } else {
7484 /* store */
7485 gen_movl_T0_reg(s, i);
b5ff1b31 7486 gen_ldst(stl, s);
99c475ab 7487 }
5899f386 7488 /* advance to the next address */
b26eefb6 7489 gen_op_addl_T1_im(4);
99c475ab
FB
7490 }
7491 }
5899f386 7492 /* Base register writeback. */
b5ff1b31
FB
7493 if ((insn & (1 << rn)) == 0)
7494 gen_movl_reg_T1(s, rn);
99c475ab
FB
7495 break;
7496
7497 case 13:
7498 /* conditional branch or swi */
7499 cond = (insn >> 8) & 0xf;
7500 if (cond == 0xe)
7501 goto undef;
7502
7503 if (cond == 0xf) {
7504 /* swi */
9ee6e8bb 7505 gen_set_condexec(s);
99c475ab
FB
7506 gen_op_movl_T0_im((long)s->pc | 1);
7507 /* Don't set r15. */
b26eefb6 7508 gen_set_pc_T0();
9ee6e8bb 7509 s->is_jmp = DISAS_SWI;
99c475ab
FB
7510 break;
7511 }
7512 /* generate a conditional jump to next instruction */
e50e6a20
FB
7513 s->condlabel = gen_new_label();
7514 gen_test_cc[cond ^ 1](s->condlabel);
7515 s->condjmp = 1;
99c475ab
FB
7516 gen_movl_T1_reg(s, 15);
7517
7518 /* jump to the offset */
5899f386 7519 val = (uint32_t)s->pc + 2;
99c475ab 7520 offset = ((int32_t)insn << 24) >> 24;
5899f386 7521 val += offset << 1;
8aaca4c0 7522 gen_jmp(s, val);
99c475ab
FB
7523 break;
7524
7525 case 14:
358bf29e 7526 if (insn & (1 << 11)) {
9ee6e8bb
PB
7527 if (disas_thumb2_insn(env, s, insn))
7528 goto undef32;
358bf29e
PB
7529 break;
7530 }
9ee6e8bb 7531 /* unconditional branch */
99c475ab
FB
7532 val = (uint32_t)s->pc;
7533 offset = ((int32_t)insn << 21) >> 21;
7534 val += (offset << 1) + 2;
8aaca4c0 7535 gen_jmp(s, val);
99c475ab
FB
7536 break;
7537
7538 case 15:
9ee6e8bb
PB
7539 if (disas_thumb2_insn(env, s, insn))
7540 goto undef32;
7541 break;
99c475ab
FB
7542 }
7543 return;
9ee6e8bb
PB
7544undef32:
7545 gen_set_condexec(s);
7546 gen_op_movl_T0_im((long)s->pc - 4);
b26eefb6 7547 gen_set_pc_T0();
9ee6e8bb
PB
7548 gen_op_undef_insn();
7549 s->is_jmp = DISAS_JUMP;
7550 return;
7551illegal_op:
99c475ab 7552undef:
9ee6e8bb 7553 gen_set_condexec(s);
5899f386 7554 gen_op_movl_T0_im((long)s->pc - 2);
b26eefb6 7555 gen_set_pc_T0();
99c475ab
FB
7556 gen_op_undef_insn();
7557 s->is_jmp = DISAS_JUMP;
7558}
7559
2c0262af
FB
7560/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7561 basic block 'tb'. If search_pc is TRUE, also generate PC
7562 information for each intermediate instruction. */
5fafdf24
TS
7563static inline int gen_intermediate_code_internal(CPUState *env,
7564 TranslationBlock *tb,
2c0262af
FB
7565 int search_pc)
7566{
7567 DisasContext dc1, *dc = &dc1;
7568 uint16_t *gen_opc_end;
7569 int j, lj;
0fa85d43 7570 target_ulong pc_start;
b5ff1b31 7571 uint32_t next_page_start;
3b46e624 7572
2c0262af 7573 /* generate intermediate code */
b26eefb6
PB
7574 num_temps = 0;
7575 memset(temps, 0, sizeof(temps));
7576
0fa85d43 7577 pc_start = tb->pc;
3b46e624 7578
2c0262af
FB
7579 dc->tb = tb;
7580
2c0262af 7581 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
7582
7583 dc->is_jmp = DISAS_NEXT;
7584 dc->pc = pc_start;
8aaca4c0 7585 dc->singlestep_enabled = env->singlestep_enabled;
e50e6a20 7586 dc->condjmp = 0;
5899f386 7587 dc->thumb = env->thumb;
9ee6e8bb
PB
7588 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
7589 dc->condexec_cond = env->condexec_bits >> 4;
6658ffb8 7590 dc->is_mem = 0;
b5ff1b31 7591#if !defined(CONFIG_USER_ONLY)
9ee6e8bb
PB
7592 if (IS_M(env)) {
7593 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
7594 } else {
7595 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
7596 }
b5ff1b31
FB
7597#endif
7598 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2c0262af 7599 lj = -1;
9ee6e8bb
PB
7600 /* Reset the conditional execution bits immediately. This avoids
7601 complications trying to do it at the end of the block. */
7602 if (env->condexec_bits)
7603 gen_op_set_condexec(0);
2c0262af 7604 do {
9ee6e8bb
PB
7605#ifndef CONFIG_USER_ONLY
7606 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
7607 /* We always get here via a jump, so know we are not in a
7608 conditional execution block. */
7609 gen_op_exception_exit();
7610 }
7611#endif
7612
1fddef4b
FB
7613 if (env->nb_breakpoints > 0) {
7614 for(j = 0; j < env->nb_breakpoints; j++) {
7615 if (env->breakpoints[j] == dc->pc) {
9ee6e8bb 7616 gen_set_condexec(dc);
1fddef4b 7617 gen_op_movl_T0_im((long)dc->pc);
b26eefb6 7618 gen_set_pc_T0();
1fddef4b
FB
7619 gen_op_debug();
7620 dc->is_jmp = DISAS_JUMP;
9ee6e8bb
PB
7621 /* Advance PC so that clearing the breakpoint will
7622 invalidate this TB. */
7623 dc->pc += 2;
7624 goto done_generating;
1fddef4b
FB
7625 break;
7626 }
7627 }
7628 }
2c0262af
FB
7629 if (search_pc) {
7630 j = gen_opc_ptr - gen_opc_buf;
7631 if (lj < j) {
7632 lj++;
7633 while (lj < j)
7634 gen_opc_instr_start[lj++] = 0;
7635 }
0fa85d43 7636 gen_opc_pc[lj] = dc->pc;
2c0262af
FB
7637 gen_opc_instr_start[lj] = 1;
7638 }
e50e6a20 7639
9ee6e8bb
PB
7640 if (env->thumb) {
7641 disas_thumb_insn(env, dc);
7642 if (dc->condexec_mask) {
7643 dc->condexec_cond = (dc->condexec_cond & 0xe)
7644 | ((dc->condexec_mask >> 4) & 1);
7645 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
7646 if (dc->condexec_mask == 0) {
7647 dc->condexec_cond = 0;
7648 }
7649 }
7650 } else {
7651 disas_arm_insn(env, dc);
7652 }
b26eefb6
PB
7653 if (num_temps) {
7654 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
7655 num_temps = 0;
7656 }
e50e6a20
FB
7657
7658 if (dc->condjmp && !dc->is_jmp) {
7659 gen_set_label(dc->condlabel);
7660 dc->condjmp = 0;
7661 }
6658ffb8
PB
7662 /* Terminate the TB on memory ops if watchpoints are present. */
7663 /* FIXME: This should be replacd by the deterministic execution
7664 * IRQ raising bits. */
7665 if (dc->is_mem && env->nb_watchpoints)
7666 break;
7667
e50e6a20
FB
7668 /* Translation stops when a conditional branch is enoutered.
7669 * Otherwise the subsequent code could get translated several times.
b5ff1b31
FB
7670 * Also stop translation when a page boundary is reached. This
7671 * ensures prefech aborts occur at the right place. */
1fddef4b
FB
7672 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
7673 !env->singlestep_enabled &&
b5ff1b31 7674 dc->pc < next_page_start);
9ee6e8bb 7675
b5ff1b31 7676 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
7677 instruction was a conditional branch or trap, and the PC has
7678 already been written. */
8aaca4c0
FB
7679 if (__builtin_expect(env->singlestep_enabled, 0)) {
7680 /* Make sure the pc is updated, and raise a debug exception. */
e50e6a20 7681 if (dc->condjmp) {
9ee6e8bb
PB
7682 gen_set_condexec(dc);
7683 if (dc->is_jmp == DISAS_SWI) {
7684 gen_op_swi();
7685 } else {
7686 gen_op_debug();
7687 }
e50e6a20
FB
7688 gen_set_label(dc->condlabel);
7689 }
7690 if (dc->condjmp || !dc->is_jmp) {
8aaca4c0 7691 gen_op_movl_T0_im((long)dc->pc);
b26eefb6 7692 gen_set_pc_T0();
e50e6a20 7693 dc->condjmp = 0;
8aaca4c0 7694 }
9ee6e8bb
PB
7695 gen_set_condexec(dc);
7696 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
7697 gen_op_swi();
7698 } else {
7699 /* FIXME: Single stepping a WFI insn will not halt
7700 the CPU. */
7701 gen_op_debug();
7702 }
8aaca4c0 7703 } else {
9ee6e8bb
PB
7704 /* While branches must always occur at the end of an IT block,
7705 there are a few other things that can cause us to terminate
7706 the TB in the middel of an IT block:
7707 - Exception generating instructions (bkpt, swi, undefined).
7708 - Page boundaries.
7709 - Hardware watchpoints.
7710 Hardware breakpoints have already been handled and skip this code.
7711 */
7712 gen_set_condexec(dc);
8aaca4c0 7713 switch(dc->is_jmp) {
8aaca4c0 7714 case DISAS_NEXT:
6e256c93 7715 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0
FB
7716 break;
7717 default:
7718 case DISAS_JUMP:
7719 case DISAS_UPDATE:
7720 /* indicate that the hash table must be used to find the next TB */
57fec1fe 7721 tcg_gen_exit_tb(0);
8aaca4c0
FB
7722 break;
7723 case DISAS_TB_JUMP:
7724 /* nothing more to generate */
7725 break;
9ee6e8bb
PB
7726 case DISAS_WFI:
7727 gen_op_wfi();
7728 break;
7729 case DISAS_SWI:
7730 gen_op_swi();
7731 break;
8aaca4c0 7732 }
e50e6a20
FB
7733 if (dc->condjmp) {
7734 gen_set_label(dc->condlabel);
9ee6e8bb 7735 gen_set_condexec(dc);
6e256c93 7736 gen_goto_tb(dc, 1, dc->pc);
e50e6a20
FB
7737 dc->condjmp = 0;
7738 }
2c0262af 7739 }
9ee6e8bb 7740done_generating:
2c0262af
FB
7741 *gen_opc_ptr = INDEX_op_end;
7742
7743#ifdef DEBUG_DISAS
e19e89a5 7744 if (loglevel & CPU_LOG_TB_IN_ASM) {
2c0262af
FB
7745 fprintf(logfile, "----------------\n");
7746 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
5899f386 7747 target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2c0262af
FB
7748 fprintf(logfile, "\n");
7749 }
7750#endif
b5ff1b31
FB
7751 if (search_pc) {
7752 j = gen_opc_ptr - gen_opc_buf;
7753 lj++;
7754 while (lj <= j)
7755 gen_opc_instr_start[lj++] = 0;
b5ff1b31 7756 } else {
2c0262af 7757 tb->size = dc->pc - pc_start;
b5ff1b31 7758 }
2c0262af
FB
7759 return 0;
7760}
7761
7762int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
7763{
7764 return gen_intermediate_code_internal(env, tb, 0);
7765}
7766
7767int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
7768{
7769 return gen_intermediate_code_internal(env, tb, 1);
7770}
7771
b5ff1b31
FB
7772static const char *cpu_mode_names[16] = {
7773 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
7774 "???", "???", "???", "und", "???", "???", "???", "sys"
7775};
9ee6e8bb 7776
5fafdf24 7777void cpu_dump_state(CPUState *env, FILE *f,
7fe48483
FB
7778 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7779 int flags)
2c0262af
FB
7780{
7781 int i;
bc380d17 7782 union {
b7bcbe95
FB
7783 uint32_t i;
7784 float s;
7785 } s0, s1;
7786 CPU_DoubleU d;
a94a6abf
PB
7787 /* ??? This assumes float64 and double have the same layout.
7788 Oh well, it's only debug dumps. */
7789 union {
7790 float64 f64;
7791 double d;
7792 } d0;
b5ff1b31 7793 uint32_t psr;
2c0262af
FB
7794
7795 for(i=0;i<16;i++) {
7fe48483 7796 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 7797 if ((i % 4) == 3)
7fe48483 7798 cpu_fprintf(f, "\n");
2c0262af 7799 else
7fe48483 7800 cpu_fprintf(f, " ");
2c0262af 7801 }
b5ff1b31 7802 psr = cpsr_read(env);
687fa640
TS
7803 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
7804 psr,
b5ff1b31
FB
7805 psr & (1 << 31) ? 'N' : '-',
7806 psr & (1 << 30) ? 'Z' : '-',
7807 psr & (1 << 29) ? 'C' : '-',
7808 psr & (1 << 28) ? 'V' : '-',
5fafdf24 7809 psr & CPSR_T ? 'T' : 'A',
b5ff1b31 7810 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
b7bcbe95
FB
7811
7812 for (i = 0; i < 16; i++) {
8e96005d
FB
7813 d.d = env->vfp.regs[i];
7814 s0.i = d.l.lower;
7815 s1.i = d.l.upper;
a94a6abf
PB
7816 d0.f64 = d.d;
7817 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
b7bcbe95 7818 i * 2, (int)s0.i, s0.s,
a94a6abf 7819 i * 2 + 1, (int)s1.i, s1.s,
b7bcbe95 7820 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
a94a6abf 7821 d0.d);
b7bcbe95 7822 }
40f137e1 7823 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
2c0262af 7824}
a6b025d3 7825