4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
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.
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.
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
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)
42 #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
44 /* internal defines */
45 typedef struct DisasContext
{
48 /* Nonzero if this instruction has been conditionally skipped. */
50 /* The label that will be jumped to when the instruction is skipped. */
52 /* Thumb-2 condtional execution bits. */
55 struct TranslationBlock
*tb
;
56 int singlestep_enabled
;
59 #if !defined(CONFIG_USER_ONLY)
64 #if defined(CONFIG_USER_ONLY)
67 #define IS_USER(s) (s->user)
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
75 /* XXX: move that elsewhere */
80 /* FIXME: These should be removed. */
83 /* initialize TCG globals. */
84 void arm_translate_init(void)
86 cpu_env
= tcg_global_reg_new(TCG_TYPE_PTR
, TCG_AREG0
, "env");
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");
93 /* The code generator doesn't like lots of temporaries, so maintain our own
94 cache for reuse within a function. */
97 static TCGv temps
[MAX_TEMPS
];
99 /* Allocate a temporary variable. */
100 static TCGv
new_tmp(void)
103 if (num_temps
== MAX_TEMPS
)
106 if (GET_TCGV(temps
[num_temps
]))
107 return temps
[num_temps
++];
109 tmp
= tcg_temp_new(TCG_TYPE_I32
);
110 temps
[num_temps
++] = tmp
;
114 /* Release a temporary variable. */
115 static void dead_tmp(TCGv tmp
)
120 if (GET_TCGV(temps
[i
]) == GET_TCGV(tmp
))
123 /* Shuffle this temp to the last slot. */
124 while (GET_TCGV(temps
[i
]) != GET_TCGV(tmp
))
126 while (i
< num_temps
) {
127 temps
[i
] = temps
[i
+ 1];
133 /* Set a variable to the value of a CPU register. */
134 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
138 /* normaly, since we updated PC, we need only to add one insn */
140 addr
= (long)s
->pc
+ 2;
142 addr
= (long)s
->pc
+ 4;
143 tcg_gen_movi_i32(var
, addr
);
145 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
149 /* Create a new temporary and set it to the value of a CPU register. */
150 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
152 TCGv tmp
= new_tmp();
153 load_reg_var(s
, tmp
, reg
);
157 /* Set a CPU register. The source must be a temporary and will be
159 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
162 tcg_gen_andi_i32(var
, var
, ~1);
163 s
->is_jmp
= DISAS_JUMP
;
165 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
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)
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])
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]);
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)
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)
205 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
207 #define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0])
209 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_addl_T0_T1_setq() \
212 gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_op_addl_T0_T1_saturate() \
214 gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
215 #define gen_op_subl_T0_T1_saturate() \
216 gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
217 #define gen_op_addl_T0_T1_usaturate() \
218 gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
219 #define gen_op_subl_T0_T1_usaturate() \
220 gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
222 /* Copy the most significant bit of T0 to all bits of T1. */
223 #define gen_op_signbit_T1_T0() tcg_gen_sari_i32(cpu_T[1], cpu_T[0], 31)
225 static void gen_smul_dual(TCGv a
, TCGv b
)
227 TCGv tmp1
= new_tmp();
228 TCGv tmp2
= new_tmp();
229 tcg_gen_ext8s_i32(tmp1
, a
);
230 tcg_gen_ext8s_i32(tmp2
, b
);
231 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
233 tcg_gen_sari_i32(a
, a
, 16);
234 tcg_gen_sari_i32(b
, b
, 16);
235 tcg_gen_mul_i32(b
, b
, a
);
236 tcg_gen_mov_i32(a
, tmp1
);
240 /* Byteswap each halfword. */
241 static void gen_rev16(TCGv var
)
243 TCGv tmp
= new_tmp();
244 tcg_gen_shri_i32(tmp
, var
, 8);
245 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
246 tcg_gen_shli_i32(var
, var
, 8);
247 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
248 tcg_gen_or_i32(var
, var
, tmp
);
252 /* Byteswap low halfword and sign extend. */
253 static void gen_revsh(TCGv var
)
255 TCGv tmp
= new_tmp();
256 tcg_gen_shri_i32(tmp
, var
, 8);
257 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
258 tcg_gen_shli_i32(var
, var
, 8);
259 tcg_gen_ext8s_i32(var
, var
);
260 tcg_gen_or_i32(var
, var
, tmp
);
264 /* Unsigned bitfield extract. */
265 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
268 tcg_gen_shri_i32(var
, var
, shift
);
269 tcg_gen_andi_i32(var
, var
, mask
);
272 /* Signed bitfield extract. */
273 static void gen_sbfx(TCGv var
, int shift
, int width
)
278 tcg_gen_sari_i32(var
, var
, shift
);
279 if (shift
+ width
< 32) {
280 signbit
= 1u << (width
- 1);
281 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
282 tcg_gen_xori_i32(var
, var
, signbit
);
283 tcg_gen_subi_i32(var
, var
, signbit
);
287 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
288 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
290 tcg_gen_shli_i32(val
, val
, shift
);
291 tcg_gen_andi_i32(val
, val
, mask
);
292 tcg_gen_andi_i32(base
, base
, ~mask
);
293 tcg_gen_or_i32(dest
, base
, val
);
296 static void gen_op_roundqd_T0_T1(void)
298 tcg_gen_shri_i32(cpu_T
[0], cpu_T
[0], 31);
299 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], cpu_T
[1]);
302 /* FIXME: Most targets have native widening multiplication.
303 It would be good to use that instead of a full wide multiply. */
304 /* Unsigned 32x32->64 multiply. */
305 static void gen_op_mull_T0_T1(void)
307 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
308 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
310 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
311 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
312 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
313 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
314 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
315 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
318 /* Signed 32x32->64 multiply. */
319 static void gen_op_imull_T0_T1(void)
321 TCGv tmp1
= tcg_temp_new(TCG_TYPE_I64
);
322 TCGv tmp2
= tcg_temp_new(TCG_TYPE_I64
);
324 tcg_gen_ext_i32_i64(tmp1
, cpu_T
[0]);
325 tcg_gen_ext_i32_i64(tmp2
, cpu_T
[1]);
326 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
327 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
328 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
329 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
332 /* Swap low and high halfwords. */
333 static void gen_swap_half(TCGv var
)
335 TCGv tmp
= new_tmp();
336 tcg_gen_shri_i32(tmp
, var
, 16);
337 tcg_gen_shli_i32(var
, var
, 16);
338 tcg_gen_or_i32(var
, var
, tmp
);
342 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
343 tmp = (t0 ^ t1) & 0x8000;
346 t0 = (t0 + t1) ^ tmp;
349 static void gen_add16(TCGv t0
, TCGv t1
)
351 TCGv tmp
= new_tmp();
352 tcg_gen_xor_i32(tmp
, t0
, t1
);
353 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
354 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
355 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
356 tcg_gen_add_i32(t0
, t0
, t1
);
357 tcg_gen_xor_i32(t0
, t0
, tmp
);
362 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
364 /* Set CF to the top bit of var. */
365 static void gen_set_CF_bit31(TCGv var
)
367 TCGv tmp
= new_tmp();
368 tcg_gen_shri_i32(tmp
, var
, 31);
373 /* Set N and Z flags from var. */
374 static inline void gen_logic_CC(TCGv var
)
376 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NZF
));
380 static void gen_adc_T0_T1(void)
382 TCGv tmp
= new_tmp();
384 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUState
, CF
));
385 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
389 /* dest = T0 - T1 + CF - 1. */
390 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
392 TCGv tmp
= new_tmp();
393 tcg_gen_sub_i32(dest
, t0
, t1
);
394 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUState
, CF
));
395 tcg_gen_add_i32(dest
, dest
, tmp
);
396 tcg_gen_subi_i32(dest
, dest
, 1);
400 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
401 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
403 /* FIXME: Implement this natively. */
404 static inline void tcg_gen_not_i32(TCGv t0
, TCGv t1
)
406 tcg_gen_xori_i32(t0
, t1
, ~0);
409 /* T0 &= ~T1. Clobbers T1. */
410 /* FIXME: Implement bic natively. */
411 static inline void gen_op_bicl_T0_T1(void)
417 /* FIXME: Implement this natively. */
418 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
426 tcg_gen_shri_i32(tmp
, t1
, i
);
427 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
428 tcg_gen_or_i32(t0
, t1
, tmp
);
432 static void shifter_out_im(TCGv var
, int shift
)
434 TCGv tmp
= new_tmp();
436 tcg_gen_andi_i32(tmp
, var
, 1);
438 tcg_gen_shri_i32(tmp
, var
, shift
);
440 tcg_gen_andi_i32(tmp
, tmp
, 1);
446 /* Shift by immediate. Includes special handling for shift == 0. */
447 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
453 shifter_out_im(var
, 32 - shift
);
454 tcg_gen_shli_i32(var
, var
, shift
);
460 tcg_gen_shri_i32(var
, var
, 31);
463 tcg_gen_movi_i32(var
, 0);
466 shifter_out_im(var
, shift
- 1);
467 tcg_gen_shri_i32(var
, var
, shift
);
474 shifter_out_im(var
, shift
- 1);
477 tcg_gen_sari_i32(var
, var
, shift
);
479 case 3: /* ROR/RRX */
482 shifter_out_im(var
, shift
- 1);
483 tcg_gen_rori_i32(var
, var
, shift
); break;
485 TCGv tmp
= new_tmp();
486 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUState
, CF
));
488 shifter_out_im(var
, 0);
489 tcg_gen_shri_i32(var
, var
, 1);
490 tcg_gen_shli_i32(tmp
, tmp
, 31);
491 tcg_gen_or_i32(var
, var
, tmp
);
497 #define PAS_OP(pfx) \
499 case 0: gen_pas_helper(glue(pfx,add16)); break; \
500 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
501 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
502 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
503 case 4: gen_pas_helper(glue(pfx,add8)); break; \
504 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
506 void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
511 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
513 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
514 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
518 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
519 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
522 #undef gen_pas_helper
523 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
536 #undef gen_pas_helper
541 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
542 #define PAS_OP(pfx) \
544 case 0: gen_pas_helper(glue(pfx,add8)); break; \
545 case 1: gen_pas_helper(glue(pfx,add16)); break; \
546 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
547 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
548 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
549 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
551 void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
556 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
558 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
559 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
563 tmp
= tcg_temp_new(TCG_TYPE_PTR
);
564 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
567 #undef gen_pas_helper
568 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
581 #undef gen_pas_helper
586 static GenOpFunc1
*gen_test_cc
[14] = {
603 const uint8_t table_logic_cc
[16] = {
622 static GenOpFunc
*gen_shift_T1_T0
[4] = {
629 static GenOpFunc
*gen_shift_T1_T0_cc
[4] = {
630 gen_op_shll_T1_T0_cc
,
631 gen_op_shrl_T1_T0_cc
,
632 gen_op_sarl_T1_T0_cc
,
633 gen_op_rorl_T1_T0_cc
,
636 /* Set PC and thumb state from T0. Clobbers T0. */
637 static inline void gen_bx(DisasContext
*s
)
641 s
->is_jmp
= DISAS_UPDATE
;
643 tcg_gen_andi_i32(tmp
, cpu_T
[0], 1);
644 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
646 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], ~1);
647 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, regs
[15]));
650 #if defined(CONFIG_USER_ONLY)
651 #define gen_ldst(name, s) gen_op_##name##_raw()
653 #define gen_ldst(name, s) do { \
656 gen_op_##name##_user(); \
658 gen_op_##name##_kernel(); \
662 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
664 load_reg_var(s
, cpu_T
[0], reg
);
667 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
669 load_reg_var(s
, cpu_T
[1], reg
);
672 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
674 load_reg_var(s
, cpu_T
[2], reg
);
677 static inline void gen_set_pc_T0(void)
679 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, regs
[15]));
682 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
687 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
691 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
694 s
->is_jmp
= DISAS_JUMP
;
698 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
700 gen_movl_reg_TN(s
, reg
, 0);
703 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
705 gen_movl_reg_TN(s
, reg
, 1);
708 /* Force a TB lookup after an instruction that changes the CPU state. */
709 static inline void gen_lookup_tb(DisasContext
*s
)
711 gen_op_movl_T0_im(s
->pc
);
712 gen_movl_reg_T0(s
, 15);
713 s
->is_jmp
= DISAS_UPDATE
;
716 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
)
718 int val
, rm
, shift
, shiftop
;
721 if (!(insn
& (1 << 25))) {
724 if (!(insn
& (1 << 23)))
727 gen_op_addl_T1_im(val
);
731 shift
= (insn
>> 7) & 0x1f;
732 shiftop
= (insn
>> 5) & 3;
733 offset
= load_reg(s
, rm
);
734 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
735 if (!(insn
& (1 << 23)))
736 tcg_gen_sub_i32(cpu_T
[1], cpu_T
[1], offset
);
738 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], offset
);
743 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
749 if (insn
& (1 << 22)) {
751 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
752 if (!(insn
& (1 << 23)))
756 gen_op_addl_T1_im(val
);
760 gen_op_addl_T1_im(extra
);
762 offset
= load_reg(s
, rm
);
763 if (!(insn
& (1 << 23)))
764 tcg_gen_sub_i32(cpu_T
[1], cpu_T
[1], offset
);
766 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], offset
);
771 #define VFP_OP(name) \
772 static inline void gen_vfp_##name(int dp) \
775 gen_op_vfp_##name##d(); \
777 gen_op_vfp_##name##s(); \
780 #define VFP_OP1(name) \
781 static inline void gen_vfp_##name(int dp, int arg) \
784 gen_op_vfp_##name##d(arg); \
786 gen_op_vfp_##name##s(arg); \
816 static inline void gen_vfp_fconst(int dp
, uint32_t val
)
819 gen_op_vfp_fconstd(val
);
821 gen_op_vfp_fconsts(val
);
824 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
827 gen_ldst(vfp_ldd
, s
);
829 gen_ldst(vfp_lds
, s
);
832 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
835 gen_ldst(vfp_std
, s
);
837 gen_ldst(vfp_sts
, s
);
841 vfp_reg_offset (int dp
, int reg
)
844 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
846 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
847 + offsetof(CPU_DoubleU
, l
.upper
);
849 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
850 + offsetof(CPU_DoubleU
, l
.lower
);
854 /* Return the offset of a 32-bit piece of a NEON register.
855 zero is the least significant end of the register. */
857 neon_reg_offset (int reg
, int n
)
861 return vfp_reg_offset(0, sreg
);
864 #define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
865 #define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
867 static inline void gen_mov_F0_vreg(int dp
, int reg
)
870 gen_op_vfp_getreg_F0d(vfp_reg_offset(dp
, reg
));
872 gen_op_vfp_getreg_F0s(vfp_reg_offset(dp
, reg
));
875 static inline void gen_mov_F1_vreg(int dp
, int reg
)
878 gen_op_vfp_getreg_F1d(vfp_reg_offset(dp
, reg
));
880 gen_op_vfp_getreg_F1s(vfp_reg_offset(dp
, reg
));
883 static inline void gen_mov_vreg_F0(int dp
, int reg
)
886 gen_op_vfp_setreg_F0d(vfp_reg_offset(dp
, reg
));
888 gen_op_vfp_setreg_F0s(vfp_reg_offset(dp
, reg
));
891 #define ARM_CP_RW_BIT (1 << 20)
893 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
898 rd
= (insn
>> 16) & 0xf;
899 gen_movl_T1_reg(s
, rd
);
901 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
902 if (insn
& (1 << 24)) {
904 if (insn
& (1 << 23))
905 gen_op_addl_T1_im(offset
);
907 gen_op_addl_T1_im(-offset
);
909 if (insn
& (1 << 21))
910 gen_movl_reg_T1(s
, rd
);
911 } else if (insn
& (1 << 21)) {
913 if (insn
& (1 << 23))
914 gen_op_movl_T0_im(offset
);
916 gen_op_movl_T0_im(- offset
);
918 gen_movl_reg_T0(s
, rd
);
919 } else if (!(insn
& (1 << 23)))
924 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
926 int rd
= (insn
>> 0) & 0xf;
929 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
932 gen_op_iwmmxt_movl_T0_wCx(rd
);
934 gen_op_iwmmxt_movl_T0_T1_wRn(rd
);
936 gen_op_movl_T1_im(mask
);
941 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
942 (ie. an undefined instruction). */
943 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
946 int rdhi
, rdlo
, rd0
, rd1
, i
;
948 if ((insn
& 0x0e000e00) == 0x0c000000) {
949 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
951 rdlo
= (insn
>> 12) & 0xf;
952 rdhi
= (insn
>> 16) & 0xf;
953 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
954 gen_op_iwmmxt_movl_T0_T1_wRn(wrd
);
955 gen_movl_reg_T0(s
, rdlo
);
956 gen_movl_reg_T1(s
, rdhi
);
958 gen_movl_T0_reg(s
, rdlo
);
959 gen_movl_T1_reg(s
, rdhi
);
960 gen_op_iwmmxt_movl_wRn_T0_T1(wrd
);
961 gen_op_iwmmxt_set_mup();
966 wrd
= (insn
>> 12) & 0xf;
967 if (gen_iwmmxt_address(s
, insn
))
969 if (insn
& ARM_CP_RW_BIT
) {
970 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
972 gen_op_iwmmxt_movl_wCx_T0(wrd
);
975 if (insn
& (1 << 22)) /* WLDRD */
976 gen_ldst(iwmmxt_ldq
, s
);
978 gen_ldst(iwmmxt_ldl
, s
);
980 if (insn
& (1 << 22)) /* WLDRH */
981 gen_ldst(iwmmxt_ldw
, s
);
983 gen_ldst(iwmmxt_ldb
, s
);
984 gen_op_iwmmxt_movq_wRn_M0(wrd
);
987 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
988 gen_op_iwmmxt_movl_T0_wCx(wrd
);
991 gen_op_iwmmxt_movq_M0_wRn(wrd
);
993 if (insn
& (1 << 22)) /* WSTRD */
994 gen_ldst(iwmmxt_stq
, s
);
996 gen_ldst(iwmmxt_stl
, s
);
998 if (insn
& (1 << 22)) /* WSTRH */
999 gen_ldst(iwmmxt_ldw
, s
);
1001 gen_ldst(iwmmxt_stb
, s
);
1007 if ((insn
& 0x0f000000) != 0x0e000000)
1010 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1011 case 0x000: /* WOR */
1012 wrd
= (insn
>> 12) & 0xf;
1013 rd0
= (insn
>> 0) & 0xf;
1014 rd1
= (insn
>> 16) & 0xf;
1015 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1016 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1017 gen_op_iwmmxt_setpsr_nz();
1018 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1019 gen_op_iwmmxt_set_mup();
1020 gen_op_iwmmxt_set_cup();
1022 case 0x011: /* TMCR */
1025 rd
= (insn
>> 12) & 0xf;
1026 wrd
= (insn
>> 16) & 0xf;
1028 case ARM_IWMMXT_wCID
:
1029 case ARM_IWMMXT_wCASF
:
1031 case ARM_IWMMXT_wCon
:
1032 gen_op_iwmmxt_set_cup();
1034 case ARM_IWMMXT_wCSSF
:
1035 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1036 gen_movl_T1_reg(s
, rd
);
1037 gen_op_bicl_T0_T1();
1038 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1040 case ARM_IWMMXT_wCGR0
:
1041 case ARM_IWMMXT_wCGR1
:
1042 case ARM_IWMMXT_wCGR2
:
1043 case ARM_IWMMXT_wCGR3
:
1044 gen_op_iwmmxt_set_cup();
1045 gen_movl_reg_T0(s
, rd
);
1046 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1052 case 0x100: /* WXOR */
1053 wrd
= (insn
>> 12) & 0xf;
1054 rd0
= (insn
>> 0) & 0xf;
1055 rd1
= (insn
>> 16) & 0xf;
1056 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1057 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1058 gen_op_iwmmxt_setpsr_nz();
1059 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1060 gen_op_iwmmxt_set_mup();
1061 gen_op_iwmmxt_set_cup();
1063 case 0x111: /* TMRC */
1066 rd
= (insn
>> 12) & 0xf;
1067 wrd
= (insn
>> 16) & 0xf;
1068 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1069 gen_movl_reg_T0(s
, rd
);
1071 case 0x300: /* WANDN */
1072 wrd
= (insn
>> 12) & 0xf;
1073 rd0
= (insn
>> 0) & 0xf;
1074 rd1
= (insn
>> 16) & 0xf;
1075 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1076 gen_op_iwmmxt_negq_M0();
1077 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1078 gen_op_iwmmxt_setpsr_nz();
1079 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1080 gen_op_iwmmxt_set_mup();
1081 gen_op_iwmmxt_set_cup();
1083 case 0x200: /* WAND */
1084 wrd
= (insn
>> 12) & 0xf;
1085 rd0
= (insn
>> 0) & 0xf;
1086 rd1
= (insn
>> 16) & 0xf;
1087 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1088 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1089 gen_op_iwmmxt_setpsr_nz();
1090 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1091 gen_op_iwmmxt_set_mup();
1092 gen_op_iwmmxt_set_cup();
1094 case 0x810: case 0xa10: /* WMADD */
1095 wrd
= (insn
>> 12) & 0xf;
1096 rd0
= (insn
>> 0) & 0xf;
1097 rd1
= (insn
>> 16) & 0xf;
1098 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1099 if (insn
& (1 << 21))
1100 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1102 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1103 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1104 gen_op_iwmmxt_set_mup();
1106 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1107 wrd
= (insn
>> 12) & 0xf;
1108 rd0
= (insn
>> 16) & 0xf;
1109 rd1
= (insn
>> 0) & 0xf;
1110 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1111 switch ((insn
>> 22) & 3) {
1113 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1116 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1119 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1124 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1125 gen_op_iwmmxt_set_mup();
1126 gen_op_iwmmxt_set_cup();
1128 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1129 wrd
= (insn
>> 12) & 0xf;
1130 rd0
= (insn
>> 16) & 0xf;
1131 rd1
= (insn
>> 0) & 0xf;
1132 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1133 switch ((insn
>> 22) & 3) {
1135 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1138 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1141 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1146 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1147 gen_op_iwmmxt_set_mup();
1148 gen_op_iwmmxt_set_cup();
1150 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1151 wrd
= (insn
>> 12) & 0xf;
1152 rd0
= (insn
>> 16) & 0xf;
1153 rd1
= (insn
>> 0) & 0xf;
1154 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1155 if (insn
& (1 << 22))
1156 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1158 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1159 if (!(insn
& (1 << 20)))
1160 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1161 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1162 gen_op_iwmmxt_set_mup();
1164 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1165 wrd
= (insn
>> 12) & 0xf;
1166 rd0
= (insn
>> 16) & 0xf;
1167 rd1
= (insn
>> 0) & 0xf;
1168 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1169 if (insn
& (1 << 21))
1170 gen_op_iwmmxt_mulsw_M0_wRn(rd1
, (insn
& (1 << 20)) ? 16 : 0);
1172 gen_op_iwmmxt_muluw_M0_wRn(rd1
, (insn
& (1 << 20)) ? 16 : 0);
1173 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1174 gen_op_iwmmxt_set_mup();
1176 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1177 wrd
= (insn
>> 12) & 0xf;
1178 rd0
= (insn
>> 16) & 0xf;
1179 rd1
= (insn
>> 0) & 0xf;
1180 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1181 if (insn
& (1 << 21))
1182 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1184 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1185 if (!(insn
& (1 << 20))) {
1186 if (insn
& (1 << 21))
1187 gen_op_iwmmxt_addsq_M0_wRn(wrd
);
1189 gen_op_iwmmxt_adduq_M0_wRn(wrd
);
1191 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1192 gen_op_iwmmxt_set_mup();
1194 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1195 wrd
= (insn
>> 12) & 0xf;
1196 rd0
= (insn
>> 16) & 0xf;
1197 rd1
= (insn
>> 0) & 0xf;
1198 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1199 switch ((insn
>> 22) & 3) {
1201 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1204 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1207 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1212 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1213 gen_op_iwmmxt_set_mup();
1214 gen_op_iwmmxt_set_cup();
1216 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1217 wrd
= (insn
>> 12) & 0xf;
1218 rd0
= (insn
>> 16) & 0xf;
1219 rd1
= (insn
>> 0) & 0xf;
1220 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1221 if (insn
& (1 << 22))
1222 gen_op_iwmmxt_avgw_M0_wRn(rd1
, (insn
>> 20) & 1);
1224 gen_op_iwmmxt_avgb_M0_wRn(rd1
, (insn
>> 20) & 1);
1225 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1226 gen_op_iwmmxt_set_mup();
1227 gen_op_iwmmxt_set_cup();
1229 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1230 wrd
= (insn
>> 12) & 0xf;
1231 rd0
= (insn
>> 16) & 0xf;
1232 rd1
= (insn
>> 0) & 0xf;
1233 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1234 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1235 gen_op_movl_T1_im(7);
1236 gen_op_andl_T0_T1();
1237 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1238 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1239 gen_op_iwmmxt_set_mup();
1241 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1242 rd
= (insn
>> 12) & 0xf;
1243 wrd
= (insn
>> 16) & 0xf;
1244 gen_movl_T0_reg(s
, rd
);
1245 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1246 switch ((insn
>> 6) & 3) {
1248 gen_op_movl_T1_im(0xff);
1249 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1252 gen_op_movl_T1_im(0xffff);
1253 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1256 gen_op_movl_T1_im(0xffffffff);
1257 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1262 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1263 gen_op_iwmmxt_set_mup();
1265 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1266 rd
= (insn
>> 12) & 0xf;
1267 wrd
= (insn
>> 16) & 0xf;
1270 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1271 switch ((insn
>> 22) & 3) {
1274 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1276 gen_op_movl_T1_im(0xff);
1277 gen_op_iwmmxt_extru_T0_M0_T1((insn
& 7) << 3);
1282 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1284 gen_op_movl_T1_im(0xffff);
1285 gen_op_iwmmxt_extru_T0_M0_T1((insn
& 3) << 4);
1289 gen_op_movl_T1_im(0xffffffff);
1290 gen_op_iwmmxt_extru_T0_M0_T1((insn
& 1) << 5);
1295 gen_movl_reg_T0(s
, rd
);
1297 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1298 if ((insn
& 0x000ff008) != 0x0003f000)
1300 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1301 switch ((insn
>> 22) & 3) {
1303 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1306 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1309 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1314 gen_op_shll_T1_im(28);
1315 gen_op_movl_T0_T1();
1316 gen_op_movl_cpsr_T0(0xf0000000);
1318 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1319 rd
= (insn
>> 12) & 0xf;
1320 wrd
= (insn
>> 16) & 0xf;
1321 gen_movl_T0_reg(s
, rd
);
1322 switch ((insn
>> 6) & 3) {
1324 gen_op_iwmmxt_bcstb_M0_T0();
1327 gen_op_iwmmxt_bcstw_M0_T0();
1330 gen_op_iwmmxt_bcstl_M0_T0();
1335 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1336 gen_op_iwmmxt_set_mup();
1338 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1339 if ((insn
& 0x000ff00f) != 0x0003f000)
1341 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1342 switch ((insn
>> 22) & 3) {
1344 for (i
= 0; i
< 7; i
++) {
1345 gen_op_shll_T1_im(4);
1346 gen_op_andl_T0_T1();
1350 for (i
= 0; i
< 3; i
++) {
1351 gen_op_shll_T1_im(8);
1352 gen_op_andl_T0_T1();
1356 gen_op_shll_T1_im(16);
1357 gen_op_andl_T0_T1();
1362 gen_op_movl_cpsr_T0(0xf0000000);
1364 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1365 wrd
= (insn
>> 12) & 0xf;
1366 rd0
= (insn
>> 16) & 0xf;
1367 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1368 switch ((insn
>> 22) & 3) {
1370 gen_op_iwmmxt_addcb_M0();
1373 gen_op_iwmmxt_addcw_M0();
1376 gen_op_iwmmxt_addcl_M0();
1381 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1382 gen_op_iwmmxt_set_mup();
1384 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1385 if ((insn
& 0x000ff00f) != 0x0003f000)
1387 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1388 switch ((insn
>> 22) & 3) {
1390 for (i
= 0; i
< 7; i
++) {
1391 gen_op_shll_T1_im(4);
1396 for (i
= 0; i
< 3; i
++) {
1397 gen_op_shll_T1_im(8);
1402 gen_op_shll_T1_im(16);
1408 gen_op_movl_T1_im(0xf0000000);
1409 gen_op_andl_T0_T1();
1410 gen_op_movl_cpsr_T0(0xf0000000);
1412 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1413 rd
= (insn
>> 12) & 0xf;
1414 rd0
= (insn
>> 16) & 0xf;
1415 if ((insn
& 0xf) != 0)
1417 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1418 switch ((insn
>> 22) & 3) {
1420 gen_op_iwmmxt_msbb_T0_M0();
1423 gen_op_iwmmxt_msbw_T0_M0();
1426 gen_op_iwmmxt_msbl_T0_M0();
1431 gen_movl_reg_T0(s
, rd
);
1433 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1434 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1435 wrd
= (insn
>> 12) & 0xf;
1436 rd0
= (insn
>> 16) & 0xf;
1437 rd1
= (insn
>> 0) & 0xf;
1438 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1439 switch ((insn
>> 22) & 3) {
1441 if (insn
& (1 << 21))
1442 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1444 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1447 if (insn
& (1 << 21))
1448 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1450 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1453 if (insn
& (1 << 21))
1454 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1456 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1461 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1462 gen_op_iwmmxt_set_mup();
1463 gen_op_iwmmxt_set_cup();
1465 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1466 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1467 wrd
= (insn
>> 12) & 0xf;
1468 rd0
= (insn
>> 16) & 0xf;
1469 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1470 switch ((insn
>> 22) & 3) {
1472 if (insn
& (1 << 21))
1473 gen_op_iwmmxt_unpacklsb_M0();
1475 gen_op_iwmmxt_unpacklub_M0();
1478 if (insn
& (1 << 21))
1479 gen_op_iwmmxt_unpacklsw_M0();
1481 gen_op_iwmmxt_unpackluw_M0();
1484 if (insn
& (1 << 21))
1485 gen_op_iwmmxt_unpacklsl_M0();
1487 gen_op_iwmmxt_unpacklul_M0();
1492 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1493 gen_op_iwmmxt_set_mup();
1494 gen_op_iwmmxt_set_cup();
1496 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1497 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1498 wrd
= (insn
>> 12) & 0xf;
1499 rd0
= (insn
>> 16) & 0xf;
1500 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1501 switch ((insn
>> 22) & 3) {
1503 if (insn
& (1 << 21))
1504 gen_op_iwmmxt_unpackhsb_M0();
1506 gen_op_iwmmxt_unpackhub_M0();
1509 if (insn
& (1 << 21))
1510 gen_op_iwmmxt_unpackhsw_M0();
1512 gen_op_iwmmxt_unpackhuw_M0();
1515 if (insn
& (1 << 21))
1516 gen_op_iwmmxt_unpackhsl_M0();
1518 gen_op_iwmmxt_unpackhul_M0();
1523 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1524 gen_op_iwmmxt_set_mup();
1525 gen_op_iwmmxt_set_cup();
1527 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1528 case 0x214: case 0x614: case 0xa14: case 0xe14:
1529 wrd
= (insn
>> 12) & 0xf;
1530 rd0
= (insn
>> 16) & 0xf;
1531 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1532 if (gen_iwmmxt_shift(insn
, 0xff))
1534 switch ((insn
>> 22) & 3) {
1538 gen_op_iwmmxt_srlw_M0_T0();
1541 gen_op_iwmmxt_srll_M0_T0();
1544 gen_op_iwmmxt_srlq_M0_T0();
1547 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1548 gen_op_iwmmxt_set_mup();
1549 gen_op_iwmmxt_set_cup();
1551 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1552 case 0x014: case 0x414: case 0x814: case 0xc14:
1553 wrd
= (insn
>> 12) & 0xf;
1554 rd0
= (insn
>> 16) & 0xf;
1555 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1556 if (gen_iwmmxt_shift(insn
, 0xff))
1558 switch ((insn
>> 22) & 3) {
1562 gen_op_iwmmxt_sraw_M0_T0();
1565 gen_op_iwmmxt_sral_M0_T0();
1568 gen_op_iwmmxt_sraq_M0_T0();
1571 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1572 gen_op_iwmmxt_set_mup();
1573 gen_op_iwmmxt_set_cup();
1575 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
1576 case 0x114: case 0x514: case 0x914: case 0xd14:
1577 wrd
= (insn
>> 12) & 0xf;
1578 rd0
= (insn
>> 16) & 0xf;
1579 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1580 if (gen_iwmmxt_shift(insn
, 0xff))
1582 switch ((insn
>> 22) & 3) {
1586 gen_op_iwmmxt_sllw_M0_T0();
1589 gen_op_iwmmxt_slll_M0_T0();
1592 gen_op_iwmmxt_sllq_M0_T0();
1595 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1596 gen_op_iwmmxt_set_mup();
1597 gen_op_iwmmxt_set_cup();
1599 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
1600 case 0x314: case 0x714: case 0xb14: case 0xf14:
1601 wrd
= (insn
>> 12) & 0xf;
1602 rd0
= (insn
>> 16) & 0xf;
1603 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1604 switch ((insn
>> 22) & 3) {
1608 if (gen_iwmmxt_shift(insn
, 0xf))
1610 gen_op_iwmmxt_rorw_M0_T0();
1613 if (gen_iwmmxt_shift(insn
, 0x1f))
1615 gen_op_iwmmxt_rorl_M0_T0();
1618 if (gen_iwmmxt_shift(insn
, 0x3f))
1620 gen_op_iwmmxt_rorq_M0_T0();
1623 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1624 gen_op_iwmmxt_set_mup();
1625 gen_op_iwmmxt_set_cup();
1627 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
1628 case 0x916: case 0xb16: case 0xd16: case 0xf16:
1629 wrd
= (insn
>> 12) & 0xf;
1630 rd0
= (insn
>> 16) & 0xf;
1631 rd1
= (insn
>> 0) & 0xf;
1632 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1633 switch ((insn
>> 22) & 3) {
1635 if (insn
& (1 << 21))
1636 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
1638 gen_op_iwmmxt_minub_M0_wRn(rd1
);
1641 if (insn
& (1 << 21))
1642 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
1644 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
1647 if (insn
& (1 << 21))
1648 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
1650 gen_op_iwmmxt_minul_M0_wRn(rd1
);
1655 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1656 gen_op_iwmmxt_set_mup();
1658 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
1659 case 0x816: case 0xa16: case 0xc16: case 0xe16:
1660 wrd
= (insn
>> 12) & 0xf;
1661 rd0
= (insn
>> 16) & 0xf;
1662 rd1
= (insn
>> 0) & 0xf;
1663 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1664 switch ((insn
>> 22) & 3) {
1666 if (insn
& (1 << 21))
1667 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
1669 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
1672 if (insn
& (1 << 21))
1673 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
1675 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
1678 if (insn
& (1 << 21))
1679 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
1681 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
1686 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1687 gen_op_iwmmxt_set_mup();
1689 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
1690 case 0x402: case 0x502: case 0x602: case 0x702:
1691 wrd
= (insn
>> 12) & 0xf;
1692 rd0
= (insn
>> 16) & 0xf;
1693 rd1
= (insn
>> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1695 gen_op_movl_T0_im((insn
>> 20) & 3);
1696 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1697 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1698 gen_op_iwmmxt_set_mup();
1700 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
1701 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1702 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1703 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1704 wrd
= (insn
>> 12) & 0xf;
1705 rd0
= (insn
>> 16) & 0xf;
1706 rd1
= (insn
>> 0) & 0xf;
1707 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1708 switch ((insn
>> 20) & 0xf) {
1710 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
1713 gen_op_iwmmxt_subub_M0_wRn(rd1
);
1716 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
1719 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
1722 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
1725 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
1728 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
1731 gen_op_iwmmxt_subul_M0_wRn(rd1
);
1734 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
1739 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1740 gen_op_iwmmxt_set_mup();
1741 gen_op_iwmmxt_set_cup();
1743 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
1744 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1745 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1746 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1747 wrd
= (insn
>> 12) & 0xf;
1748 rd0
= (insn
>> 16) & 0xf;
1749 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1750 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
1751 gen_op_iwmmxt_shufh_M0_T0();
1752 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1753 gen_op_iwmmxt_set_mup();
1754 gen_op_iwmmxt_set_cup();
1756 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
1757 case 0x418: case 0x518: case 0x618: case 0x718:
1758 case 0x818: case 0x918: case 0xa18: case 0xb18:
1759 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1760 wrd
= (insn
>> 12) & 0xf;
1761 rd0
= (insn
>> 16) & 0xf;
1762 rd1
= (insn
>> 0) & 0xf;
1763 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1764 switch ((insn
>> 20) & 0xf) {
1766 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
1769 gen_op_iwmmxt_addub_M0_wRn(rd1
);
1772 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
1775 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
1778 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
1781 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
1784 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
1787 gen_op_iwmmxt_addul_M0_wRn(rd1
);
1790 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
1795 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1796 gen_op_iwmmxt_set_mup();
1797 gen_op_iwmmxt_set_cup();
1799 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
1800 case 0x408: case 0x508: case 0x608: case 0x708:
1801 case 0x808: case 0x908: case 0xa08: case 0xb08:
1802 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1803 wrd
= (insn
>> 12) & 0xf;
1804 rd0
= (insn
>> 16) & 0xf;
1805 rd1
= (insn
>> 0) & 0xf;
1806 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1807 if (!(insn
& (1 << 20)))
1809 switch ((insn
>> 22) & 3) {
1813 if (insn
& (1 << 21))
1814 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
1816 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
1819 if (insn
& (1 << 21))
1820 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
1822 gen_op_iwmmxt_packul_M0_wRn(rd1
);
1825 if (insn
& (1 << 21))
1826 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
1828 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
1831 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1832 gen_op_iwmmxt_set_mup();
1833 gen_op_iwmmxt_set_cup();
1835 case 0x201: case 0x203: case 0x205: case 0x207:
1836 case 0x209: case 0x20b: case 0x20d: case 0x20f:
1837 case 0x211: case 0x213: case 0x215: case 0x217:
1838 case 0x219: case 0x21b: case 0x21d: case 0x21f:
1839 wrd
= (insn
>> 5) & 0xf;
1840 rd0
= (insn
>> 12) & 0xf;
1841 rd1
= (insn
>> 0) & 0xf;
1842 if (rd0
== 0xf || rd1
== 0xf)
1844 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1845 switch ((insn
>> 16) & 0xf) {
1846 case 0x0: /* TMIA */
1847 gen_movl_T0_reg(s
, rd0
);
1848 gen_movl_T1_reg(s
, rd1
);
1849 gen_op_iwmmxt_muladdsl_M0_T0_T1();
1851 case 0x8: /* TMIAPH */
1852 gen_movl_T0_reg(s
, rd0
);
1853 gen_movl_T1_reg(s
, rd1
);
1854 gen_op_iwmmxt_muladdsw_M0_T0_T1();
1856 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
1857 gen_movl_T1_reg(s
, rd0
);
1858 if (insn
& (1 << 16))
1859 gen_op_shrl_T1_im(16);
1860 gen_op_movl_T0_T1();
1861 gen_movl_T1_reg(s
, rd1
);
1862 if (insn
& (1 << 17))
1863 gen_op_shrl_T1_im(16);
1864 gen_op_iwmmxt_muladdswl_M0_T0_T1();
1869 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1870 gen_op_iwmmxt_set_mup();
1879 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
1880 (ie. an undefined instruction). */
1881 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1883 int acc
, rd0
, rd1
, rdhi
, rdlo
;
1885 if ((insn
& 0x0ff00f10) == 0x0e200010) {
1886 /* Multiply with Internal Accumulate Format */
1887 rd0
= (insn
>> 12) & 0xf;
1889 acc
= (insn
>> 5) & 7;
1894 switch ((insn
>> 16) & 0xf) {
1896 gen_movl_T0_reg(s
, rd0
);
1897 gen_movl_T1_reg(s
, rd1
);
1898 gen_op_iwmmxt_muladdsl_M0_T0_T1();
1900 case 0x8: /* MIAPH */
1901 gen_movl_T0_reg(s
, rd0
);
1902 gen_movl_T1_reg(s
, rd1
);
1903 gen_op_iwmmxt_muladdsw_M0_T0_T1();
1905 case 0xc: /* MIABB */
1906 case 0xd: /* MIABT */
1907 case 0xe: /* MIATB */
1908 case 0xf: /* MIATT */
1909 gen_movl_T1_reg(s
, rd0
);
1910 if (insn
& (1 << 16))
1911 gen_op_shrl_T1_im(16);
1912 gen_op_movl_T0_T1();
1913 gen_movl_T1_reg(s
, rd1
);
1914 if (insn
& (1 << 17))
1915 gen_op_shrl_T1_im(16);
1916 gen_op_iwmmxt_muladdswl_M0_T0_T1();
1922 gen_op_iwmmxt_movq_wRn_M0(acc
);
1926 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
1927 /* Internal Accumulator Access Format */
1928 rdhi
= (insn
>> 16) & 0xf;
1929 rdlo
= (insn
>> 12) & 0xf;
1935 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
1936 gen_op_iwmmxt_movl_T0_T1_wRn(acc
);
1937 gen_movl_reg_T0(s
, rdlo
);
1938 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1939 gen_op_andl_T0_T1();
1940 gen_movl_reg_T0(s
, rdhi
);
1942 gen_movl_T0_reg(s
, rdlo
);
1943 gen_movl_T1_reg(s
, rdhi
);
1944 gen_op_iwmmxt_movl_wRn_T0_T1(acc
);
1952 /* Disassemble system coprocessor instruction. Return nonzero if
1953 instruction is not defined. */
1954 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1956 uint32_t rd
= (insn
>> 12) & 0xf;
1957 uint32_t cp
= (insn
>> 8) & 0xf;
1962 if (insn
& ARM_CP_RW_BIT
) {
1963 if (!env
->cp
[cp
].cp_read
)
1965 gen_op_movl_T0_im((uint32_t) s
->pc
);
1967 gen_op_movl_T0_cp(insn
);
1968 gen_movl_reg_T0(s
, rd
);
1970 if (!env
->cp
[cp
].cp_write
)
1972 gen_op_movl_T0_im((uint32_t) s
->pc
);
1974 gen_movl_T0_reg(s
, rd
);
1975 gen_op_movl_cp_T0(insn
);
1980 static int cp15_user_ok(uint32_t insn
)
1982 int cpn
= (insn
>> 16) & 0xf;
1983 int cpm
= insn
& 0xf;
1984 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
1986 if (cpn
== 13 && cpm
== 0) {
1988 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
1992 /* ISB, DSB, DMB. */
1993 if ((cpm
== 5 && op
== 4)
1994 || (cpm
== 10 && (op
== 4 || op
== 5)))
2000 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2001 instruction is not defined. */
2002 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2006 /* M profile cores use memory mapped registers instead of cp15. */
2007 if (arm_feature(env
, ARM_FEATURE_M
))
2010 if ((insn
& (1 << 25)) == 0) {
2011 if (insn
& (1 << 20)) {
2015 /* mcrr. Used for block cache operations, so implement as no-op. */
2018 if ((insn
& (1 << 4)) == 0) {
2022 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2025 if ((insn
& 0x0fff0fff) == 0x0e070f90
2026 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2027 /* Wait for interrupt. */
2028 gen_op_movl_T0_im((long)s
->pc
);
2030 s
->is_jmp
= DISAS_WFI
;
2033 rd
= (insn
>> 12) & 0xf;
2034 if (insn
& ARM_CP_RW_BIT
) {
2035 gen_op_movl_T0_cp15(insn
);
2036 /* If the destination register is r15 then sets condition codes. */
2038 gen_movl_reg_T0(s
, rd
);
2040 gen_movl_T0_reg(s
, rd
);
2041 gen_op_movl_cp15_T0(insn
);
2042 /* Normally we would always end the TB here, but Linux
2043 * arch/arm/mach-pxa/sleep.S expects two instructions following
2044 * an MMU enable to execute from cache. Imitate this behaviour. */
2045 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2046 (insn
& 0x0fff0fff) != 0x0e010f10)
2052 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2053 #define VFP_SREG(insn, bigbit, smallbit) \
2054 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2055 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2056 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2057 reg = (((insn) >> (bigbit)) & 0x0f) \
2058 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2060 if (insn & (1 << (smallbit))) \
2062 reg = ((insn) >> (bigbit)) & 0x0f; \
2065 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2066 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2067 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2068 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2069 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2070 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2073 vfp_enabled(CPUState
* env
)
2075 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2078 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2079 (ie. an undefined instruction). */
2080 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2082 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2085 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2088 if (!vfp_enabled(env
)) {
2089 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2090 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2092 rn
= (insn
>> 16) & 0xf;
2093 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2094 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2097 dp
= ((insn
& 0xf00) == 0xb00);
2098 switch ((insn
>> 24) & 0xf) {
2100 if (insn
& (1 << 4)) {
2101 /* single register transfer */
2102 rd
= (insn
>> 12) & 0xf;
2107 VFP_DREG_N(rn
, insn
);
2110 if (insn
& 0x00c00060
2111 && !arm_feature(env
, ARM_FEATURE_NEON
))
2114 pass
= (insn
>> 21) & 1;
2115 if (insn
& (1 << 22)) {
2117 offset
= ((insn
>> 5) & 3) * 8;
2118 } else if (insn
& (1 << 5)) {
2120 offset
= (insn
& (1 << 6)) ? 16 : 0;
2125 if (insn
& ARM_CP_RW_BIT
) {
2129 NEON_GET_REG(T1
, rn
, pass
);
2131 gen_op_shrl_T1_im(offset
);
2132 if (insn
& (1 << 23))
2138 NEON_GET_REG(T1
, rn
, pass
);
2139 if (insn
& (1 << 23)) {
2141 gen_op_shrl_T1_im(16);
2147 gen_op_sarl_T1_im(16);
2154 NEON_GET_REG(T1
, rn
, pass
);
2157 gen_movl_reg_T1(s
, rd
);
2160 gen_movl_T0_reg(s
, rd
);
2161 if (insn
& (1 << 23)) {
2164 gen_op_neon_dup_u8(0);
2165 } else if (size
== 1) {
2166 gen_op_neon_dup_low16();
2168 NEON_SET_REG(T0
, rn
, 0);
2169 NEON_SET_REG(T0
, rn
, 1);
2174 NEON_GET_REG(T2
, rn
, pass
);
2175 gen_op_movl_T1_im(0xff);
2176 gen_op_andl_T0_T1();
2177 gen_op_neon_insert_elt(offset
, ~(0xff << offset
));
2178 NEON_SET_REG(T2
, rn
, pass
);
2181 NEON_GET_REG(T2
, rn
, pass
);
2182 gen_op_movl_T1_im(0xffff);
2183 gen_op_andl_T0_T1();
2184 bank_mask
= offset
? 0xffff : 0xffff0000;
2185 gen_op_neon_insert_elt(offset
, bank_mask
);
2186 NEON_SET_REG(T2
, rn
, pass
);
2189 NEON_SET_REG(T0
, rn
, pass
);
2195 if ((insn
& 0x6f) != 0x00)
2197 rn
= VFP_SREG_N(insn
);
2198 if (insn
& ARM_CP_RW_BIT
) {
2200 if (insn
& (1 << 21)) {
2201 /* system register */
2206 /* VFP2 allows access for FSID from userspace.
2207 VFP3 restricts all id registers to privileged
2210 && arm_feature(env
, ARM_FEATURE_VFP3
))
2212 gen_op_vfp_movl_T0_xreg(rn
);
2217 gen_op_vfp_movl_T0_xreg(rn
);
2219 case ARM_VFP_FPINST
:
2220 case ARM_VFP_FPINST2
:
2221 /* Not present in VFP3. */
2223 || arm_feature(env
, ARM_FEATURE_VFP3
))
2225 gen_op_vfp_movl_T0_xreg(rn
);
2229 gen_op_vfp_movl_T0_fpscr_flags();
2231 gen_op_vfp_movl_T0_fpscr();
2236 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2238 gen_op_vfp_movl_T0_xreg(rn
);
2244 gen_mov_F0_vreg(0, rn
);
2248 /* Set the 4 flag bits in the CPSR. */
2249 gen_op_movl_cpsr_T0(0xf0000000);
2251 gen_movl_reg_T0(s
, rd
);
2254 gen_movl_T0_reg(s
, rd
);
2255 if (insn
& (1 << 21)) {
2257 /* system register */
2262 /* Writes are ignored. */
2265 gen_op_vfp_movl_fpscr_T0();
2271 gen_op_vfp_movl_xreg_T0(rn
);
2274 case ARM_VFP_FPINST
:
2275 case ARM_VFP_FPINST2
:
2276 gen_op_vfp_movl_xreg_T0(rn
);
2283 gen_mov_vreg_F0(0, rn
);
2288 /* data processing */
2289 /* The opcode is in bits 23, 21, 20 and 6. */
2290 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2294 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2296 /* rn is register number */
2297 VFP_DREG_N(rn
, insn
);
2300 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2301 /* Integer or single precision destination. */
2302 rd
= VFP_SREG_D(insn
);
2304 VFP_DREG_D(rd
, insn
);
2307 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2308 /* Integer source. */
2309 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2311 VFP_DREG_M(rm
, insn
);
2314 rn
= VFP_SREG_N(insn
);
2315 if (op
== 15 && rn
== 15) {
2316 /* Double precision destination. */
2317 VFP_DREG_D(rd
, insn
);
2319 rd
= VFP_SREG_D(insn
);
2321 rm
= VFP_SREG_M(insn
);
2324 veclen
= env
->vfp
.vec_len
;
2325 if (op
== 15 && rn
> 3)
2328 /* Shut up compiler warnings. */
2339 /* Figure out what type of vector operation this is. */
2340 if ((rd
& bank_mask
) == 0) {
2345 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2347 delta_d
= env
->vfp
.vec_stride
+ 1;
2349 if ((rm
& bank_mask
) == 0) {
2350 /* mixed scalar/vector */
2359 /* Load the initial operands. */
2364 /* Integer source */
2365 gen_mov_F0_vreg(0, rm
);
2370 gen_mov_F0_vreg(dp
, rd
);
2371 gen_mov_F1_vreg(dp
, rm
);
2375 /* Compare with zero */
2376 gen_mov_F0_vreg(dp
, rd
);
2383 /* Source and destination the same. */
2384 gen_mov_F0_vreg(dp
, rd
);
2387 /* One source operand. */
2388 gen_mov_F0_vreg(dp
, rm
);
2392 /* Two source operands. */
2393 gen_mov_F0_vreg(dp
, rn
);
2394 gen_mov_F1_vreg(dp
, rm
);
2398 /* Perform the calculation. */
2400 case 0: /* mac: fd + (fn * fm) */
2402 gen_mov_F1_vreg(dp
, rd
);
2405 case 1: /* nmac: fd - (fn * fm) */
2408 gen_mov_F1_vreg(dp
, rd
);
2411 case 2: /* msc: -fd + (fn * fm) */
2413 gen_mov_F1_vreg(dp
, rd
);
2416 case 3: /* nmsc: -fd - (fn * fm) */
2418 gen_mov_F1_vreg(dp
, rd
);
2422 case 4: /* mul: fn * fm */
2425 case 5: /* nmul: -(fn * fm) */
2429 case 6: /* add: fn + fm */
2432 case 7: /* sub: fn - fm */
2435 case 8: /* div: fn / fm */
2438 case 14: /* fconst */
2439 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2442 n
= (insn
<< 12) & 0x80000000;
2443 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
2457 gen_vfp_fconst(dp
, n
);
2459 case 15: /* extension space */
2482 case 11: /* cmpez */
2486 case 15: /* single<->double conversion */
2488 gen_op_vfp_fcvtsd();
2490 gen_op_vfp_fcvtds();
2492 case 16: /* fuito */
2495 case 17: /* fsito */
2498 case 20: /* fshto */
2499 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2501 gen_vfp_shto(dp
, rm
);
2503 case 21: /* fslto */
2504 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2506 gen_vfp_slto(dp
, rm
);
2508 case 22: /* fuhto */
2509 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2511 gen_vfp_uhto(dp
, rm
);
2513 case 23: /* fulto */
2514 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2516 gen_vfp_ulto(dp
, rm
);
2518 case 24: /* ftoui */
2521 case 25: /* ftouiz */
2524 case 26: /* ftosi */
2527 case 27: /* ftosiz */
2530 case 28: /* ftosh */
2531 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2533 gen_vfp_tosh(dp
, rm
);
2535 case 29: /* ftosl */
2536 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2538 gen_vfp_tosl(dp
, rm
);
2540 case 30: /* ftouh */
2541 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2543 gen_vfp_touh(dp
, rm
);
2545 case 31: /* ftoul */
2546 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
2548 gen_vfp_toul(dp
, rm
);
2550 default: /* undefined */
2551 printf ("rn:%d\n", rn
);
2555 default: /* undefined */
2556 printf ("op:%d\n", op
);
2560 /* Write back the result. */
2561 if (op
== 15 && (rn
>= 8 && rn
<= 11))
2562 ; /* Comparison, do nothing. */
2563 else if (op
== 15 && rn
> 17)
2564 /* Integer result. */
2565 gen_mov_vreg_F0(0, rd
);
2566 else if (op
== 15 && rn
== 15)
2568 gen_mov_vreg_F0(!dp
, rd
);
2570 gen_mov_vreg_F0(dp
, rd
);
2572 /* break out of the loop if we have finished */
2576 if (op
== 15 && delta_m
== 0) {
2577 /* single source one-many */
2579 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
2581 gen_mov_vreg_F0(dp
, rd
);
2585 /* Setup the next operands. */
2587 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
2591 /* One source operand. */
2592 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
2594 gen_mov_F0_vreg(dp
, rm
);
2596 /* Two source operands. */
2597 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
2599 gen_mov_F0_vreg(dp
, rn
);
2601 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
2603 gen_mov_F1_vreg(dp
, rm
);
2611 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
2612 /* two-register transfer */
2613 rn
= (insn
>> 16) & 0xf;
2614 rd
= (insn
>> 12) & 0xf;
2616 VFP_DREG_M(rm
, insn
);
2618 rm
= VFP_SREG_M(insn
);
2621 if (insn
& ARM_CP_RW_BIT
) {
2624 gen_mov_F0_vreg(1, rm
);
2626 gen_movl_reg_T0(s
, rd
);
2627 gen_movl_reg_T1(s
, rn
);
2629 gen_mov_F0_vreg(0, rm
);
2631 gen_movl_reg_T0(s
, rn
);
2632 gen_mov_F0_vreg(0, rm
+ 1);
2634 gen_movl_reg_T0(s
, rd
);
2639 gen_movl_T0_reg(s
, rd
);
2640 gen_movl_T1_reg(s
, rn
);
2642 gen_mov_vreg_F0(1, rm
);
2644 gen_movl_T0_reg(s
, rn
);
2646 gen_mov_vreg_F0(0, rm
);
2647 gen_movl_T0_reg(s
, rd
);
2649 gen_mov_vreg_F0(0, rm
+ 1);
2654 rn
= (insn
>> 16) & 0xf;
2656 VFP_DREG_D(rd
, insn
);
2658 rd
= VFP_SREG_D(insn
);
2659 if (s
->thumb
&& rn
== 15) {
2660 gen_op_movl_T1_im(s
->pc
& ~2);
2662 gen_movl_T1_reg(s
, rn
);
2664 if ((insn
& 0x01200000) == 0x01000000) {
2665 /* Single load/store */
2666 offset
= (insn
& 0xff) << 2;
2667 if ((insn
& (1 << 23)) == 0)
2669 gen_op_addl_T1_im(offset
);
2670 if (insn
& (1 << 20)) {
2672 gen_mov_vreg_F0(dp
, rd
);
2674 gen_mov_F0_vreg(dp
, rd
);
2678 /* load/store multiple */
2680 n
= (insn
>> 1) & 0x7f;
2684 if (insn
& (1 << 24)) /* pre-decrement */
2685 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
2691 for (i
= 0; i
< n
; i
++) {
2692 if (insn
& ARM_CP_RW_BIT
) {
2695 gen_mov_vreg_F0(dp
, rd
+ i
);
2698 gen_mov_F0_vreg(dp
, rd
+ i
);
2701 gen_op_addl_T1_im(offset
);
2703 if (insn
& (1 << 21)) {
2705 if (insn
& (1 << 24))
2706 offset
= -offset
* n
;
2707 else if (dp
&& (insn
& 1))
2713 gen_op_addl_T1_im(offset
);
2714 gen_movl_reg_T1(s
, rn
);
2720 /* Should never happen. */
2726 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
2728 TranslationBlock
*tb
;
2731 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
2733 gen_op_movl_T0_im(dest
);
2735 tcg_gen_exit_tb((long)tb
+ n
);
2737 gen_op_movl_T0_im(dest
);
2743 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
2745 if (__builtin_expect(s
->singlestep_enabled
, 0)) {
2746 /* An indirect jump so that we still trigger the debug exception. */
2749 gen_op_movl_T0_im(dest
);
2752 gen_goto_tb(s
, 0, dest
);
2753 s
->is_jmp
= DISAS_TB_JUMP
;
2757 static inline void gen_mulxy(int x
, int y
)
2760 tcg_gen_sari_i32(cpu_T
[0], cpu_T
[0], 16);
2764 gen_op_sarl_T1_im(16);
2770 /* Return the mask of PSR bits set by a MSR instruction. */
2771 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
2775 if (flags
& (1 << 0))
2777 if (flags
& (1 << 1))
2779 if (flags
& (1 << 2))
2781 if (flags
& (1 << 3))
2784 /* Mask out undefined bits. */
2785 mask
&= ~CPSR_RESERVED
;
2786 if (!arm_feature(env
, ARM_FEATURE_V6
))
2787 mask
&= ~(CPSR_E
| CPSR_GE
);
2788 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
2790 /* Mask out execution state bits. */
2793 /* Mask out privileged bits. */
2799 /* Returns nonzero if access to the PSR is not permitted. */
2800 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
2803 /* ??? This is also undefined in system mode. */
2806 gen_op_movl_spsr_T0(mask
);
2808 gen_op_movl_cpsr_T0(mask
);
2814 /* Generate an old-style exception return. */
2815 static void gen_exception_return(DisasContext
*s
)
2818 gen_op_movl_T0_spsr();
2819 gen_op_movl_cpsr_T0(0xffffffff);
2820 s
->is_jmp
= DISAS_UPDATE
;
2823 /* Generate a v6 exception return. */
2824 static void gen_rfe(DisasContext
*s
)
2826 gen_op_movl_cpsr_T0(0xffffffff);
2827 gen_op_movl_T0_T2();
2829 s
->is_jmp
= DISAS_UPDATE
;
2833 gen_set_condexec (DisasContext
*s
)
2835 if (s
->condexec_mask
) {
2836 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
2837 TCGv tmp
= new_tmp();
2838 tcg_gen_movi_i32(tmp
, val
);
2839 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, condexec_bits
));
2844 static void gen_nop_hint(DisasContext
*s
, int val
)
2848 gen_op_movl_T0_im((long)s
->pc
);
2850 s
->is_jmp
= DISAS_WFI
;
2854 /* TODO: Implement SEV and WFE. May help SMP performance. */
2860 /* Neon shift by constant. The actual ops are the same as used for variable
2861 shifts. [OP][U][SIZE] */
2862 static GenOpFunc
*gen_neon_shift_im
[8][2][4] = {
2863 { /* 0 */ /* VSHR */
2866 gen_op_neon_shl_u16
,
2867 gen_op_neon_shl_u32
,
2871 gen_op_neon_shl_s16
,
2872 gen_op_neon_shl_s32
,
2875 }, { /* 1 */ /* VSRA */
2878 gen_op_neon_shl_u16
,
2879 gen_op_neon_shl_u32
,
2883 gen_op_neon_shl_s16
,
2884 gen_op_neon_shl_s32
,
2887 }, { /* 2 */ /* VRSHR */
2889 gen_op_neon_rshl_u8
,
2890 gen_op_neon_rshl_u16
,
2891 gen_op_neon_rshl_u32
,
2892 gen_op_neon_rshl_u64
2894 gen_op_neon_rshl_s8
,
2895 gen_op_neon_rshl_s16
,
2896 gen_op_neon_rshl_s32
,
2897 gen_op_neon_rshl_s64
2899 }, { /* 3 */ /* VRSRA */
2901 gen_op_neon_rshl_u8
,
2902 gen_op_neon_rshl_u16
,
2903 gen_op_neon_rshl_u32
,
2904 gen_op_neon_rshl_u64
2906 gen_op_neon_rshl_s8
,
2907 gen_op_neon_rshl_s16
,
2908 gen_op_neon_rshl_s32
,
2909 gen_op_neon_rshl_s64
2913 NULL
, NULL
, NULL
, NULL
2916 gen_op_neon_shl_u16
,
2917 gen_op_neon_shl_u32
,
2918 gen_op_neon_shl_u64
,
2923 gen_op_neon_shl_u16
,
2924 gen_op_neon_shl_u32
,
2925 gen_op_neon_shl_u64
,
2928 gen_op_neon_shl_u16
,
2929 gen_op_neon_shl_u32
,
2930 gen_op_neon_shl_u64
,
2932 }, { /* 6 */ /* VQSHL */
2934 gen_op_neon_qshl_u8
,
2935 gen_op_neon_qshl_u16
,
2936 gen_op_neon_qshl_u32
,
2937 gen_op_neon_qshl_u64
2939 gen_op_neon_qshl_s8
,
2940 gen_op_neon_qshl_s16
,
2941 gen_op_neon_qshl_s32
,
2942 gen_op_neon_qshl_s64
2944 }, { /* 7 */ /* VQSHLU */
2946 gen_op_neon_qshl_u8
,
2947 gen_op_neon_qshl_u16
,
2948 gen_op_neon_qshl_u32
,
2949 gen_op_neon_qshl_u64
2951 gen_op_neon_qshl_u8
,
2952 gen_op_neon_qshl_u16
,
2953 gen_op_neon_qshl_u32
,
2954 gen_op_neon_qshl_u64
2959 /* [R][U][size - 1] */
2960 static GenOpFunc
*gen_neon_shift_im_narrow
[2][2][3] = {
2963 gen_op_neon_shl_u16
,
2964 gen_op_neon_shl_u32
,
2967 gen_op_neon_shl_s16
,
2968 gen_op_neon_shl_s32
,
2973 gen_op_neon_rshl_u16
,
2974 gen_op_neon_rshl_u32
,
2975 gen_op_neon_rshl_u64
2977 gen_op_neon_rshl_s16
,
2978 gen_op_neon_rshl_s32
,
2979 gen_op_neon_rshl_s64
2985 gen_op_neon_narrow_u32 ()
2990 static GenOpFunc
*gen_neon_narrow
[3] = {
2991 gen_op_neon_narrow_u8
,
2992 gen_op_neon_narrow_u16
,
2993 gen_op_neon_narrow_u32
2996 static GenOpFunc
*gen_neon_narrow_satu
[3] = {
2997 gen_op_neon_narrow_sat_u8
,
2998 gen_op_neon_narrow_sat_u16
,
2999 gen_op_neon_narrow_sat_u32
3002 static GenOpFunc
*gen_neon_narrow_sats
[3] = {
3003 gen_op_neon_narrow_sat_s8
,
3004 gen_op_neon_narrow_sat_s16
,
3005 gen_op_neon_narrow_sat_s32
3008 static inline int gen_neon_add(int size
)
3011 case 0: gen_op_neon_add_u8(); break;
3012 case 1: gen_op_neon_add_u16(); break;
3013 case 2: gen_op_addl_T0_T1(); break;
3019 /* 32-bit pairwise ops end up the same as the elementsise versions. */
3020 #define gen_op_neon_pmax_s32 gen_op_neon_max_s32
3021 #define gen_op_neon_pmax_u32 gen_op_neon_max_u32
3022 #define gen_op_neon_pmin_s32 gen_op_neon_min_s32
3023 #define gen_op_neon_pmin_u32 gen_op_neon_min_u32
3025 #define GEN_NEON_INTEGER_OP(name) do { \
3026 switch ((size << 1) | u) { \
3027 case 0: gen_op_neon_##name##_s8(); break; \
3028 case 1: gen_op_neon_##name##_u8(); break; \
3029 case 2: gen_op_neon_##name##_s16(); break; \
3030 case 3: gen_op_neon_##name##_u16(); break; \
3031 case 4: gen_op_neon_##name##_s32(); break; \
3032 case 5: gen_op_neon_##name##_u32(); break; \
3033 default: return 1; \
3037 gen_neon_movl_scratch_T0(int scratch
)
3041 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3042 gen_op_neon_setreg_T0(offset
);
3046 gen_neon_movl_scratch_T1(int scratch
)
3050 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3051 gen_op_neon_setreg_T1(offset
);
3055 gen_neon_movl_T0_scratch(int scratch
)
3059 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3060 gen_op_neon_getreg_T0(offset
);
3064 gen_neon_movl_T1_scratch(int scratch
)
3068 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3069 gen_op_neon_getreg_T1(offset
);
3072 static inline void gen_op_neon_widen_u32(void)
3074 gen_op_movl_T1_im(0);
3077 static inline void gen_neon_get_scalar(int size
, int reg
)
3080 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3082 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3084 gen_op_neon_dup_low16();
3086 gen_op_neon_dup_high16();
3090 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3094 for (n
= 0; n
< q
+ 1; n
+= 2) {
3095 NEON_GET_REG(T0
, reg
, n
);
3096 NEON_GET_REG(T0
, reg
, n
+ n
);
3098 case 0: gen_op_neon_unzip_u8(); break;
3099 case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same. */
3100 case 2: /* no-op */; break;
3103 gen_neon_movl_scratch_T0(tmp
+ n
);
3104 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3112 } neon_ls_element_type
[11] = {
3126 /* Translate a NEON load/store element instruction. Return nonzero if the
3127 instruction is invalid. */
3128 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3143 if (!vfp_enabled(env
))
3145 VFP_DREG_D(rd
, insn
);
3146 rn
= (insn
>> 16) & 0xf;
3148 load
= (insn
& (1 << 21)) != 0;
3149 if ((insn
& (1 << 23)) == 0) {
3150 /* Load store all elements. */
3151 op
= (insn
>> 8) & 0xf;
3152 size
= (insn
>> 6) & 3;
3153 if (op
> 10 || size
== 3)
3155 nregs
= neon_ls_element_type
[op
].nregs
;
3156 interleave
= neon_ls_element_type
[op
].interleave
;
3157 gen_movl_T1_reg(s
, rn
);
3158 stride
= (1 << size
) * interleave
;
3159 for (reg
= 0; reg
< nregs
; reg
++) {
3160 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3161 gen_movl_T1_reg(s
, rn
);
3162 gen_op_addl_T1_im((1 << size
) * reg
);
3163 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3164 gen_movl_T1_reg(s
, rn
);
3165 gen_op_addl_T1_im(1 << size
);
3167 for (pass
= 0; pass
< 2; pass
++) {
3171 NEON_SET_REG(T0
, rd
, pass
);
3173 NEON_GET_REG(T0
, rd
, pass
);
3176 gen_op_addl_T1_im(stride
);
3177 } else if (size
== 1) {
3180 gen_op_addl_T1_im(stride
);
3181 gen_op_movl_T2_T0();
3183 gen_op_addl_T1_im(stride
);
3184 gen_op_neon_insert_elt(16, 0xffff);
3185 NEON_SET_REG(T2
, rd
, pass
);
3187 NEON_GET_REG(T2
, rd
, pass
);
3188 gen_op_movl_T0_T2();
3190 gen_op_addl_T1_im(stride
);
3191 gen_op_neon_extract_elt(16, 0xffff0000);
3193 gen_op_addl_T1_im(stride
);
3195 } else /* size == 0 */ {
3198 for (n
= 0; n
< 4; n
++) {
3200 gen_op_addl_T1_im(stride
);
3202 gen_op_movl_T2_T0();
3204 gen_op_neon_insert_elt(n
* 8, ~mask
);
3208 NEON_SET_REG(T2
, rd
, pass
);
3210 NEON_GET_REG(T2
, rd
, pass
);
3212 for (n
= 0; n
< 4; n
++) {
3214 gen_op_movl_T0_T2();
3216 gen_op_neon_extract_elt(n
* 8, mask
);
3219 gen_op_addl_T1_im(stride
);
3225 rd
+= neon_ls_element_type
[op
].spacing
;
3229 size
= (insn
>> 10) & 3;
3231 /* Load single element to all lanes. */
3234 size
= (insn
>> 6) & 3;
3235 nregs
= ((insn
>> 8) & 3) + 1;
3236 stride
= (insn
& (1 << 5)) ? 2 : 1;
3237 gen_movl_T1_reg(s
, rn
);
3238 for (reg
= 0; reg
< nregs
; reg
++) {
3242 gen_op_neon_dup_u8(0);
3246 gen_op_neon_dup_low16();
3254 gen_op_addl_T1_im(1 << size
);
3255 NEON_SET_REG(T0
, rd
, 0);
3256 NEON_SET_REG(T0
, rd
, 1);
3259 stride
= (1 << size
) * nregs
;
3261 /* Single element. */
3262 pass
= (insn
>> 7) & 1;
3265 shift
= ((insn
>> 5) & 3) * 8;
3266 mask
= 0xff << shift
;
3270 shift
= ((insn
>> 6) & 1) * 16;
3271 mask
= shift
? 0xffff0000 : 0xffff;
3272 stride
= (insn
& (1 << 5)) ? 2 : 1;
3277 stride
= (insn
& (1 << 6)) ? 2 : 1;
3282 nregs
= ((insn
>> 8) & 3) + 1;
3283 gen_movl_T1_reg(s
, rn
);
3284 for (reg
= 0; reg
< nregs
; reg
++) {
3287 NEON_GET_REG(T2
, rd
, pass
);
3298 NEON_SET_REG(T0
, rd
, pass
);
3302 gen_op_neon_insert_elt(shift
, ~mask
);
3303 NEON_SET_REG(T0
, rd
, pass
);
3305 } else { /* Store */
3307 NEON_GET_REG(T0
, rd
, pass
);
3309 NEON_GET_REG(T2
, rd
, pass
);
3310 gen_op_neon_extract_elt(shift
, mask
);
3325 gen_op_addl_T1_im(1 << size
);
3327 stride
= nregs
* (1 << size
);
3333 base
= load_reg(s
, rn
);
3335 tcg_gen_addi_i32(base
, base
, stride
);
3338 index
= load_reg(s
, rm
);
3339 tcg_gen_add_i32(base
, base
, index
);
3342 store_reg(s
, rn
, base
);
3347 /* Translate a NEON data processing instruction. Return nonzero if the
3348 instruction is invalid.
3349 In general we process vectors in 32-bit chunks. This means we can reuse
3350 some of the scalar ops, and hopefully the code generated for 32-bit
3351 hosts won't be too awful. The downside is that the few 64-bit operations
3352 (mainly shifts) get complicated. */
3354 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3368 if (!vfp_enabled(env
))
3370 q
= (insn
& (1 << 6)) != 0;
3371 u
= (insn
>> 24) & 1;
3372 VFP_DREG_D(rd
, insn
);
3373 VFP_DREG_N(rn
, insn
);
3374 VFP_DREG_M(rm
, insn
);
3375 size
= (insn
>> 20) & 3;
3376 if ((insn
& (1 << 23)) == 0) {
3377 /* Three register same length. */
3378 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
3379 if (size
== 3 && (op
== 1 || op
== 5 || op
== 16)) {
3380 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
3381 NEON_GET_REG(T0
, rm
, pass
* 2);
3382 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
3383 gen_neon_movl_scratch_T0(0);
3384 gen_neon_movl_scratch_T1(1);
3385 NEON_GET_REG(T0
, rn
, pass
* 2);
3386 NEON_GET_REG(T1
, rn
, pass
* 2 + 1);
3390 gen_op_neon_addl_saturate_u64();
3392 gen_op_neon_addl_saturate_s64();
3397 gen_op_neon_subl_saturate_u64();
3399 gen_op_neon_subl_saturate_s64();
3404 gen_op_neon_subl_u64();
3406 gen_op_neon_addl_u64();
3412 NEON_SET_REG(T0
, rd
, pass
* 2);
3413 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
3420 case 10: /* VRSHL */
3421 case 11: /* VQSHL */
3422 /* Shift operations have Rn and Rm reversed. */
3431 case 20: /* VPMAX */
3432 case 21: /* VPMIN */
3433 case 23: /* VPADD */
3436 case 26: /* VPADD (float) */
3437 pairwise
= (u
&& size
< 2);
3439 case 30: /* VPMIN/VPMAX (float) */
3446 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
3455 NEON_GET_REG(T0
, rn
, n
);
3456 NEON_GET_REG(T1
, rn
, n
+ 1);
3458 NEON_GET_REG(T0
, rm
, n
);
3459 NEON_GET_REG(T1
, rm
, n
+ 1);
3463 NEON_GET_REG(T0
, rn
, pass
);
3464 NEON_GET_REG(T1
, rm
, pass
);
3468 GEN_NEON_INTEGER_OP(hadd
);
3471 switch (size
<< 1| u
) {
3472 case 0: gen_op_neon_qadd_s8(); break;
3473 case 1: gen_op_neon_qadd_u8(); break;
3474 case 2: gen_op_neon_qadd_s16(); break;
3475 case 3: gen_op_neon_qadd_u16(); break;
3476 case 4: gen_op_addl_T0_T1_saturate(); break;
3477 case 5: gen_op_addl_T0_T1_usaturate(); break;
3481 case 2: /* VRHADD */
3482 GEN_NEON_INTEGER_OP(rhadd
);
3484 case 3: /* Logic ops. */
3485 switch ((u
<< 2) | size
) {
3487 gen_op_andl_T0_T1();
3490 gen_op_bicl_T0_T1();
3500 gen_op_xorl_T0_T1();
3503 NEON_GET_REG(T2
, rd
, pass
);
3507 NEON_GET_REG(T2
, rd
, pass
);
3511 NEON_GET_REG(T2
, rd
, pass
);
3517 GEN_NEON_INTEGER_OP(hsub
);
3520 switch ((size
<< 1) | u
) {
3521 case 0: gen_op_neon_qsub_s8(); break;
3522 case 1: gen_op_neon_qsub_u8(); break;
3523 case 2: gen_op_neon_qsub_s16(); break;
3524 case 3: gen_op_neon_qsub_u16(); break;
3525 case 4: gen_op_subl_T0_T1_saturate(); break;
3526 case 5: gen_op_subl_T0_T1_usaturate(); break;
3531 GEN_NEON_INTEGER_OP(cgt
);
3534 GEN_NEON_INTEGER_OP(cge
);
3537 switch ((size
<< 1) | u
) {
3538 case 0: gen_op_neon_shl_s8(); break;
3539 case 1: gen_op_neon_shl_u8(); break;
3540 case 2: gen_op_neon_shl_s16(); break;
3541 case 3: gen_op_neon_shl_u16(); break;
3542 case 4: gen_op_neon_shl_s32(); break;
3543 case 5: gen_op_neon_shl_u32(); break;
3545 /* ??? Implementing these is tricky because the vector ops work
3546 on 32-bit pieces. */
3547 case 6: gen_op_neon_shl_s64(); break;
3548 case 7: gen_op_neon_shl_u64(); break;
3550 case 6: case 7: cpu_abort(env
, "VSHL.64 not implemented");
3555 switch ((size
<< 1) | u
) {
3556 case 0: gen_op_neon_qshl_s8(); break;
3557 case 1: gen_op_neon_qshl_u8(); break;
3558 case 2: gen_op_neon_qshl_s16(); break;
3559 case 3: gen_op_neon_qshl_u16(); break;
3560 case 4: gen_op_neon_qshl_s32(); break;
3561 case 5: gen_op_neon_qshl_u32(); break;
3563 /* ??? Implementing these is tricky because the vector ops work
3564 on 32-bit pieces. */
3565 case 6: gen_op_neon_qshl_s64(); break;
3566 case 7: gen_op_neon_qshl_u64(); break;
3568 case 6: case 7: cpu_abort(env
, "VQSHL.64 not implemented");
3572 case 10: /* VRSHL */
3573 switch ((size
<< 1) | u
) {
3574 case 0: gen_op_neon_rshl_s8(); break;
3575 case 1: gen_op_neon_rshl_u8(); break;
3576 case 2: gen_op_neon_rshl_s16(); break;
3577 case 3: gen_op_neon_rshl_u16(); break;
3578 case 4: gen_op_neon_rshl_s32(); break;
3579 case 5: gen_op_neon_rshl_u32(); break;
3581 /* ??? Implementing these is tricky because the vector ops work
3582 on 32-bit pieces. */
3583 case 6: gen_op_neon_rshl_s64(); break;
3584 case 7: gen_op_neon_rshl_u64(); break;
3586 case 6: case 7: cpu_abort(env
, "VRSHL.64 not implemented");
3590 case 11: /* VQRSHL */
3591 switch ((size
<< 1) | u
) {
3592 case 0: gen_op_neon_qrshl_s8(); break;
3593 case 1: gen_op_neon_qrshl_u8(); break;
3594 case 2: gen_op_neon_qrshl_s16(); break;
3595 case 3: gen_op_neon_qrshl_u16(); break;
3596 case 4: gen_op_neon_qrshl_s32(); break;
3597 case 5: gen_op_neon_qrshl_u32(); break;
3599 /* ??? Implementing these is tricky because the vector ops work
3600 on 32-bit pieces. */
3601 case 6: gen_op_neon_qrshl_s64(); break;
3602 case 7: gen_op_neon_qrshl_u64(); break;
3604 case 6: case 7: cpu_abort(env
, "VQRSHL.64 not implemented");
3609 GEN_NEON_INTEGER_OP(max
);
3612 GEN_NEON_INTEGER_OP(min
);
3615 GEN_NEON_INTEGER_OP(abd
);
3618 GEN_NEON_INTEGER_OP(abd
);
3619 NEON_GET_REG(T1
, rd
, pass
);
3623 if (!u
) { /* VADD */
3624 if (gen_neon_add(size
))
3628 case 0: gen_op_neon_sub_u8(); break;
3629 case 1: gen_op_neon_sub_u16(); break;
3630 case 2: gen_op_subl_T0_T1(); break;
3636 if (!u
) { /* VTST */
3638 case 0: gen_op_neon_tst_u8(); break;
3639 case 1: gen_op_neon_tst_u16(); break;
3640 case 2: gen_op_neon_tst_u32(); break;
3645 case 0: gen_op_neon_ceq_u8(); break;
3646 case 1: gen_op_neon_ceq_u16(); break;
3647 case 2: gen_op_neon_ceq_u32(); break;
3652 case 18: /* Multiply. */
3654 case 0: gen_op_neon_mul_u8(); break;
3655 case 1: gen_op_neon_mul_u16(); break;
3656 case 2: gen_op_mul_T0_T1(); break;
3659 NEON_GET_REG(T1
, rd
, pass
);
3662 case 0: gen_op_neon_rsb_u8(); break;
3663 case 1: gen_op_neon_rsb_u16(); break;
3664 case 2: gen_op_rsbl_T0_T1(); break;
3672 if (u
) { /* polynomial */
3673 gen_op_neon_mul_p8();
3674 } else { /* Integer */
3676 case 0: gen_op_neon_mul_u8(); break;
3677 case 1: gen_op_neon_mul_u16(); break;
3678 case 2: gen_op_mul_T0_T1(); break;
3683 case 20: /* VPMAX */
3684 GEN_NEON_INTEGER_OP(pmax
);
3686 case 21: /* VPMIN */
3687 GEN_NEON_INTEGER_OP(pmin
);
3689 case 22: /* Hultiply high. */
3690 if (!u
) { /* VQDMULH */
3692 case 1: gen_op_neon_qdmulh_s16(); break;
3693 case 2: gen_op_neon_qdmulh_s32(); break;
3696 } else { /* VQRDHMUL */
3698 case 1: gen_op_neon_qrdmulh_s16(); break;
3699 case 2: gen_op_neon_qrdmulh_s32(); break;
3704 case 23: /* VPADD */
3708 case 0: gen_op_neon_padd_u8(); break;
3709 case 1: gen_op_neon_padd_u16(); break;
3710 case 2: gen_op_addl_T0_T1(); break;
3714 case 26: /* Floating point arithnetic. */
3715 switch ((u
<< 2) | size
) {
3717 gen_op_neon_add_f32();
3720 gen_op_neon_sub_f32();
3723 gen_op_neon_add_f32();
3726 gen_op_neon_abd_f32();
3732 case 27: /* Float multiply. */
3733 gen_op_neon_mul_f32();
3735 NEON_GET_REG(T1
, rd
, pass
);
3737 gen_op_neon_add_f32();
3739 gen_op_neon_rsb_f32();
3743 case 28: /* Float compare. */
3745 gen_op_neon_ceq_f32();
3748 gen_op_neon_cge_f32();
3750 gen_op_neon_cgt_f32();
3753 case 29: /* Float compare absolute. */
3757 gen_op_neon_acge_f32();
3759 gen_op_neon_acgt_f32();
3761 case 30: /* Float min/max. */
3763 gen_op_neon_max_f32();
3765 gen_op_neon_min_f32();
3769 gen_op_neon_recps_f32();
3771 gen_op_neon_rsqrts_f32();
3776 /* Save the result. For elementwise operations we can put it
3777 straight into the destination register. For pairwise operations
3778 we have to be careful to avoid clobbering the source operands. */
3779 if (pairwise
&& rd
== rm
) {
3780 gen_neon_movl_scratch_T0(pass
);
3782 NEON_SET_REG(T0
, rd
, pass
);
3786 if (pairwise
&& rd
== rm
) {
3787 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
3788 gen_neon_movl_T0_scratch(pass
);
3789 NEON_SET_REG(T0
, rd
, pass
);
3792 } else if (insn
& (1 << 4)) {
3793 if ((insn
& 0x00380080) != 0) {
3794 /* Two registers and shift. */
3795 op
= (insn
>> 8) & 0xf;
3796 if (insn
& (1 << 7)) {
3801 while ((insn
& (1 << (size
+ 19))) == 0)
3804 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
3805 /* To avoid excessive dumplication of ops we implement shift
3806 by immediate using the variable shift operations. */
3808 /* Shift by immediate:
3809 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
3810 /* Right shifts are encoded as N - shift, where N is the
3811 element size in bits. */
3813 shift
= shift
- (1 << (size
+ 3));
3823 imm
= (uint8_t) shift
;
3828 imm
= (uint16_t) shift
;
3839 for (pass
= 0; pass
< count
; pass
++) {
3841 /* Operands in T0 and T1. */
3842 gen_op_movl_T1_im(imm
);
3843 NEON_GET_REG(T0
, rm
, pass
);
3845 /* Operands in {T0, T1} and env->vfp.scratch. */
3846 gen_op_movl_T0_im(imm
);
3847 gen_neon_movl_scratch_T0(0);
3848 gen_op_movl_T0_im((int32_t)imm
>> 31);
3849 gen_neon_movl_scratch_T0(1);
3850 NEON_GET_REG(T0
, rm
, pass
* 2);
3851 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
3854 if (gen_neon_shift_im
[op
][u
][size
] == NULL
)
3856 gen_neon_shift_im
[op
][u
][size
]();
3858 if (op
== 1 || op
== 3) {
3861 gen_neon_movl_scratch_T0(0);
3862 gen_neon_movl_scratch_T1(1);
3863 NEON_GET_REG(T0
, rd
, pass
* 2);
3864 NEON_GET_REG(T1
, rd
, pass
* 2 + 1);
3865 gen_op_neon_addl_u64();
3867 NEON_GET_REG(T1
, rd
, pass
);
3870 } else if (op
== 4 || (op
== 5 && u
)) {
3873 cpu_abort(env
, "VS[LR]I.64 not implemented");
3878 imm
= 0xff >> -shift
;
3880 imm
= (uint8_t)(0xff << shift
);
3886 imm
= 0xffff >> -shift
;
3888 imm
= (uint16_t)(0xffff << shift
);
3893 imm
= 0xffffffffu
>> -shift
;
3895 imm
= 0xffffffffu
<< shift
;
3900 NEON_GET_REG(T1
, rd
, pass
);
3901 gen_op_movl_T2_im(imm
);
3905 NEON_SET_REG(T0
, rd
, pass
* 2);
3906 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
3908 NEON_SET_REG(T0
, rd
, pass
);
3911 } else if (op
< 10) {
3912 /* Shift by immedaiate and narrow:
3913 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
3914 shift
= shift
- (1 << (size
+ 3));
3923 imm
= (uint16_t) shift
;
3934 /* Processing MSB first means we need to do less shuffling at
3936 for (pass
= count
- 1; pass
>= 0; pass
--) {
3937 /* Avoid clobbering the second operand before it has been
3946 /* Operands in T0 and T1. */
3947 gen_op_movl_T1_im(imm
);
3948 NEON_GET_REG(T0
, rm
, n
);
3950 /* Operands in {T0, T1} and env->vfp.scratch. */
3951 gen_op_movl_T0_im(imm
);
3952 gen_neon_movl_scratch_T0(0);
3953 gen_op_movl_T0_im((int32_t)imm
>> 31);
3954 gen_neon_movl_scratch_T0(1);
3955 NEON_GET_REG(T0
, rm
, n
* 2);
3956 NEON_GET_REG(T0
, rm
, n
* 2 + 1);
3959 gen_neon_shift_im_narrow
[q
][u
][size
- 1]();
3961 if (size
< 3 && (pass
& 1) == 0) {
3962 gen_neon_movl_scratch_T0(0);
3967 gen_neon_movl_T1_scratch(0);
3969 if (op
== 8 && !u
) {
3970 gen_neon_narrow
[size
- 1]();
3973 gen_neon_narrow_sats
[size
- 2]();
3975 gen_neon_narrow_satu
[size
- 1]();
3978 offset
= neon_reg_offset(rd
, n
);
3980 offset
= neon_reg_offset(rd
, n
>> 1);
3981 gen_op_neon_setreg_T0(offset
);
3984 } else if (op
== 10) {
3988 for (pass
= 0; pass
< 2; pass
++) {
3989 /* Avoid clobbering the input operand. */
3995 NEON_GET_REG(T0
, rm
, n
);
3996 GEN_NEON_INTEGER_OP(widen
);
3998 /* The shift is less than the width of the source
3999 type, so in some cases we can just
4000 shift the whole register. */
4001 if (size
== 1 || (size
== 0 && u
)) {
4002 gen_op_shll_T0_im(shift
);
4003 gen_op_shll_T1_im(shift
);
4006 case 0: gen_op_neon_shll_u16(shift
); break;
4007 case 2: gen_op_neon_shll_u64(shift
); break;
4012 NEON_SET_REG(T0
, rd
, n
* 2);
4013 NEON_SET_REG(T1
, rd
, n
* 2 + 1);
4015 } else if (op
== 15 || op
== 16) {
4016 /* VCVT fixed-point. */
4017 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4018 gen_op_vfp_getreg_F0s(neon_reg_offset(rm
, pass
));
4021 gen_op_vfp_ultos(shift
);
4023 gen_op_vfp_sltos(shift
);
4026 gen_op_vfp_touls(shift
);
4028 gen_op_vfp_tosls(shift
);
4030 gen_op_vfp_setreg_F0s(neon_reg_offset(rd
, pass
));
4035 } else { /* (insn & 0x00380080) == 0 */
4038 op
= (insn
>> 8) & 0xf;
4039 /* One register and immediate. */
4040 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4041 invert
= (insn
& (1 << 5)) != 0;
4059 imm
= (imm
<< 8) | (imm
<< 24);
4062 imm
= (imm
< 8) | 0xff;
4065 imm
= (imm
<< 16) | 0xffff;
4068 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4073 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4074 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4080 if (op
!= 14 || !invert
)
4081 gen_op_movl_T1_im(imm
);
4083 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4084 if (op
& 1 && op
< 12) {
4085 NEON_GET_REG(T0
, rd
, pass
);
4087 /* The immediate value has already been inverted, so
4089 gen_op_andl_T0_T1();
4093 NEON_SET_REG(T0
, rd
, pass
);
4095 if (op
== 14 && invert
) {
4098 for (n
= 0; n
< 4; n
++) {
4099 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4100 tmp
|= 0xff << (n
* 8);
4102 gen_op_movl_T1_im(tmp
);
4105 NEON_SET_REG(T1
, rd
, pass
);
4109 } else { /* (insn & 0x00800010 == 0x00800010) */
4111 op
= (insn
>> 8) & 0xf;
4112 if ((insn
& (1 << 6)) == 0) {
4113 /* Three registers of different lengths. */
4117 /* prewiden, src1_wide, src2_wide */
4118 static const int neon_3reg_wide
[16][3] = {
4119 {1, 0, 0}, /* VADDL */
4120 {1, 1, 0}, /* VADDW */
4121 {1, 0, 0}, /* VSUBL */
4122 {1, 1, 0}, /* VSUBW */
4123 {0, 1, 1}, /* VADDHN */
4124 {0, 0, 0}, /* VABAL */
4125 {0, 1, 1}, /* VSUBHN */
4126 {0, 0, 0}, /* VABDL */
4127 {0, 0, 0}, /* VMLAL */
4128 {0, 0, 0}, /* VQDMLAL */
4129 {0, 0, 0}, /* VMLSL */
4130 {0, 0, 0}, /* VQDMLSL */
4131 {0, 0, 0}, /* Integer VMULL */
4132 {0, 0, 0}, /* VQDMULL */
4133 {0, 0, 0} /* Polynomial VMULL */
4136 prewiden
= neon_3reg_wide
[op
][0];
4137 src1_wide
= neon_3reg_wide
[op
][1];
4138 src2_wide
= neon_3reg_wide
[op
][2];
4140 /* Avoid overlapping operands. Wide source operands are
4141 always aligned so will never overlap with wide
4142 destinations in problematic ways. */
4144 NEON_GET_REG(T2
, rm
, 1);
4145 } else if (rd
== rn
) {
4146 NEON_GET_REG(T2
, rn
, 1);
4148 for (pass
= 0; pass
< 2; pass
++) {
4149 /* Load the second operand into env->vfp.scratch.
4150 Also widen narrow operands. */
4151 if (pass
== 1 && rd
== rm
) {
4153 gen_op_movl_T0_T2();
4155 gen_op_movl_T1_T2();
4159 NEON_GET_REG(T0
, rm
, pass
* 2);
4160 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
4163 NEON_GET_REG(T0
, rm
, pass
);
4165 NEON_GET_REG(T1
, rm
, pass
);
4169 if (prewiden
&& !src2_wide
) {
4170 GEN_NEON_INTEGER_OP(widen
);
4172 if (prewiden
|| src2_wide
) {
4173 gen_neon_movl_scratch_T0(0);
4174 gen_neon_movl_scratch_T1(1);
4177 /* Load the first operand. */
4178 if (pass
== 1 && rd
== rn
) {
4179 gen_op_movl_T0_T2();
4182 NEON_GET_REG(T0
, rn
, pass
* 2);
4183 NEON_GET_REG(T1
, rn
, pass
* 2 + 1);
4185 NEON_GET_REG(T0
, rn
, pass
);
4188 if (prewiden
&& !src1_wide
) {
4189 GEN_NEON_INTEGER_OP(widen
);
4192 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4194 case 0: gen_op_neon_addl_u16(); break;
4195 case 1: gen_op_neon_addl_u32(); break;
4196 case 2: gen_op_neon_addl_u64(); break;
4200 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4202 case 0: gen_op_neon_subl_u16(); break;
4203 case 1: gen_op_neon_subl_u32(); break;
4204 case 2: gen_op_neon_subl_u64(); break;
4208 case 5: case 7: /* VABAL, VABDL */
4209 switch ((size
<< 1) | u
) {
4210 case 0: gen_op_neon_abdl_s16(); break;
4211 case 1: gen_op_neon_abdl_u16(); break;
4212 case 2: gen_op_neon_abdl_s32(); break;
4213 case 3: gen_op_neon_abdl_u32(); break;
4214 case 4: gen_op_neon_abdl_s64(); break;
4215 case 5: gen_op_neon_abdl_u64(); break;
4219 case 8: case 9: case 10: case 11: case 12: case 13:
4220 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4221 switch ((size
<< 1) | u
) {
4222 case 0: gen_op_neon_mull_s8(); break;
4223 case 1: gen_op_neon_mull_u8(); break;
4224 case 2: gen_op_neon_mull_s16(); break;
4225 case 3: gen_op_neon_mull_u16(); break;
4226 case 4: gen_op_imull_T0_T1(); break;
4227 case 5: gen_op_mull_T0_T1(); break;
4231 case 14: /* Polynomial VMULL */
4232 cpu_abort(env
, "Polynomial VMULL not implemented");
4234 default: /* 15 is RESERVED. */
4237 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4239 if (op
== 10 || op
== 11) {
4241 case 0: gen_op_neon_negl_u16(); break;
4242 case 1: gen_op_neon_negl_u32(); break;
4243 case 2: gen_op_neon_negl_u64(); break;
4248 gen_neon_movl_scratch_T0(0);
4249 gen_neon_movl_scratch_T1(1);
4252 NEON_GET_REG(T0
, rd
, pass
* 2);
4253 NEON_GET_REG(T1
, rd
, pass
* 2 + 1);
4257 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4259 case 0: gen_op_neon_addl_u16(); break;
4260 case 1: gen_op_neon_addl_u32(); break;
4261 case 2: gen_op_neon_addl_u64(); break;
4265 case 9: case 11: /* VQDMLAL, VQDMLSL */
4267 case 1: gen_op_neon_addl_saturate_s32(); break;
4268 case 2: gen_op_neon_addl_saturate_s64(); break;
4272 case 13: /* VQDMULL */
4274 case 1: gen_op_neon_addl_saturate_s32(); break;
4275 case 2: gen_op_neon_addl_saturate_s64(); break;
4282 NEON_SET_REG(T0
, rd
, pass
* 2);
4283 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
4284 } else if (op
== 4 || op
== 6) {
4285 /* Narrowing operation. */
4288 case 0: gen_op_neon_narrow_high_u8(); break;
4289 case 1: gen_op_neon_narrow_high_u16(); break;
4290 case 2: gen_op_movl_T0_T1(); break;
4295 case 0: gen_op_neon_narrow_high_round_u8(); break;
4296 case 1: gen_op_neon_narrow_high_round_u16(); break;
4297 case 2: gen_op_neon_narrow_high_round_u32(); break;
4301 NEON_SET_REG(T0
, rd
, pass
);
4303 /* Write back the result. */
4304 NEON_SET_REG(T0
, rd
, pass
* 2);
4305 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
4309 /* Two registers and a scalar. */
4311 case 0: /* Integer VMLA scalar */
4312 case 1: /* Float VMLA scalar */
4313 case 4: /* Integer VMLS scalar */
4314 case 5: /* Floating point VMLS scalar */
4315 case 8: /* Integer VMUL scalar */
4316 case 9: /* Floating point VMUL scalar */
4317 case 12: /* VQDMULH scalar */
4318 case 13: /* VQRDMULH scalar */
4319 gen_neon_get_scalar(size
, rm
);
4320 gen_op_movl_T2_T0();
4321 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
4323 gen_op_movl_T0_T2();
4324 NEON_GET_REG(T1
, rn
, pass
);
4327 gen_op_neon_qdmulh_s16();
4329 gen_op_neon_qdmulh_s32();
4331 } else if (op
== 13) {
4333 gen_op_neon_qrdmulh_s16();
4335 gen_op_neon_qrdmulh_s32();
4337 } else if (op
& 1) {
4338 gen_op_neon_mul_f32();
4341 case 0: gen_op_neon_mul_u8(); break;
4342 case 1: gen_op_neon_mul_u16(); break;
4343 case 2: gen_op_mul_T0_T1(); break;
4349 NEON_GET_REG(T1
, rd
, pass
);
4355 gen_op_neon_add_f32();
4359 case 0: gen_op_neon_rsb_u8(); break;
4360 case 1: gen_op_neon_rsb_u16(); break;
4361 case 2: gen_op_rsbl_T0_T1(); break;
4366 gen_op_neon_rsb_f32();
4372 NEON_SET_REG(T0
, rd
, pass
);
4375 case 2: /* VMLAL sclar */
4376 case 3: /* VQDMLAL scalar */
4377 case 6: /* VMLSL scalar */
4378 case 7: /* VQDMLSL scalar */
4379 case 10: /* VMULL scalar */
4380 case 11: /* VQDMULL scalar */
4382 /* Save overlapping operands before they are
4384 NEON_GET_REG(T0
, rn
, 1);
4385 gen_neon_movl_scratch_T0(2);
4387 gen_neon_get_scalar(size
, rm
);
4388 gen_op_movl_T2_T0();
4389 for (pass
= 0; pass
< 2; pass
++) {
4391 gen_op_movl_T0_T2();
4393 if (pass
!= 0 && rd
== rn
) {
4394 gen_neon_movl_T1_scratch(2);
4396 NEON_GET_REG(T1
, rn
, pass
);
4398 switch ((size
<< 1) | u
) {
4399 case 0: gen_op_neon_mull_s8(); break;
4400 case 1: gen_op_neon_mull_u8(); break;
4401 case 2: gen_op_neon_mull_s16(); break;
4402 case 3: gen_op_neon_mull_u16(); break;
4403 case 4: gen_op_imull_T0_T1(); break;
4404 case 5: gen_op_mull_T0_T1(); break;
4407 if (op
== 6 || op
== 7) {
4409 case 0: gen_op_neon_negl_u16(); break;
4410 case 1: gen_op_neon_negl_u32(); break;
4411 case 2: gen_op_neon_negl_u64(); break;
4415 gen_neon_movl_scratch_T0(0);
4416 gen_neon_movl_scratch_T1(1);
4417 NEON_GET_REG(T0
, rd
, pass
* 2);
4418 NEON_GET_REG(T1
, rd
, pass
* 2 + 1);
4422 case 0: gen_op_neon_addl_u16(); break;
4423 case 1: gen_op_neon_addl_u32(); break;
4424 case 2: gen_op_neon_addl_u64(); break;
4431 gen_op_neon_addl_saturate_s32();
4432 gen_op_neon_addl_saturate_s32();
4435 gen_op_neon_addl_saturate_s64();
4436 gen_op_neon_addl_saturate_s64();
4446 case 1: gen_op_neon_addl_saturate_s32(); break;
4447 case 2: gen_op_neon_addl_saturate_s64(); break;
4454 NEON_SET_REG(T0
, rd
, pass
* 2);
4455 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
4458 default: /* 14 and 15 are RESERVED */
4462 } else { /* size == 3 */
4466 imm
= (insn
>> 8) & 0xf;
4470 NEON_GET_REG(T0
, reg
, n
);
4471 for (pass
= 0; pass
< count
; pass
++) {
4478 NEON_GET_REG(T1
, reg
, n
);
4479 gen_op_neon_extract((insn
<< 3) & 0x1f);
4481 /* ??? This is broken if rd and rm overlap */
4482 NEON_SET_REG(T0
, rd
, pass
);
4484 gen_op_movl_T0_T1();
4486 NEON_GET_REG(T0
, reg
, n
);
4489 } else if ((insn
& (1 << 11)) == 0) {
4490 /* Two register misc. */
4491 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
4492 size
= (insn
>> 18) & 3;
4494 case 0: /* VREV64 */
4497 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4498 NEON_GET_REG(T0
, rm
, pass
* 2);
4499 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
4501 case 0: gen_op_rev_T0(); break;
4502 case 1: gen_swap_half(cpu_T
[0]); break;
4503 case 2: /* no-op */ break;
4506 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
4508 NEON_SET_REG(T1
, rd
, pass
* 2);
4510 gen_op_movl_T0_T1();
4512 case 0: gen_op_rev_T0(); break;
4513 case 1: gen_swap_half(cpu_T
[0]); break;
4516 NEON_SET_REG(T0
, rd
, pass
* 2);
4520 case 4: case 5: /* VPADDL */
4521 case 12: case 13: /* VPADAL */
4526 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4527 NEON_GET_REG(T0
, rm
, pass
* 2);
4528 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
4530 gen_op_neon_paddl_u32();
4532 gen_op_neon_paddl_s32();
4535 gen_neon_movl_scratch_T0(0);
4536 gen_neon_movl_scratch_T1(1);
4538 NEON_GET_REG(T0
, rd
, pass
* 2);
4539 NEON_GET_REG(T1
, rd
, pass
* 2 + 1);
4540 gen_op_neon_addl_u64();
4542 NEON_SET_REG(T0
, rd
, pass
* 2);
4543 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
4548 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
4549 NEON_GET_REG(T0
, rm
, n
);
4550 NEON_GET_REG(T1
, rd
, n
+ 1);
4551 NEON_SET_REG(T1
, rm
, n
);
4552 NEON_SET_REG(T0
, rd
, n
+ 1);
4560 Rd A3 A2 A1 A0 B2 B0 A2 A0
4561 Rm B3 B2 B1 B0 B3 B1 A3 A1
4565 gen_neon_unzip(rd
, q
, 0, size
);
4566 gen_neon_unzip(rm
, q
, 4, size
);
4568 static int unzip_order_q
[8] =
4569 {0, 2, 4, 6, 1, 3, 5, 7};
4570 for (n
= 0; n
< 8; n
++) {
4571 int reg
= (n
< 4) ? rd
: rm
;
4572 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
4573 NEON_SET_REG(T0
, reg
, n
% 4);
4576 static int unzip_order
[4] =
4578 for (n
= 0; n
< 4; n
++) {
4579 int reg
= (n
< 2) ? rd
: rm
;
4580 gen_neon_movl_T0_scratch(unzip_order
[n
]);
4581 NEON_SET_REG(T0
, reg
, n
% 2);
4587 Rd A3 A2 A1 A0 B1 A1 B0 A0
4588 Rm B3 B2 B1 B0 B3 A3 B2 A2
4592 count
= (q
? 4 : 2);
4593 for (n
= 0; n
< count
; n
++) {
4594 NEON_GET_REG(T0
, rd
, n
);
4595 NEON_GET_REG(T1
, rd
, n
);
4597 case 0: gen_op_neon_zip_u8(); break;
4598 case 1: gen_op_neon_zip_u16(); break;
4599 case 2: /* no-op */; break;
4602 gen_neon_movl_scratch_T0(n
* 2);
4603 gen_neon_movl_scratch_T1(n
* 2 + 1);
4605 for (n
= 0; n
< count
* 2; n
++) {
4606 int reg
= (n
< count
) ? rd
: rm
;
4607 gen_neon_movl_T0_scratch(n
);
4608 NEON_SET_REG(T0
, reg
, n
% count
);
4611 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4612 for (pass
= 0; pass
< 2; pass
++) {
4618 NEON_GET_REG(T0
, rm
, n
* 2);
4619 NEON_GET_REG(T1
, rm
, n
* 2 + 1);
4620 if (op
== 36 && q
== 0) {
4622 case 0: gen_op_neon_narrow_u8(); break;
4623 case 1: gen_op_neon_narrow_u16(); break;
4624 case 2: /* no-op */ break;
4629 case 0: gen_op_neon_narrow_sat_u8(); break;
4630 case 1: gen_op_neon_narrow_sat_u16(); break;
4631 case 2: gen_op_neon_narrow_sat_u32(); break;
4636 case 0: gen_op_neon_narrow_sat_s8(); break;
4637 case 1: gen_op_neon_narrow_sat_s16(); break;
4638 case 2: gen_op_neon_narrow_sat_s32(); break;
4642 NEON_SET_REG(T0
, rd
, n
);
4645 case 38: /* VSHLL */
4649 NEON_GET_REG(T2
, rm
, 1);
4651 for (pass
= 0; pass
< 2; pass
++) {
4652 if (pass
== 1 && rm
== rd
) {
4653 gen_op_movl_T0_T2();
4655 NEON_GET_REG(T0
, rm
, pass
);
4658 case 0: gen_op_neon_widen_high_u8(); break;
4659 case 1: gen_op_neon_widen_high_u16(); break;
4661 gen_op_movl_T1_T0();
4662 gen_op_movl_T0_im(0);
4666 NEON_SET_REG(T0
, rd
, pass
* 2);
4667 NEON_SET_REG(T1
, rd
, pass
* 2 + 1);
4672 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4673 if (op
== 30 || op
== 31 || op
>= 58) {
4674 gen_op_vfp_getreg_F0s(neon_reg_offset(rm
, pass
));
4676 NEON_GET_REG(T0
, rm
, pass
);
4679 case 1: /* VREV32 */
4681 case 0: gen_op_rev_T0(); break;
4682 case 1: gen_swap_half(cpu_T
[0]); break;
4686 case 2: /* VREV16 */
4689 gen_rev16(cpu_T
[0]);
4691 case 4: case 5: /* VPADDL */
4692 case 12: case 13: /* VPADAL */
4693 switch ((size
<< 1) | (op
& 1)) {
4694 case 0: gen_op_neon_paddl_s8(); break;
4695 case 1: gen_op_neon_paddl_u8(); break;
4696 case 2: gen_op_neon_paddl_s16(); break;
4697 case 3: gen_op_neon_paddl_u16(); break;
4702 NEON_GET_REG(T1
, rd
, pass
);
4704 case 0: gen_op_neon_add_u16(); break;
4705 case 1: gen_op_addl_T0_T1(); break;
4712 case 0: gen_op_neon_cls_s8(); break;
4713 case 1: gen_op_neon_cls_s16(); break;
4714 case 2: gen_op_neon_cls_s32(); break;
4720 case 0: gen_op_neon_clz_u8(); break;
4721 case 1: gen_op_neon_clz_u16(); break;
4722 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
4729 gen_op_neon_cnt_u8();
4736 case 14: /* VQABS */
4738 case 0: gen_op_neon_qabs_s8(); break;
4739 case 1: gen_op_neon_qabs_s16(); break;
4740 case 2: gen_op_neon_qabs_s32(); break;
4744 case 15: /* VQNEG */
4746 case 0: gen_op_neon_qneg_s8(); break;
4747 case 1: gen_op_neon_qneg_s16(); break;
4748 case 2: gen_op_neon_qneg_s32(); break;
4752 case 16: case 19: /* VCGT #0, VCLE #0 */
4753 gen_op_movl_T1_im(0);
4755 case 0: gen_op_neon_cgt_s8(); break;
4756 case 1: gen_op_neon_cgt_s16(); break;
4757 case 2: gen_op_neon_cgt_s32(); break;
4763 case 17: case 20: /* VCGE #0, VCLT #0 */
4764 gen_op_movl_T1_im(0);
4766 case 0: gen_op_neon_cge_s8(); break;
4767 case 1: gen_op_neon_cge_s16(); break;
4768 case 2: gen_op_neon_cge_s32(); break;
4774 case 18: /* VCEQ #0 */
4775 gen_op_movl_T1_im(0);
4777 case 0: gen_op_neon_ceq_u8(); break;
4778 case 1: gen_op_neon_ceq_u16(); break;
4779 case 2: gen_op_neon_ceq_u32(); break;
4785 case 0: gen_op_neon_abs_s8(); break;
4786 case 1: gen_op_neon_abs_s16(); break;
4787 case 2: gen_op_neon_abs_s32(); break;
4792 gen_op_movl_T1_im(0);
4794 case 0: gen_op_neon_rsb_u8(); break;
4795 case 1: gen_op_neon_rsb_u16(); break;
4796 case 2: gen_op_rsbl_T0_T1(); break;
4800 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4801 gen_op_movl_T1_im(0);
4802 gen_op_neon_cgt_f32();
4806 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4807 gen_op_movl_T1_im(0);
4808 gen_op_neon_cge_f32();
4812 case 26: /* Float VCEQ #0 */
4813 gen_op_movl_T1_im(0);
4814 gen_op_neon_ceq_f32();
4816 case 30: /* Float VABS */
4819 case 31: /* Float VNEG */
4823 NEON_GET_REG(T1
, rd
, pass
);
4824 NEON_SET_REG(T1
, rm
, pass
);
4827 NEON_GET_REG(T1
, rd
, pass
);
4829 case 0: gen_op_neon_trn_u8(); break;
4830 case 1: gen_op_neon_trn_u16(); break;
4834 NEON_SET_REG(T1
, rm
, pass
);
4836 case 56: /* Integer VRECPE */
4837 gen_op_neon_recpe_u32();
4839 case 57: /* Integer VRSQRTE */
4840 gen_op_neon_rsqrte_u32();
4842 case 58: /* Float VRECPE */
4843 gen_op_neon_recpe_f32();
4845 case 59: /* Float VRSQRTE */
4846 gen_op_neon_rsqrte_f32();
4848 case 60: /* VCVT.F32.S32 */
4849 gen_op_vfp_tosizs();
4851 case 61: /* VCVT.F32.U32 */
4852 gen_op_vfp_touizs();
4854 case 62: /* VCVT.S32.F32 */
4857 case 63: /* VCVT.U32.F32 */
4861 /* Reserved: 21, 29, 39-56 */
4864 if (op
== 30 || op
== 31 || op
>= 58) {
4865 gen_op_vfp_setreg_F0s(neon_reg_offset(rm
, pass
));
4867 NEON_SET_REG(T0
, rd
, pass
);
4872 } else if ((insn
& (1 << 10)) == 0) {
4874 n
= (insn
>> 5) & 0x18;
4875 NEON_GET_REG(T1
, rm
, 0);
4876 if (insn
& (1 << 6)) {
4877 NEON_GET_REG(T0
, rd
, 0);
4879 gen_op_movl_T0_im(0);
4881 gen_op_neon_tbl(rn
, n
);
4882 gen_op_movl_T2_T0();
4883 NEON_GET_REG(T1
, rm
, 1);
4884 if (insn
& (1 << 6)) {
4885 NEON_GET_REG(T0
, rd
, 0);
4887 gen_op_movl_T0_im(0);
4889 gen_op_neon_tbl(rn
, n
);
4890 NEON_SET_REG(T2
, rd
, 0);
4891 NEON_SET_REG(T0
, rd
, 1);
4892 } else if ((insn
& 0x380) == 0) {
4894 if (insn
& (1 << 19)) {
4895 NEON_SET_REG(T0
, rm
, 1);
4897 NEON_SET_REG(T0
, rm
, 0);
4899 if (insn
& (1 << 16)) {
4900 gen_op_neon_dup_u8(((insn
>> 17) & 3) * 8);
4901 } else if (insn
& (1 << 17)) {
4902 if ((insn
>> 18) & 1)
4903 gen_op_neon_dup_high16();
4905 gen_op_neon_dup_low16();
4907 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4908 NEON_SET_REG(T0
, rd
, pass
);
4918 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4922 cpnum
= (insn
>> 8) & 0xf;
4923 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
4924 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
4930 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
4931 return disas_iwmmxt_insn(env
, s
, insn
);
4932 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
4933 return disas_dsp_insn(env
, s
, insn
);
4938 return disas_vfp_insn (env
, s
, insn
);
4940 return disas_cp15_insn (env
, s
, insn
);
4942 /* Unknown coprocessor. See if the board has hooked it. */
4943 return disas_cp_insn (env
, s
, insn
);
4947 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
4949 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
4954 insn
= ldl_code(s
->pc
);
4957 /* M variants do not implement ARM mode. */
4962 /* Unconditional instructions. */
4963 if (((insn
>> 25) & 7) == 1) {
4964 /* NEON Data processing. */
4965 if (!arm_feature(env
, ARM_FEATURE_NEON
))
4968 if (disas_neon_data_insn(env
, s
, insn
))
4972 if ((insn
& 0x0f100000) == 0x04000000) {
4973 /* NEON load/store. */
4974 if (!arm_feature(env
, ARM_FEATURE_NEON
))
4977 if (disas_neon_ls_insn(env
, s
, insn
))
4981 if ((insn
& 0x0d70f000) == 0x0550f000)
4983 else if ((insn
& 0x0ffffdff) == 0x01010000) {
4986 if (insn
& (1 << 9)) {
4987 /* BE8 mode not implemented. */
4991 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
4992 switch ((insn
>> 4) & 0xf) {
5001 /* We don't emulate caches so these are a no-op. */
5006 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5012 op1
= (insn
& 0x1f);
5013 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5014 gen_movl_T1_reg(s
, 13);
5016 gen_op_movl_T1_r13_banked(op1
);
5018 i
= (insn
>> 23) & 3;
5020 case 0: offset
= -4; break; /* DA */
5021 case 1: offset
= -8; break; /* DB */
5022 case 2: offset
= 0; break; /* IA */
5023 case 3: offset
= 4; break; /* IB */
5027 gen_op_addl_T1_im(offset
);
5028 gen_movl_T0_reg(s
, 14);
5030 gen_op_movl_T0_cpsr();
5031 gen_op_addl_T1_im(4);
5033 if (insn
& (1 << 21)) {
5034 /* Base writeback. */
5036 case 0: offset
= -8; break;
5037 case 1: offset
= -4; break;
5038 case 2: offset
= 4; break;
5039 case 3: offset
= 0; break;
5043 gen_op_addl_T1_im(offset
);
5044 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5045 gen_movl_reg_T1(s
, 13);
5047 gen_op_movl_r13_T1_banked(op1
);
5050 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5056 rn
= (insn
>> 16) & 0xf;
5057 gen_movl_T1_reg(s
, rn
);
5058 i
= (insn
>> 23) & 3;
5060 case 0: offset
= 0; break; /* DA */
5061 case 1: offset
= -4; break; /* DB */
5062 case 2: offset
= 4; break; /* IA */
5063 case 3: offset
= 8; break; /* IB */
5067 gen_op_addl_T1_im(offset
);
5068 /* Load CPSR into T2 and PC into T0. */
5070 gen_op_movl_T2_T0();
5071 gen_op_addl_T1_im(-4);
5073 if (insn
& (1 << 21)) {
5074 /* Base writeback. */
5076 case 0: offset
= -4; break;
5077 case 1: offset
= 0; break;
5078 case 2: offset
= 8; break;
5079 case 3: offset
= 4; break;
5083 gen_op_addl_T1_im(offset
);
5084 gen_movl_reg_T1(s
, rn
);
5087 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5088 /* branch link and change to thumb (blx <offset>) */
5091 val
= (uint32_t)s
->pc
;
5092 gen_op_movl_T0_im(val
);
5093 gen_movl_reg_T0(s
, 14);
5094 /* Sign-extend the 24-bit offset */
5095 offset
= (((int32_t)insn
) << 8) >> 8;
5096 /* offset * 4 + bit24 * 2 + (thumb bit) */
5097 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5098 /* pipeline offset */
5100 gen_op_movl_T0_im(val
);
5103 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5104 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5105 /* iWMMXt register transfer. */
5106 if (env
->cp15
.c15_cpar
& (1 << 1))
5107 if (!disas_iwmmxt_insn(env
, s
, insn
))
5110 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5111 /* Coprocessor double register transfer. */
5112 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5113 /* Additional coprocessor register transfer. */
5114 } else if ((insn
& 0x0ff10010) == 0x01000000) {
5117 /* cps (privileged) */
5121 if (insn
& (1 << 19)) {
5122 if (insn
& (1 << 8))
5124 if (insn
& (1 << 7))
5126 if (insn
& (1 << 6))
5128 if (insn
& (1 << 18))
5131 if (insn
& (1 << 14)) {
5133 val
|= (insn
& 0x1f);
5136 gen_op_movl_T0_im(val
);
5137 gen_set_psr_T0(s
, mask
, 0);
5144 /* if not always execute, we generate a conditional jump to
5146 s
->condlabel
= gen_new_label();
5147 gen_test_cc
[cond
^ 1](s
->condlabel
);
5150 if ((insn
& 0x0f900000) == 0x03000000) {
5151 if ((insn
& (1 << 21)) == 0) {
5153 rd
= (insn
>> 12) & 0xf;
5154 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5155 if ((insn
& (1 << 22)) == 0) {
5157 gen_op_movl_T0_im(val
);
5160 gen_movl_T0_reg(s
, rd
);
5161 gen_op_movl_T1_im(0xffff);
5162 gen_op_andl_T0_T1();
5163 gen_op_movl_T1_im(val
<< 16);
5166 gen_movl_reg_T0(s
, rd
);
5168 if (((insn
>> 12) & 0xf) != 0xf)
5170 if (((insn
>> 16) & 0xf) == 0) {
5171 gen_nop_hint(s
, insn
& 0xff);
5173 /* CPSR = immediate */
5175 shift
= ((insn
>> 8) & 0xf) * 2;
5177 val
= (val
>> shift
) | (val
<< (32 - shift
));
5178 gen_op_movl_T0_im(val
);
5179 i
= ((insn
& (1 << 22)) != 0);
5180 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5184 } else if ((insn
& 0x0f900000) == 0x01000000
5185 && (insn
& 0x00000090) != 0x00000090) {
5186 /* miscellaneous instructions */
5187 op1
= (insn
>> 21) & 3;
5188 sh
= (insn
>> 4) & 0xf;
5191 case 0x0: /* move program status register */
5194 gen_movl_T0_reg(s
, rm
);
5195 i
= ((op1
& 2) != 0);
5196 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5200 rd
= (insn
>> 12) & 0xf;
5204 gen_op_movl_T0_spsr();
5206 gen_op_movl_T0_cpsr();
5208 gen_movl_reg_T0(s
, rd
);
5213 /* branch/exchange thumb (bx). */
5214 gen_movl_T0_reg(s
, rm
);
5216 } else if (op1
== 3) {
5218 rd
= (insn
>> 12) & 0xf;
5219 tmp
= load_reg(s
, rm
);
5220 gen_helper_clz(tmp
, tmp
);
5221 store_reg(s
, rd
, tmp
);
5229 /* Trivial implementation equivalent to bx. */
5230 gen_movl_T0_reg(s
, rm
);
5240 /* branch link/exchange thumb (blx) */
5241 val
= (uint32_t)s
->pc
;
5242 gen_op_movl_T1_im(val
);
5243 gen_movl_T0_reg(s
, rm
);
5244 gen_movl_reg_T1(s
, 14);
5247 case 0x5: /* saturating add/subtract */
5248 rd
= (insn
>> 12) & 0xf;
5249 rn
= (insn
>> 16) & 0xf;
5250 gen_movl_T0_reg(s
, rm
);
5251 gen_movl_T1_reg(s
, rn
);
5253 gen_helper_double_saturate(cpu_T
[1], cpu_T
[1]);
5255 gen_op_subl_T0_T1_saturate();
5257 gen_op_addl_T0_T1_saturate();
5258 gen_movl_reg_T0(s
, rd
);
5261 gen_set_condexec(s
);
5262 gen_op_movl_T0_im((long)s
->pc
- 4);
5265 s
->is_jmp
= DISAS_JUMP
;
5267 case 0x8: /* signed multiply */
5271 rs
= (insn
>> 8) & 0xf;
5272 rn
= (insn
>> 12) & 0xf;
5273 rd
= (insn
>> 16) & 0xf;
5275 /* (32 * 16) >> 16 */
5276 gen_movl_T0_reg(s
, rm
);
5277 gen_movl_T1_reg(s
, rs
);
5279 gen_op_sarl_T1_im(16);
5282 gen_op_imulw_T0_T1();
5283 if ((sh
& 2) == 0) {
5284 gen_movl_T1_reg(s
, rn
);
5285 gen_op_addl_T0_T1_setq();
5287 gen_movl_reg_T0(s
, rd
);
5290 gen_movl_T0_reg(s
, rm
);
5291 gen_movl_T1_reg(s
, rs
);
5292 gen_mulxy(sh
& 2, sh
& 4);
5294 gen_op_signbit_T1_T0();
5295 gen_op_addq_T0_T1(rn
, rd
);
5296 gen_movl_reg_T0(s
, rn
);
5297 gen_movl_reg_T1(s
, rd
);
5300 gen_movl_T1_reg(s
, rn
);
5301 gen_op_addl_T0_T1_setq();
5303 gen_movl_reg_T0(s
, rd
);
5310 } else if (((insn
& 0x0e000000) == 0 &&
5311 (insn
& 0x00000090) != 0x90) ||
5312 ((insn
& 0x0e000000) == (1 << 25))) {
5313 int set_cc
, logic_cc
, shiftop
;
5315 op1
= (insn
>> 21) & 0xf;
5316 set_cc
= (insn
>> 20) & 1;
5317 logic_cc
= table_logic_cc
[op1
] & set_cc
;
5319 /* data processing instruction */
5320 if (insn
& (1 << 25)) {
5321 /* immediate operand */
5323 shift
= ((insn
>> 8) & 0xf) * 2;
5325 val
= (val
>> shift
) | (val
<< (32 - shift
));
5326 gen_op_movl_T1_im(val
);
5327 if (logic_cc
&& shift
)
5328 gen_set_CF_bit31(cpu_T
[1]);
5332 gen_movl_T1_reg(s
, rm
);
5333 shiftop
= (insn
>> 5) & 3;
5334 if (!(insn
& (1 << 4))) {
5335 shift
= (insn
>> 7) & 0x1f;
5336 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
5338 rs
= (insn
>> 8) & 0xf;
5339 gen_movl_T0_reg(s
, rs
);
5341 gen_shift_T1_T0_cc
[shiftop
]();
5343 gen_shift_T1_T0
[shiftop
]();
5347 if (op1
!= 0x0f && op1
!= 0x0d) {
5348 rn
= (insn
>> 16) & 0xf;
5349 gen_movl_T0_reg(s
, rn
);
5351 rd
= (insn
>> 12) & 0xf;
5354 gen_op_andl_T0_T1();
5355 gen_movl_reg_T0(s
, rd
);
5357 gen_op_logic_T0_cc();
5360 gen_op_xorl_T0_T1();
5361 gen_movl_reg_T0(s
, rd
);
5363 gen_op_logic_T0_cc();
5366 if (set_cc
&& rd
== 15) {
5367 /* SUBS r15, ... is used for exception return. */
5370 gen_op_subl_T0_T1_cc();
5371 gen_exception_return(s
);
5374 gen_op_subl_T0_T1_cc();
5376 gen_op_subl_T0_T1();
5377 gen_movl_reg_T0(s
, rd
);
5382 gen_op_rsbl_T0_T1_cc();
5384 gen_op_rsbl_T0_T1();
5385 gen_movl_reg_T0(s
, rd
);
5389 gen_op_addl_T0_T1_cc();
5391 gen_op_addl_T0_T1();
5392 gen_movl_reg_T0(s
, rd
);
5396 gen_op_adcl_T0_T1_cc();
5399 gen_movl_reg_T0(s
, rd
);
5403 gen_op_sbcl_T0_T1_cc();
5406 gen_movl_reg_T0(s
, rd
);
5410 gen_op_rscl_T0_T1_cc();
5413 gen_movl_reg_T0(s
, rd
);
5417 gen_op_andl_T0_T1();
5418 gen_op_logic_T0_cc();
5423 gen_op_xorl_T0_T1();
5424 gen_op_logic_T0_cc();
5429 gen_op_subl_T0_T1_cc();
5434 gen_op_addl_T0_T1_cc();
5439 gen_movl_reg_T0(s
, rd
);
5441 gen_op_logic_T0_cc();
5444 if (logic_cc
&& rd
== 15) {
5445 /* MOVS r15, ... is used for exception return. */
5448 gen_op_movl_T0_T1();
5449 gen_exception_return(s
);
5451 gen_movl_reg_T1(s
, rd
);
5453 gen_op_logic_T1_cc();
5457 gen_op_bicl_T0_T1();
5458 gen_movl_reg_T0(s
, rd
);
5460 gen_op_logic_T0_cc();
5465 gen_movl_reg_T1(s
, rd
);
5467 gen_op_logic_T1_cc();
5471 /* other instructions */
5472 op1
= (insn
>> 24) & 0xf;
5476 /* multiplies, extra load/stores */
5477 sh
= (insn
>> 5) & 3;
5480 rd
= (insn
>> 16) & 0xf;
5481 rn
= (insn
>> 12) & 0xf;
5482 rs
= (insn
>> 8) & 0xf;
5484 op1
= (insn
>> 20) & 0xf;
5486 case 0: case 1: case 2: case 3: case 6:
5488 gen_movl_T0_reg(s
, rs
);
5489 gen_movl_T1_reg(s
, rm
);
5491 if (insn
& (1 << 22)) {
5492 /* Subtract (mls) */
5494 gen_movl_T1_reg(s
, rn
);
5495 gen_op_rsbl_T0_T1();
5496 } else if (insn
& (1 << 21)) {
5498 gen_movl_T1_reg(s
, rn
);
5499 gen_op_addl_T0_T1();
5501 if (insn
& (1 << 20))
5502 gen_op_logic_T0_cc();
5503 gen_movl_reg_T0(s
, rd
);
5507 gen_movl_T0_reg(s
, rs
);
5508 gen_movl_T1_reg(s
, rm
);
5509 if (insn
& (1 << 22))
5510 gen_op_imull_T0_T1();
5512 gen_op_mull_T0_T1();
5513 if (insn
& (1 << 21)) /* mult accumulate */
5514 gen_op_addq_T0_T1(rn
, rd
);
5515 if (!(insn
& (1 << 23))) { /* double accumulate */
5517 gen_op_addq_lo_T0_T1(rn
);
5518 gen_op_addq_lo_T0_T1(rd
);
5520 if (insn
& (1 << 20))
5522 gen_movl_reg_T0(s
, rn
);
5523 gen_movl_reg_T1(s
, rd
);
5527 rn
= (insn
>> 16) & 0xf;
5528 rd
= (insn
>> 12) & 0xf;
5529 if (insn
& (1 << 23)) {
5530 /* load/store exclusive */
5531 gen_movl_T1_reg(s
, rn
);
5532 if (insn
& (1 << 20)) {
5536 gen_movl_T0_reg(s
, rm
);
5539 gen_movl_reg_T0(s
, rd
);
5541 /* SWP instruction */
5544 gen_movl_T0_reg(s
, rm
);
5545 gen_movl_T1_reg(s
, rn
);
5546 if (insn
& (1 << 22)) {
5551 gen_movl_reg_T0(s
, rd
);
5557 /* Misc load/store */
5558 rn
= (insn
>> 16) & 0xf;
5559 rd
= (insn
>> 12) & 0xf;
5560 gen_movl_T1_reg(s
, rn
);
5561 if (insn
& (1 << 24))
5562 gen_add_datah_offset(s
, insn
, 0);
5564 if (insn
& (1 << 20)) {
5579 } else if (sh
& 2) {
5583 gen_movl_T0_reg(s
, rd
);
5585 gen_op_addl_T1_im(4);
5586 gen_movl_T0_reg(s
, rd
+ 1);
5592 gen_movl_reg_T0(s
, rd
);
5593 gen_op_addl_T1_im(4);
5598 address_offset
= -4;
5601 gen_movl_T0_reg(s
, rd
);
5605 /* Perform base writeback before the loaded value to
5606 ensure correct behavior with overlapping index registers.
5607 ldrd with base writeback is is undefined if the
5608 destination and index registers overlap. */
5609 if (!(insn
& (1 << 24))) {
5610 gen_add_datah_offset(s
, insn
, address_offset
);
5611 gen_movl_reg_T1(s
, rn
);
5612 } else if (insn
& (1 << 21)) {
5614 gen_op_addl_T1_im(address_offset
);
5615 gen_movl_reg_T1(s
, rn
);
5618 /* Complete the load. */
5619 gen_movl_reg_T0(s
, rd
);
5628 if (insn
& (1 << 4)) {
5630 /* Armv6 Media instructions. */
5632 rn
= (insn
>> 16) & 0xf;
5633 rd
= (insn
>> 12) & 0xf;
5634 rs
= (insn
>> 8) & 0xf;
5635 switch ((insn
>> 23) & 3) {
5636 case 0: /* Parallel add/subtract. */
5637 op1
= (insn
>> 20) & 7;
5638 tmp
= load_reg(s
, rn
);
5639 tmp2
= load_reg(s
, rm
);
5640 sh
= (insn
>> 5) & 7;
5641 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
5643 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
5645 store_reg(s
, rd
, tmp
);
5648 if ((insn
& 0x00700020) == 0) {
5650 tmp
= load_reg(s
, rn
);
5651 tmp2
= load_reg(s
, rm
);
5652 shift
= (insn
>> 7) & 0x1f;
5654 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
5655 if (insn
& (1 << 6)) {
5657 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
5658 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff);
5661 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
5662 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
5664 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
5665 store_reg(s
, rd
, tmp
);
5666 } else if ((insn
& 0x00200020) == 0x00200000) {
5668 tmp
= load_reg(s
, rm
);
5669 shift
= (insn
>> 7) & 0x1f;
5670 if (insn
& (1 << 6)) {
5673 tcg_gen_sari_i32(tmp
, tmp
, shift
);
5675 tcg_gen_shli_i32(tmp
, tmp
, shift
);
5677 sh
= (insn
>> 16) & 0x1f;
5679 if (insn
& (1 << 22))
5680 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
5682 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
5684 store_reg(s
, rd
, tmp
);
5685 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
5687 tmp
= load_reg(s
, rm
);
5688 sh
= (insn
>> 16) & 0x1f;
5690 if (insn
& (1 << 22))
5691 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
5693 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
5695 store_reg(s
, rd
, tmp
);
5696 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
5698 tmp
= load_reg(s
, rn
);
5699 tmp2
= load_reg(s
, rm
);
5701 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
5702 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
5705 store_reg(s
, rd
, tmp
);
5706 } else if ((insn
& 0x000003e0) == 0x00000060) {
5707 gen_movl_T1_reg(s
, rm
);
5708 shift
= (insn
>> 10) & 3;
5709 /* ??? In many cases it's not neccessary to do a
5710 rotate, a shift is sufficient. */
5712 gen_op_rorl_T1_im(shift
* 8);
5713 op1
= (insn
>> 20) & 7;
5715 case 0: gen_sxtb16(cpu_T
[1]); break;
5716 case 2: gen_sxtb(cpu_T
[1]); break;
5717 case 3: gen_sxth(cpu_T
[1]); break;
5718 case 4: gen_uxtb16(cpu_T
[1]); break;
5719 case 6: gen_uxtb(cpu_T
[1]); break;
5720 case 7: gen_uxth(cpu_T
[1]); break;
5721 default: goto illegal_op
;
5724 tmp
= load_reg(s
, rn
);
5725 if ((op1
& 3) == 0) {
5726 gen_add16(cpu_T
[1], tmp
);
5728 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
5732 gen_movl_reg_T1(s
, rd
);
5733 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
5735 gen_movl_T0_reg(s
, rm
);
5736 if (insn
& (1 << 22)) {
5737 if (insn
& (1 << 7)) {
5738 gen_revsh(cpu_T
[0]);
5741 gen_helper_rbit(cpu_T
[0], cpu_T
[0]);
5744 if (insn
& (1 << 7))
5745 gen_rev16(cpu_T
[0]);
5749 gen_movl_reg_T0(s
, rd
);
5754 case 2: /* Multiplies (Type 3). */
5755 gen_movl_T0_reg(s
, rm
);
5756 gen_movl_T1_reg(s
, rs
);
5757 if (insn
& (1 << 20)) {
5758 /* Signed multiply most significant [accumulate]. */
5759 gen_op_imull_T0_T1();
5760 if (insn
& (1 << 5))
5761 gen_op_roundqd_T0_T1();
5763 gen_op_movl_T0_T1();
5765 gen_movl_T1_reg(s
, rn
);
5766 if (insn
& (1 << 6)) {
5767 gen_op_addl_T0_T1();
5769 gen_op_rsbl_T0_T1();
5772 gen_movl_reg_T0(s
, rd
);
5774 if (insn
& (1 << 5))
5775 gen_swap_half(cpu_T
[1]);
5776 gen_smul_dual(cpu_T
[0], cpu_T
[1]);
5777 if (insn
& (1 << 22)) {
5778 if (insn
& (1 << 6)) {
5780 gen_op_addq_T0_T1_dual(rn
, rd
);
5783 gen_op_subq_T0_T1_dual(rn
, rd
);
5786 /* This addition cannot overflow. */
5787 if (insn
& (1 << 6)) {
5789 gen_op_subl_T0_T1();
5792 gen_op_addl_T0_T1();
5796 gen_movl_T1_reg(s
, rn
);
5797 gen_op_addl_T0_T1_setq();
5799 gen_movl_reg_T0(s
, rd
);
5804 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
5806 case 0: /* Unsigned sum of absolute differences. */
5808 tmp
= load_reg(s
, rm
);
5809 tmp2
= load_reg(s
, rs
);
5810 gen_helper_usad8(tmp
, tmp
, tmp2
);
5813 tmp2
= load_reg(s
, rn
);
5814 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
5817 store_reg(s
, rd
, tmp
);
5819 case 0x20: case 0x24: case 0x28: case 0x2c:
5820 /* Bitfield insert/clear. */
5822 shift
= (insn
>> 7) & 0x1f;
5823 i
= (insn
>> 16) & 0x1f;
5826 gen_op_movl_T1_im(0);
5828 gen_movl_T1_reg(s
, rm
);
5831 gen_movl_T0_reg(s
, rd
);
5832 gen_bfi(cpu_T
[1], cpu_T
[0], cpu_T
[1],
5833 shift
, ((1u << i
) - 1) << shift
);
5835 gen_movl_reg_T1(s
, rd
);
5837 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
5838 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
5839 gen_movl_T1_reg(s
, rm
);
5840 shift
= (insn
>> 7) & 0x1f;
5841 i
= ((insn
>> 16) & 0x1f) + 1;
5846 gen_ubfx(cpu_T
[1], shift
, (1u << i
) - 1);
5848 gen_sbfx(cpu_T
[1], shift
, i
);
5851 gen_movl_reg_T1(s
, rd
);
5861 /* Check for undefined extension instructions
5862 * per the ARM Bible IE:
5863 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
5865 sh
= (0xf << 20) | (0xf << 4);
5866 if (op1
== 0x7 && ((insn
& sh
) == sh
))
5870 /* load/store byte/word */
5871 rn
= (insn
>> 16) & 0xf;
5872 rd
= (insn
>> 12) & 0xf;
5873 gen_movl_T1_reg(s
, rn
);
5874 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
5875 if (insn
& (1 << 24))
5876 gen_add_data_offset(s
, insn
);
5877 if (insn
& (1 << 20)) {
5880 #if defined(CONFIG_USER_ONLY)
5881 if (insn
& (1 << 22))
5886 if (insn
& (1 << 22)) {
5890 gen_op_ldub_kernel();
5895 gen_op_ldl_kernel();
5900 gen_movl_T0_reg(s
, rd
);
5901 #if defined(CONFIG_USER_ONLY)
5902 if (insn
& (1 << 22))
5907 if (insn
& (1 << 22)) {
5911 gen_op_stb_kernel();
5916 gen_op_stl_kernel();
5920 if (!(insn
& (1 << 24))) {
5921 gen_add_data_offset(s
, insn
);
5922 gen_movl_reg_T1(s
, rn
);
5923 } else if (insn
& (1 << 21))
5924 gen_movl_reg_T1(s
, rn
); {
5926 if (insn
& (1 << 20)) {
5927 /* Complete the load. */
5931 gen_movl_reg_T0(s
, rd
);
5937 int j
, n
, user
, loaded_base
;
5938 /* load/store multiple words */
5939 /* XXX: store correct base if write back */
5941 if (insn
& (1 << 22)) {
5943 goto illegal_op
; /* only usable in supervisor mode */
5945 if ((insn
& (1 << 15)) == 0)
5948 rn
= (insn
>> 16) & 0xf;
5949 gen_movl_T1_reg(s
, rn
);
5951 /* compute total size */
5955 if (insn
& (1 << i
))
5958 /* XXX: test invalid n == 0 case ? */
5959 if (insn
& (1 << 23)) {
5960 if (insn
& (1 << 24)) {
5962 gen_op_addl_T1_im(4);
5964 /* post increment */
5967 if (insn
& (1 << 24)) {
5969 gen_op_addl_T1_im(-(n
* 4));
5971 /* post decrement */
5973 gen_op_addl_T1_im(-((n
- 1) * 4));
5978 if (insn
& (1 << i
)) {
5979 if (insn
& (1 << 20)) {
5985 gen_op_movl_user_T0(i
);
5986 } else if (i
== rn
) {
5987 gen_op_movl_T2_T0();
5990 gen_movl_reg_T0(s
, i
);
5995 /* special case: r15 = PC + 8 */
5996 val
= (long)s
->pc
+ 4;
5997 gen_op_movl_T0_im(val
);
5999 gen_op_movl_T0_user(i
);
6001 gen_movl_T0_reg(s
, i
);
6006 /* no need to add after the last transfer */
6008 gen_op_addl_T1_im(4);
6011 if (insn
& (1 << 21)) {
6013 if (insn
& (1 << 23)) {
6014 if (insn
& (1 << 24)) {
6017 /* post increment */
6018 gen_op_addl_T1_im(4);
6021 if (insn
& (1 << 24)) {
6024 gen_op_addl_T1_im(-((n
- 1) * 4));
6026 /* post decrement */
6027 gen_op_addl_T1_im(-(n
* 4));
6030 gen_movl_reg_T1(s
, rn
);
6033 gen_op_movl_T0_T2();
6034 gen_movl_reg_T0(s
, rn
);
6036 if ((insn
& (1 << 22)) && !user
) {
6037 /* Restore CPSR from SPSR. */
6038 gen_op_movl_T0_spsr();
6039 gen_op_movl_cpsr_T0(0xffffffff);
6040 s
->is_jmp
= DISAS_UPDATE
;
6049 /* branch (and link) */
6050 val
= (int32_t)s
->pc
;
6051 if (insn
& (1 << 24)) {
6052 gen_op_movl_T0_im(val
);
6053 gen_movl_reg_T0(s
, 14);
6055 offset
= (((int32_t)insn
<< 8) >> 8);
6056 val
+= (offset
<< 2) + 4;
6064 if (disas_coproc_insn(env
, s
, insn
))
6069 gen_op_movl_T0_im((long)s
->pc
);
6071 s
->is_jmp
= DISAS_SWI
;
6075 gen_set_condexec(s
);
6076 gen_op_movl_T0_im((long)s
->pc
- 4);
6078 gen_op_undef_insn();
6079 s
->is_jmp
= DISAS_JUMP
;
6085 /* Return true if this is a Thumb-2 logical op. */
6087 thumb2_logic_op(int op
)
6092 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6093 then set condition code flags based on the result of the operation.
6094 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6095 to the high bit of T1.
6096 Returns zero if the opcode is valid. */
6099 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6106 gen_op_andl_T0_T1();
6110 gen_op_bicl_T0_T1();
6123 gen_op_xorl_T0_T1();
6128 gen_op_addl_T0_T1_cc();
6130 gen_op_addl_T0_T1();
6134 gen_op_adcl_T0_T1_cc();
6140 gen_op_sbcl_T0_T1_cc();
6146 gen_op_subl_T0_T1_cc();
6148 gen_op_subl_T0_T1();
6152 gen_op_rsbl_T0_T1_cc();
6154 gen_op_rsbl_T0_T1();
6156 default: /* 5, 6, 7, 9, 12, 15. */
6160 gen_op_logic_T0_cc();
6162 gen_set_CF_bit31(cpu_T
[1]);
6167 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
6169 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
6171 uint32_t insn
, imm
, shift
, offset
, addr
;
6172 uint32_t rd
, rn
, rm
, rs
;
6181 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
6182 || arm_feature (env
, ARM_FEATURE_M
))) {
6183 /* Thumb-1 cores may need to tread bl and blx as a pair of
6184 16-bit instructions to get correct prefetch abort behavior. */
6186 if ((insn
& (1 << 12)) == 0) {
6187 /* Second half of blx. */
6188 offset
= ((insn
& 0x7ff) << 1);
6189 gen_movl_T0_reg(s
, 14);
6190 gen_op_movl_T1_im(offset
);
6191 gen_op_addl_T0_T1();
6192 gen_op_movl_T1_im(0xfffffffc);
6193 gen_op_andl_T0_T1();
6195 addr
= (uint32_t)s
->pc
;
6196 gen_op_movl_T1_im(addr
| 1);
6197 gen_movl_reg_T1(s
, 14);
6201 if (insn
& (1 << 11)) {
6202 /* Second half of bl. */
6203 offset
= ((insn
& 0x7ff) << 1) | 1;
6204 gen_movl_T0_reg(s
, 14);
6205 gen_op_movl_T1_im(offset
);
6206 gen_op_addl_T0_T1();
6208 addr
= (uint32_t)s
->pc
;
6209 gen_op_movl_T1_im(addr
| 1);
6210 gen_movl_reg_T1(s
, 14);
6214 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
6215 /* Instruction spans a page boundary. Implement it as two
6216 16-bit instructions in case the second half causes an
6218 offset
= ((int32_t)insn
<< 21) >> 9;
6219 addr
= s
->pc
+ 2 + offset
;
6220 gen_op_movl_T0_im(addr
);
6221 gen_movl_reg_T0(s
, 14);
6224 /* Fall through to 32-bit decode. */
6227 insn
= lduw_code(s
->pc
);
6229 insn
|= (uint32_t)insn_hw1
<< 16;
6231 if ((insn
& 0xf800e800) != 0xf000e800) {
6235 rn
= (insn
>> 16) & 0xf;
6236 rs
= (insn
>> 12) & 0xf;
6237 rd
= (insn
>> 8) & 0xf;
6239 switch ((insn
>> 25) & 0xf) {
6240 case 0: case 1: case 2: case 3:
6241 /* 16-bit instructions. Should never happen. */
6244 if (insn
& (1 << 22)) {
6245 /* Other load/store, table branch. */
6246 if (insn
& 0x01200000) {
6247 /* Load/store doubleword. */
6249 gen_op_movl_T1_im(s
->pc
& ~3);
6251 gen_movl_T1_reg(s
, rn
);
6253 offset
= (insn
& 0xff) * 4;
6254 if ((insn
& (1 << 23)) == 0)
6256 if (insn
& (1 << 24)) {
6257 gen_op_addl_T1_im(offset
);
6260 if (insn
& (1 << 20)) {
6263 gen_movl_reg_T0(s
, rs
);
6264 gen_op_addl_T1_im(4);
6266 gen_movl_reg_T0(s
, rd
);
6269 gen_movl_T0_reg(s
, rs
);
6271 gen_op_addl_T1_im(4);
6272 gen_movl_T0_reg(s
, rd
);
6275 if (insn
& (1 << 21)) {
6276 /* Base writeback. */
6279 gen_op_addl_T1_im(offset
- 4);
6280 gen_movl_reg_T1(s
, rn
);
6282 } else if ((insn
& (1 << 23)) == 0) {
6283 /* Load/store exclusive word. */
6284 gen_movl_T0_reg(s
, rd
);
6285 gen_movl_T1_reg(s
, rn
);
6286 if (insn
& (1 << 20)) {
6291 gen_movl_reg_T0(s
, rd
);
6292 } else if ((insn
& (1 << 6)) == 0) {
6295 gen_op_movl_T1_im(s
->pc
);
6297 gen_movl_T1_reg(s
, rn
);
6299 tmp
= load_reg(s
, rm
);
6300 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
6301 if (insn
& (1 << 4)) {
6303 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
6310 tcg_gen_shli_i32(cpu_T
[0], cpu_T
[0], 1);
6311 tcg_gen_addi_i32(cpu_T
[0], cpu_T
[0], s
->pc
);
6312 gen_movl_reg_T0(s
, 15);
6314 /* Load/store exclusive byte/halfword/doubleword. */
6315 op
= (insn
>> 4) & 0x3;
6316 gen_movl_T1_reg(s
, rn
);
6317 if (insn
& (1 << 20)) {
6327 gen_movl_reg_T1(s
, rd
);
6332 gen_movl_reg_T0(s
, rs
);
6334 gen_movl_T0_reg(s
, rs
);
6343 gen_movl_T2_reg(s
, rd
);
6349 gen_movl_reg_T0(s
, rm
);
6353 /* Load/store multiple, RFE, SRS. */
6354 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
6355 /* Not available in user mode. */
6358 if (insn
& (1 << 20)) {
6360 gen_movl_T1_reg(s
, rn
);
6361 if (insn
& (1 << 24)) {
6362 gen_op_addl_T1_im(4);
6364 gen_op_addl_T1_im(-4);
6366 /* Load CPSR into T2 and PC into T0. */
6368 gen_op_movl_T2_T0();
6369 gen_op_addl_T1_im(-4);
6371 if (insn
& (1 << 21)) {
6372 /* Base writeback. */
6373 if (insn
& (1 << 24))
6374 gen_op_addl_T1_im(8);
6375 gen_movl_reg_T1(s
, rn
);
6381 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
6382 gen_movl_T1_reg(s
, 13);
6384 gen_op_movl_T1_r13_banked(op
);
6386 if ((insn
& (1 << 24)) == 0) {
6387 gen_op_addl_T1_im(-8);
6389 gen_movl_T0_reg(s
, 14);
6391 gen_op_movl_T0_cpsr();
6392 gen_op_addl_T1_im(4);
6394 if (insn
& (1 << 21)) {
6395 if ((insn
& (1 << 24)) == 0) {
6396 gen_op_addl_T1_im(-4);
6398 gen_op_addl_T1_im(4);
6400 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
6401 gen_movl_reg_T1(s
, 13);
6403 gen_op_movl_r13_T1_banked(op
);
6409 /* Load/store multiple. */
6410 gen_movl_T1_reg(s
, rn
);
6412 for (i
= 0; i
< 16; i
++) {
6413 if (insn
& (1 << i
))
6416 if (insn
& (1 << 24)) {
6417 gen_op_addl_T1_im(-offset
);
6420 for (i
= 0; i
< 16; i
++) {
6421 if ((insn
& (1 << i
)) == 0)
6423 if (insn
& (1 << 20)) {
6429 gen_movl_reg_T0(s
, i
);
6433 gen_movl_T0_reg(s
, i
);
6436 gen_op_addl_T1_im(4);
6438 if (insn
& (1 << 21)) {
6439 /* Base register writeback. */
6440 if (insn
& (1 << 24)) {
6441 gen_op_addl_T1_im(-offset
);
6443 /* Fault if writeback register is in register list. */
6444 if (insn
& (1 << rn
))
6446 gen_movl_reg_T1(s
, rn
);
6451 case 5: /* Data processing register constant shift. */
6453 gen_op_movl_T0_im(0);
6455 gen_movl_T0_reg(s
, rn
);
6456 gen_movl_T1_reg(s
, rm
);
6457 op
= (insn
>> 21) & 0xf;
6458 shiftop
= (insn
>> 4) & 3;
6459 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
6460 conds
= (insn
& (1 << 20)) != 0;
6461 logic_cc
= (conds
&& thumb2_logic_op(op
));
6462 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
6463 if (gen_thumb2_data_op(s
, op
, conds
, 0))
6466 gen_movl_reg_T0(s
, rd
);
6468 case 13: /* Misc data processing. */
6469 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
6470 if (op
< 4 && (insn
& 0xf000) != 0xf000)
6473 case 0: /* Register controlled shift. */
6474 gen_movl_T0_reg(s
, rm
);
6475 gen_movl_T1_reg(s
, rn
);
6476 if ((insn
& 0x70) != 0)
6478 op
= (insn
>> 21) & 3;
6479 if (insn
& (1 << 20)) {
6480 gen_shift_T1_T0_cc
[op
]();
6481 gen_op_logic_T1_cc();
6483 gen_shift_T1_T0
[op
]();
6485 gen_movl_reg_T1(s
, rd
);
6487 case 1: /* Sign/zero extend. */
6488 gen_movl_T1_reg(s
, rm
);
6489 shift
= (insn
>> 4) & 3;
6490 /* ??? In many cases it's not neccessary to do a
6491 rotate, a shift is sufficient. */
6493 gen_op_rorl_T1_im(shift
* 8);
6494 op
= (insn
>> 20) & 7;
6496 case 0: gen_sxth(cpu_T
[1]); break;
6497 case 1: gen_uxth(cpu_T
[1]); break;
6498 case 2: gen_sxtb16(cpu_T
[1]); break;
6499 case 3: gen_uxtb16(cpu_T
[1]); break;
6500 case 4: gen_sxtb(cpu_T
[1]); break;
6501 case 5: gen_uxtb(cpu_T
[1]); break;
6502 default: goto illegal_op
;
6505 tmp
= load_reg(s
, rn
);
6506 if ((op
>> 1) == 1) {
6507 gen_add16(cpu_T
[1], tmp
);
6509 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
6513 gen_movl_reg_T1(s
, rd
);
6515 case 2: /* SIMD add/subtract. */
6516 op
= (insn
>> 20) & 7;
6517 shift
= (insn
>> 4) & 7;
6518 if ((op
& 3) == 3 || (shift
& 3) == 3)
6520 tmp
= load_reg(s
, rn
);
6521 tmp2
= load_reg(s
, rm
);
6522 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
6524 store_reg(s
, rd
, tmp
);
6526 case 3: /* Other data processing. */
6527 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
6529 /* Saturating add/subtract. */
6530 gen_movl_T0_reg(s
, rm
);
6531 gen_movl_T1_reg(s
, rn
);
6533 gen_helper_double_saturate(cpu_T
[1], cpu_T
[1]);
6535 gen_op_subl_T0_T1_saturate();
6537 gen_op_addl_T0_T1_saturate();
6539 gen_movl_T0_reg(s
, rn
);
6541 case 0x0a: /* rbit */
6542 gen_helper_rbit(cpu_T
[0], cpu_T
[0]);
6544 case 0x08: /* rev */
6547 case 0x09: /* rev16 */
6548 gen_rev16(cpu_T
[0]);
6550 case 0x0b: /* revsh */
6551 gen_revsh(cpu_T
[0]);
6553 case 0x10: /* sel */
6554 gen_movl_T1_reg(s
, rm
);
6556 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6557 gen_helper_sel_flags(cpu_T
[0], tmp3
, cpu_T
[0], cpu_T
[1]);
6560 case 0x18: /* clz */
6561 gen_helper_clz(cpu_T
[0], cpu_T
[0]);
6567 gen_movl_reg_T0(s
, rd
);
6569 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
6570 op
= (insn
>> 4) & 0xf;
6571 gen_movl_T0_reg(s
, rn
);
6572 gen_movl_T1_reg(s
, rm
);
6573 switch ((insn
>> 20) & 7) {
6574 case 0: /* 32 x 32 -> 32 */
6577 gen_movl_T1_reg(s
, rs
);
6579 gen_op_rsbl_T0_T1();
6581 gen_op_addl_T0_T1();
6583 gen_movl_reg_T0(s
, rd
);
6585 case 1: /* 16 x 16 -> 32 */
6586 gen_mulxy(op
& 2, op
& 1);
6588 gen_movl_T1_reg(s
, rs
);
6589 gen_op_addl_T0_T1_setq();
6591 gen_movl_reg_T0(s
, rd
);
6593 case 2: /* Dual multiply add. */
6594 case 4: /* Dual multiply subtract. */
6596 gen_swap_half(cpu_T
[1]);
6597 gen_smul_dual(cpu_T
[0], cpu_T
[1]);
6598 /* This addition cannot overflow. */
6599 if (insn
& (1 << 22)) {
6600 gen_op_subl_T0_T1();
6602 gen_op_addl_T0_T1();
6606 gen_movl_T1_reg(s
, rs
);
6607 gen_op_addl_T0_T1_setq();
6609 gen_movl_reg_T0(s
, rd
);
6611 case 3: /* 32 * 16 -> 32msb */
6613 gen_op_sarl_T1_im(16);
6616 gen_op_imulw_T0_T1();
6619 gen_movl_T1_reg(s
, rs
);
6620 gen_op_addl_T0_T1_setq();
6622 gen_movl_reg_T0(s
, rd
);
6624 case 5: case 6: /* 32 * 32 -> 32msb */
6625 gen_op_imull_T0_T1();
6626 if (insn
& (1 << 5))
6627 gen_op_roundqd_T0_T1();
6629 gen_op_movl_T0_T1();
6631 gen_movl_T1_reg(s
, rs
);
6632 if (insn
& (1 << 21)) {
6633 gen_op_addl_T0_T1();
6635 gen_op_rsbl_T0_T1();
6638 gen_movl_reg_T0(s
, rd
);
6640 case 7: /* Unsigned sum of absolute differences. */
6641 gen_helper_usad8(cpu_T
[0], cpu_T
[0], cpu_T
[1]);
6643 gen_movl_T1_reg(s
, rs
);
6644 gen_op_addl_T0_T1();
6646 gen_movl_reg_T0(s
, rd
);
6650 case 6: case 7: /* 64-bit multiply, Divide. */
6651 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
6652 gen_movl_T0_reg(s
, rn
);
6653 gen_movl_T1_reg(s
, rm
);
6654 if ((op
& 0x50) == 0x10) {
6656 if (!arm_feature(env
, ARM_FEATURE_DIV
))
6659 gen_helper_udiv(cpu_T
[0], cpu_T
[0], cpu_T
[1]);
6661 gen_helper_sdiv(cpu_T
[0], cpu_T
[0], cpu_T
[1]);
6662 gen_movl_reg_T0(s
, rd
);
6663 } else if ((op
& 0xe) == 0xc) {
6664 /* Dual multiply accumulate long. */
6666 gen_swap_half(cpu_T
[1]);
6667 gen_smul_dual(cpu_T
[0], cpu_T
[1]);
6669 gen_op_subl_T0_T1();
6671 gen_op_addl_T0_T1();
6673 gen_op_signbit_T1_T0();
6674 gen_op_addq_T0_T1(rs
, rd
);
6675 gen_movl_reg_T0(s
, rs
);
6676 gen_movl_reg_T1(s
, rd
);
6679 /* Unsigned 64-bit multiply */
6680 gen_op_mull_T0_T1();
6684 gen_mulxy(op
& 2, op
& 1);
6685 gen_op_signbit_T1_T0();
6687 /* Signed 64-bit multiply */
6688 gen_op_imull_T0_T1();
6693 gen_op_addq_lo_T0_T1(rs
);
6694 gen_op_addq_lo_T0_T1(rd
);
6695 } else if (op
& 0x40) {
6696 /* 64-bit accumulate. */
6697 gen_op_addq_T0_T1(rs
, rd
);
6699 gen_movl_reg_T0(s
, rs
);
6700 gen_movl_reg_T1(s
, rd
);
6705 case 6: case 7: case 14: case 15:
6707 if (((insn
>> 24) & 3) == 3) {
6708 /* Translate into the equivalent ARM encoding. */
6709 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
6710 if (disas_neon_data_insn(env
, s
, insn
))
6713 if (insn
& (1 << 28))
6715 if (disas_coproc_insn (env
, s
, insn
))
6719 case 8: case 9: case 10: case 11:
6720 if (insn
& (1 << 15)) {
6721 /* Branches, misc control. */
6722 if (insn
& 0x5000) {
6723 /* Unconditional branch. */
6724 /* signextend(hw1[10:0]) -> offset[:12]. */
6725 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
6726 /* hw1[10:0] -> offset[11:1]. */
6727 offset
|= (insn
& 0x7ff) << 1;
6728 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
6729 offset[24:22] already have the same value because of the
6730 sign extension above. */
6731 offset
^= ((~insn
) & (1 << 13)) << 10;
6732 offset
^= ((~insn
) & (1 << 11)) << 11;
6735 if (insn
& (1 << 14)) {
6736 /* Branch and link. */
6737 gen_op_movl_T1_im(addr
| 1);
6738 gen_movl_reg_T1(s
, 14);
6742 if (insn
& (1 << 12)) {
6747 addr
&= ~(uint32_t)2;
6748 gen_op_movl_T0_im(addr
);
6751 } else if (((insn
>> 23) & 7) == 7) {
6753 if (insn
& (1 << 13))
6756 if (insn
& (1 << 26)) {
6757 /* Secure monitor call (v6Z) */
6758 goto illegal_op
; /* not implemented. */
6760 op
= (insn
>> 20) & 7;
6762 case 0: /* msr cpsr. */
6764 gen_op_v7m_msr_T0(insn
& 0xff);
6765 gen_movl_reg_T0(s
, rn
);
6770 case 1: /* msr spsr. */
6773 gen_movl_T0_reg(s
, rn
);
6774 if (gen_set_psr_T0(s
,
6775 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
6779 case 2: /* cps, nop-hint. */
6780 if (((insn
>> 8) & 7) == 0) {
6781 gen_nop_hint(s
, insn
& 0xff);
6783 /* Implemented as NOP in user mode. */
6788 if (insn
& (1 << 10)) {
6789 if (insn
& (1 << 7))
6791 if (insn
& (1 << 6))
6793 if (insn
& (1 << 5))
6795 if (insn
& (1 << 9))
6796 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
6798 if (insn
& (1 << 8)) {
6800 imm
|= (insn
& 0x1f);
6803 gen_op_movl_T0_im(imm
);
6804 gen_set_psr_T0(s
, offset
, 0);
6807 case 3: /* Special control operations. */
6808 op
= (insn
>> 4) & 0xf;
6816 /* These execute as NOPs. */
6824 /* Trivial implementation equivalent to bx. */
6825 gen_movl_T0_reg(s
, rn
);
6828 case 5: /* Exception return. */
6829 /* Unpredictable in user mode. */
6831 case 6: /* mrs cpsr. */
6833 gen_op_v7m_mrs_T0(insn
& 0xff);
6835 gen_op_movl_T0_cpsr();
6837 gen_movl_reg_T0(s
, rd
);
6839 case 7: /* mrs spsr. */
6840 /* Not accessible in user mode. */
6841 if (IS_USER(s
) || IS_M(env
))
6843 gen_op_movl_T0_spsr();
6844 gen_movl_reg_T0(s
, rd
);
6849 /* Conditional branch. */
6850 op
= (insn
>> 22) & 0xf;
6851 /* Generate a conditional jump to next instruction. */
6852 s
->condlabel
= gen_new_label();
6853 gen_test_cc
[op
^ 1](s
->condlabel
);
6856 /* offset[11:1] = insn[10:0] */
6857 offset
= (insn
& 0x7ff) << 1;
6858 /* offset[17:12] = insn[21:16]. */
6859 offset
|= (insn
& 0x003f0000) >> 4;
6860 /* offset[31:20] = insn[26]. */
6861 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
6862 /* offset[18] = insn[13]. */
6863 offset
|= (insn
& (1 << 13)) << 5;
6864 /* offset[19] = insn[11]. */
6865 offset
|= (insn
& (1 << 11)) << 8;
6867 /* jump to the offset */
6868 addr
= s
->pc
+ offset
;
6872 /* Data processing immediate. */
6873 if (insn
& (1 << 25)) {
6874 if (insn
& (1 << 24)) {
6875 if (insn
& (1 << 20))
6877 /* Bitfield/Saturate. */
6878 op
= (insn
>> 21) & 7;
6880 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
6883 tcg_gen_movi_i32(tmp
, 0);
6885 tmp
= load_reg(s
, rn
);
6888 case 2: /* Signed bitfield extract. */
6890 if (shift
+ imm
> 32)
6893 gen_sbfx(tmp
, shift
, imm
);
6895 case 6: /* Unsigned bitfield extract. */
6897 if (shift
+ imm
> 32)
6900 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
6902 case 3: /* Bitfield insert/clear. */
6905 imm
= imm
+ 1 - shift
;
6907 tmp2
= load_reg(s
, rd
);
6908 gen_bfi(tmp
, tmp2
, tmp
,
6909 shift
, ((1u << imm
) - 1) << shift
);
6915 default: /* Saturate. */
6918 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6920 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6922 tmp2
= tcg_const_i32(imm
);
6925 if ((op
& 1) && shift
== 0)
6926 gen_helper_usat16(tmp
, tmp
, tmp2
);
6928 gen_helper_usat(tmp
, tmp
, tmp2
);
6931 if ((op
& 1) && shift
== 0)
6932 gen_helper_ssat16(tmp
, tmp
, tmp2
);
6934 gen_helper_ssat(tmp
, tmp
, tmp2
);
6938 store_reg(s
, rd
, tmp
);
6940 imm
= ((insn
& 0x04000000) >> 15)
6941 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
6942 if (insn
& (1 << 22)) {
6943 /* 16-bit immediate. */
6944 imm
|= (insn
>> 4) & 0xf000;
6945 if (insn
& (1 << 23)) {
6947 gen_movl_T0_reg(s
, rd
);
6948 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], 0xffff);
6949 tcg_gen_ori_i32(cpu_T
[0], cpu_T
[0], imm
<< 16);
6952 gen_op_movl_T0_im(imm
);
6955 /* Add/sub 12-bit immediate. */
6957 addr
= s
->pc
& ~(uint32_t)3;
6958 if (insn
& (1 << 23))
6962 gen_op_movl_T0_im(addr
);
6964 gen_movl_T0_reg(s
, rn
);
6965 gen_op_movl_T1_im(imm
);
6966 if (insn
& (1 << 23))
6967 gen_op_subl_T0_T1();
6969 gen_op_addl_T0_T1();
6972 gen_movl_reg_T0(s
, rd
);
6975 int shifter_out
= 0;
6976 /* modified 12-bit immediate. */
6977 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
6978 imm
= (insn
& 0xff);
6981 /* Nothing to do. */
6983 case 1: /* 00XY00XY */
6986 case 2: /* XY00XY00 */
6990 case 3: /* XYXYXYXY */
6994 default: /* Rotated constant. */
6995 shift
= (shift
<< 1) | (imm
>> 7);
6997 imm
= imm
<< (32 - shift
);
7001 gen_op_movl_T1_im(imm
);
7002 rn
= (insn
>> 16) & 0xf;
7004 gen_op_movl_T0_im(0);
7006 gen_movl_T0_reg(s
, rn
);
7007 op
= (insn
>> 21) & 0xf;
7008 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7011 rd
= (insn
>> 8) & 0xf;
7013 gen_movl_reg_T0(s
, rd
);
7018 case 12: /* Load/store single data item. */
7022 if ((insn
& 0x01100000) == 0x01000000) {
7023 if (disas_neon_ls_insn(env
, s
, insn
))
7029 /* s->pc has already been incremented by 4. */
7030 imm
= s
->pc
& 0xfffffffc;
7031 if (insn
& (1 << 23))
7032 imm
+= insn
& 0xfff;
7034 imm
-= insn
& 0xfff;
7035 gen_op_movl_T1_im(imm
);
7037 gen_movl_T1_reg(s
, rn
);
7038 if (insn
& (1 << 23)) {
7039 /* Positive offset. */
7041 gen_op_addl_T1_im(imm
);
7043 op
= (insn
>> 8) & 7;
7046 case 0: case 8: /* Shifted Register. */
7047 shift
= (insn
>> 4) & 0xf;
7050 tmp
= load_reg(s
, rm
);
7052 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7053 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
7056 case 4: /* Negative offset. */
7057 gen_op_addl_T1_im(-imm
);
7059 case 6: /* User privilege. */
7060 gen_op_addl_T1_im(imm
);
7062 case 1: /* Post-decrement. */
7065 case 3: /* Post-increment. */
7069 case 5: /* Pre-decrement. */
7072 case 7: /* Pre-increment. */
7073 gen_op_addl_T1_im(imm
);
7081 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7082 if (insn
& (1 << 20)) {
7084 if (rs
== 15 && op
!= 2) {
7087 /* Memory hint. Implemented as NOP. */
7090 case 0: gen_ldst(ldub
, s
); break;
7091 case 4: gen_ldst(ldsb
, s
); break;
7092 case 1: gen_ldst(lduw
, s
); break;
7093 case 5: gen_ldst(ldsw
, s
); break;
7094 case 2: gen_ldst(ldl
, s
); break;
7095 default: goto illegal_op
;
7100 gen_movl_reg_T0(s
, rs
);
7107 gen_movl_T0_reg(s
, rs
);
7109 case 0: gen_ldst(stb
, s
); break;
7110 case 1: gen_ldst(stw
, s
); break;
7111 case 2: gen_ldst(stl
, s
); break;
7112 default: goto illegal_op
;
7116 gen_op_addl_T1_im(imm
);
7118 gen_movl_reg_T1(s
, rn
);
7129 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
7131 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
7136 if (s
->condexec_mask
) {
7137 cond
= s
->condexec_cond
;
7138 s
->condlabel
= gen_new_label();
7139 gen_test_cc
[cond
^ 1](s
->condlabel
);
7143 insn
= lduw_code(s
->pc
);
7146 switch (insn
>> 12) {
7149 op
= (insn
>> 11) & 3;
7152 rn
= (insn
>> 3) & 7;
7153 gen_movl_T0_reg(s
, rn
);
7154 if (insn
& (1 << 10)) {
7156 gen_op_movl_T1_im((insn
>> 6) & 7);
7159 rm
= (insn
>> 6) & 7;
7160 gen_movl_T1_reg(s
, rm
);
7162 if (insn
& (1 << 9)) {
7163 if (s
->condexec_mask
)
7164 gen_op_subl_T0_T1();
7166 gen_op_subl_T0_T1_cc();
7168 if (s
->condexec_mask
)
7169 gen_op_addl_T0_T1();
7171 gen_op_addl_T0_T1_cc();
7173 gen_movl_reg_T0(s
, rd
);
7175 /* shift immediate */
7176 rm
= (insn
>> 3) & 7;
7177 shift
= (insn
>> 6) & 0x1f;
7178 tmp
= load_reg(s
, rm
);
7179 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
7180 if (!s
->condexec_mask
)
7182 store_reg(s
, rd
, tmp
);
7186 /* arithmetic large immediate */
7187 op
= (insn
>> 11) & 3;
7188 rd
= (insn
>> 8) & 0x7;
7190 gen_op_movl_T0_im(insn
& 0xff);
7192 gen_movl_T0_reg(s
, rd
);
7193 gen_op_movl_T1_im(insn
& 0xff);
7197 if (!s
->condexec_mask
)
7198 gen_op_logic_T0_cc();
7201 gen_op_subl_T0_T1_cc();
7204 if (s
->condexec_mask
)
7205 gen_op_addl_T0_T1();
7207 gen_op_addl_T0_T1_cc();
7210 if (s
->condexec_mask
)
7211 gen_op_subl_T0_T1();
7213 gen_op_subl_T0_T1_cc();
7217 gen_movl_reg_T0(s
, rd
);
7220 if (insn
& (1 << 11)) {
7221 rd
= (insn
>> 8) & 7;
7222 /* load pc-relative. Bit 1 of PC is ignored. */
7223 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
7224 val
&= ~(uint32_t)2;
7225 gen_op_movl_T1_im(val
);
7227 gen_movl_reg_T0(s
, rd
);
7230 if (insn
& (1 << 10)) {
7231 /* data processing extended or blx */
7232 rd
= (insn
& 7) | ((insn
>> 4) & 8);
7233 rm
= (insn
>> 3) & 0xf;
7234 op
= (insn
>> 8) & 3;
7237 gen_movl_T0_reg(s
, rd
);
7238 gen_movl_T1_reg(s
, rm
);
7239 gen_op_addl_T0_T1();
7240 gen_movl_reg_T0(s
, rd
);
7243 gen_movl_T0_reg(s
, rd
);
7244 gen_movl_T1_reg(s
, rm
);
7245 gen_op_subl_T0_T1_cc();
7247 case 2: /* mov/cpy */
7248 gen_movl_T0_reg(s
, rm
);
7249 gen_movl_reg_T0(s
, rd
);
7251 case 3:/* branch [and link] exchange thumb register */
7252 if (insn
& (1 << 7)) {
7253 val
= (uint32_t)s
->pc
| 1;
7254 gen_op_movl_T1_im(val
);
7255 gen_movl_reg_T1(s
, 14);
7257 gen_movl_T0_reg(s
, rm
);
7264 /* data processing register */
7266 rm
= (insn
>> 3) & 7;
7267 op
= (insn
>> 6) & 0xf;
7268 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
7269 /* the shift/rotate ops want the operands backwards */
7278 if (op
== 9) /* neg */
7279 gen_op_movl_T0_im(0);
7280 else if (op
!= 0xf) /* mvn doesn't read its first operand */
7281 gen_movl_T0_reg(s
, rd
);
7283 gen_movl_T1_reg(s
, rm
);
7286 gen_op_andl_T0_T1();
7287 if (!s
->condexec_mask
)
7288 gen_op_logic_T0_cc();
7291 gen_op_xorl_T0_T1();
7292 if (!s
->condexec_mask
)
7293 gen_op_logic_T0_cc();
7296 if (s
->condexec_mask
) {
7297 gen_op_shll_T1_T0();
7299 gen_op_shll_T1_T0_cc();
7300 gen_op_logic_T1_cc();
7304 if (s
->condexec_mask
) {
7305 gen_op_shrl_T1_T0();
7307 gen_op_shrl_T1_T0_cc();
7308 gen_op_logic_T1_cc();
7312 if (s
->condexec_mask
) {
7313 gen_op_sarl_T1_T0();
7315 gen_op_sarl_T1_T0_cc();
7316 gen_op_logic_T1_cc();
7320 if (s
->condexec_mask
)
7323 gen_op_adcl_T0_T1_cc();
7326 if (s
->condexec_mask
)
7329 gen_op_sbcl_T0_T1_cc();
7332 if (s
->condexec_mask
) {
7333 gen_op_rorl_T1_T0();
7335 gen_op_rorl_T1_T0_cc();
7336 gen_op_logic_T1_cc();
7340 gen_op_andl_T0_T1();
7341 gen_op_logic_T0_cc();
7345 if (s
->condexec_mask
)
7346 gen_op_subl_T0_T1();
7348 gen_op_subl_T0_T1_cc();
7351 gen_op_subl_T0_T1_cc();
7355 gen_op_addl_T0_T1_cc();
7360 if (!s
->condexec_mask
)
7361 gen_op_logic_T0_cc();
7364 gen_op_mull_T0_T1();
7365 if (!s
->condexec_mask
)
7366 gen_op_logic_T0_cc();
7369 gen_op_bicl_T0_T1();
7370 if (!s
->condexec_mask
)
7371 gen_op_logic_T0_cc();
7375 if (!s
->condexec_mask
)
7376 gen_op_logic_T1_cc();
7383 gen_movl_reg_T1(s
, rm
);
7385 gen_movl_reg_T0(s
, rd
);
7390 /* load/store register offset. */
7392 rn
= (insn
>> 3) & 7;
7393 rm
= (insn
>> 6) & 7;
7394 op
= (insn
>> 9) & 7;
7395 gen_movl_T1_reg(s
, rn
);
7396 tmp
= load_reg(s
, rm
);
7397 tcg_gen_add_i32(cpu_T
[1], cpu_T
[1], tmp
);
7400 if (op
< 3) /* store */
7401 gen_movl_T0_reg(s
, rd
);
7429 if (op
>= 3) /* load */
7430 gen_movl_reg_T0(s
, rd
);
7434 /* load/store word immediate offset */
7436 rn
= (insn
>> 3) & 7;
7437 gen_movl_T1_reg(s
, rn
);
7438 val
= (insn
>> 4) & 0x7c;
7439 tcg_gen_addi_i32(cpu_T
[1], cpu_T
[1], val
);
7441 if (insn
& (1 << 11)) {
7444 gen_movl_reg_T0(s
, rd
);
7447 gen_movl_T0_reg(s
, rd
);
7453 /* load/store byte immediate offset */
7455 rn
= (insn
>> 3) & 7;
7456 gen_movl_T1_reg(s
, rn
);
7457 val
= (insn
>> 6) & 0x1f;
7458 tcg_gen_addi_i32(cpu_T
[1], cpu_T
[1], val
);
7460 if (insn
& (1 << 11)) {
7463 gen_movl_reg_T0(s
, rd
);
7466 gen_movl_T0_reg(s
, rd
);
7472 /* load/store halfword immediate offset */
7474 rn
= (insn
>> 3) & 7;
7475 gen_movl_T1_reg(s
, rn
);
7476 val
= (insn
>> 5) & 0x3e;
7477 tcg_gen_addi_i32(cpu_T
[1], cpu_T
[1], val
);
7479 if (insn
& (1 << 11)) {
7482 gen_movl_reg_T0(s
, rd
);
7485 gen_movl_T0_reg(s
, rd
);
7491 /* load/store from stack */
7492 rd
= (insn
>> 8) & 7;
7493 gen_movl_T1_reg(s
, 13);
7494 val
= (insn
& 0xff) * 4;
7495 tcg_gen_addi_i32(cpu_T
[1], cpu_T
[1], val
);
7497 if (insn
& (1 << 11)) {
7500 gen_movl_reg_T0(s
, rd
);
7503 gen_movl_T0_reg(s
, rd
);
7509 /* add to high reg */
7510 rd
= (insn
>> 8) & 7;
7511 if (insn
& (1 << 11)) {
7513 gen_movl_T0_reg(s
, 13);
7515 /* PC. bit 1 is ignored. */
7516 gen_op_movl_T0_im((s
->pc
+ 2) & ~(uint32_t)2);
7518 val
= (insn
& 0xff) * 4;
7519 gen_op_movl_T1_im(val
);
7520 gen_op_addl_T0_T1();
7521 gen_movl_reg_T0(s
, rd
);
7526 op
= (insn
>> 8) & 0xf;
7529 /* adjust stack pointer */
7530 tmp
= load_reg(s
, 13);
7531 val
= (insn
& 0x7f) * 4;
7532 if (insn
& (1 << 7))
7533 val
= -(int32_t)val
;
7534 tcg_gen_addi_i32(tmp
, tmp
, val
);
7535 store_reg(s
, 13, tmp
);
7538 case 2: /* sign/zero extend. */
7541 rm
= (insn
>> 3) & 7;
7542 gen_movl_T1_reg(s
, rm
);
7543 switch ((insn
>> 6) & 3) {
7544 case 0: gen_sxth(cpu_T
[1]); break;
7545 case 1: gen_sxtb(cpu_T
[1]); break;
7546 case 2: gen_uxth(cpu_T
[1]); break;
7547 case 3: gen_uxtb(cpu_T
[1]); break;
7549 gen_movl_reg_T1(s
, rd
);
7551 case 4: case 5: case 0xc: case 0xd:
7553 gen_movl_T1_reg(s
, 13);
7554 if (insn
& (1 << 8))
7558 for (i
= 0; i
< 8; i
++) {
7559 if (insn
& (1 << i
))
7562 if ((insn
& (1 << 11)) == 0) {
7563 gen_op_addl_T1_im(-offset
);
7565 for (i
= 0; i
< 8; i
++) {
7566 if (insn
& (1 << i
)) {
7567 if (insn
& (1 << 11)) {
7570 gen_movl_reg_T0(s
, i
);
7573 gen_movl_T0_reg(s
, i
);
7576 /* advance to the next address. */
7577 gen_op_addl_T1_im(4);
7580 if (insn
& (1 << 8)) {
7581 if (insn
& (1 << 11)) {
7584 /* don't set the pc until the rest of the instruction
7588 gen_movl_T0_reg(s
, 14);
7591 gen_op_addl_T1_im(4);
7593 if ((insn
& (1 << 11)) == 0) {
7594 gen_op_addl_T1_im(-offset
);
7596 /* write back the new stack pointer */
7597 gen_movl_reg_T1(s
, 13);
7598 /* set the new PC value */
7599 if ((insn
& 0x0900) == 0x0900)
7603 case 1: case 3: case 9: case 11: /* czb */
7605 gen_movl_T0_reg(s
, rm
);
7606 s
->condlabel
= gen_new_label();
7608 if (insn
& (1 << 11))
7609 gen_op_testn_T0(s
->condlabel
);
7611 gen_op_test_T0(s
->condlabel
);
7613 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
7614 val
= (uint32_t)s
->pc
+ 2;
7619 case 15: /* IT, nop-hint. */
7620 if ((insn
& 0xf) == 0) {
7621 gen_nop_hint(s
, (insn
>> 4) & 0xf);
7625 s
->condexec_cond
= (insn
>> 4) & 0xe;
7626 s
->condexec_mask
= insn
& 0x1f;
7627 /* No actual code generated for this insn, just setup state. */
7630 case 0xe: /* bkpt */
7631 gen_set_condexec(s
);
7632 gen_op_movl_T0_im((long)s
->pc
- 2);
7635 s
->is_jmp
= DISAS_JUMP
;
7640 rn
= (insn
>> 3) & 0x7;
7642 gen_movl_T0_reg(s
, rn
);
7643 switch ((insn
>> 6) & 3) {
7644 case 0: gen_op_rev_T0(); break;
7645 case 1: gen_rev16(cpu_T
[0]); break;
7646 case 3: gen_revsh(cpu_T
[0]); break;
7647 default: goto illegal_op
;
7649 gen_movl_reg_T0(s
, rd
);
7657 val
= (insn
& (1 << 4)) != 0;
7658 gen_op_movl_T0_im(val
);
7661 gen_op_v7m_msr_T0(16);
7664 gen_op_v7m_msr_T0(17);
7668 if (insn
& (1 << 4))
7669 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
7673 val
= ((insn
& 7) << 6) & shift
;
7674 gen_op_movl_T0_im(val
);
7675 gen_set_psr_T0(s
, shift
, 0);
7685 /* load/store multiple */
7686 rn
= (insn
>> 8) & 0x7;
7687 gen_movl_T1_reg(s
, rn
);
7688 for (i
= 0; i
< 8; i
++) {
7689 if (insn
& (1 << i
)) {
7690 if (insn
& (1 << 11)) {
7693 gen_movl_reg_T0(s
, i
);
7696 gen_movl_T0_reg(s
, i
);
7699 /* advance to the next address */
7700 gen_op_addl_T1_im(4);
7703 /* Base register writeback. */
7704 if ((insn
& (1 << rn
)) == 0)
7705 gen_movl_reg_T1(s
, rn
);
7709 /* conditional branch or swi */
7710 cond
= (insn
>> 8) & 0xf;
7716 gen_set_condexec(s
);
7717 gen_op_movl_T0_im((long)s
->pc
| 1);
7718 /* Don't set r15. */
7720 s
->is_jmp
= DISAS_SWI
;
7723 /* generate a conditional jump to next instruction */
7724 s
->condlabel
= gen_new_label();
7725 gen_test_cc
[cond
^ 1](s
->condlabel
);
7727 gen_movl_T1_reg(s
, 15);
7729 /* jump to the offset */
7730 val
= (uint32_t)s
->pc
+ 2;
7731 offset
= ((int32_t)insn
<< 24) >> 24;
7737 if (insn
& (1 << 11)) {
7738 if (disas_thumb2_insn(env
, s
, insn
))
7742 /* unconditional branch */
7743 val
= (uint32_t)s
->pc
;
7744 offset
= ((int32_t)insn
<< 21) >> 21;
7745 val
+= (offset
<< 1) + 2;
7750 if (disas_thumb2_insn(env
, s
, insn
))
7756 gen_set_condexec(s
);
7757 gen_op_movl_T0_im((long)s
->pc
- 4);
7759 gen_op_undef_insn();
7760 s
->is_jmp
= DISAS_JUMP
;
7764 gen_set_condexec(s
);
7765 gen_op_movl_T0_im((long)s
->pc
- 2);
7767 gen_op_undef_insn();
7768 s
->is_jmp
= DISAS_JUMP
;
7771 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7772 basic block 'tb'. If search_pc is TRUE, also generate PC
7773 information for each intermediate instruction. */
7774 static inline int gen_intermediate_code_internal(CPUState
*env
,
7775 TranslationBlock
*tb
,
7778 DisasContext dc1
, *dc
= &dc1
;
7779 uint16_t *gen_opc_end
;
7781 target_ulong pc_start
;
7782 uint32_t next_page_start
;
7784 /* generate intermediate code */
7786 memset(temps
, 0, sizeof(temps
));
7792 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
7794 dc
->is_jmp
= DISAS_NEXT
;
7796 dc
->singlestep_enabled
= env
->singlestep_enabled
;
7798 dc
->thumb
= env
->thumb
;
7799 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
7800 dc
->condexec_cond
= env
->condexec_bits
>> 4;
7802 #if !defined(CONFIG_USER_ONLY)
7804 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
7806 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
7809 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
7811 /* Reset the conditional execution bits immediately. This avoids
7812 complications trying to do it at the end of the block. */
7813 if (env
->condexec_bits
)
7815 TCGv tmp
= new_tmp();
7816 tcg_gen_movi_i32(tmp
, 0);
7817 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, condexec_bits
));
7821 #ifndef CONFIG_USER_ONLY
7822 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
7823 /* We always get here via a jump, so know we are not in a
7824 conditional execution block. */
7825 gen_op_exception_exit();
7829 if (env
->nb_breakpoints
> 0) {
7830 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
7831 if (env
->breakpoints
[j
] == dc
->pc
) {
7832 gen_set_condexec(dc
);
7833 gen_op_movl_T0_im((long)dc
->pc
);
7836 dc
->is_jmp
= DISAS_JUMP
;
7837 /* Advance PC so that clearing the breakpoint will
7838 invalidate this TB. */
7840 goto done_generating
;
7846 j
= gen_opc_ptr
- gen_opc_buf
;
7850 gen_opc_instr_start
[lj
++] = 0;
7852 gen_opc_pc
[lj
] = dc
->pc
;
7853 gen_opc_instr_start
[lj
] = 1;
7857 disas_thumb_insn(env
, dc
);
7858 if (dc
->condexec_mask
) {
7859 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
7860 | ((dc
->condexec_mask
>> 4) & 1);
7861 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
7862 if (dc
->condexec_mask
== 0) {
7863 dc
->condexec_cond
= 0;
7867 disas_arm_insn(env
, dc
);
7870 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
7874 if (dc
->condjmp
&& !dc
->is_jmp
) {
7875 gen_set_label(dc
->condlabel
);
7878 /* Terminate the TB on memory ops if watchpoints are present. */
7879 /* FIXME: This should be replacd by the deterministic execution
7880 * IRQ raising bits. */
7881 if (dc
->is_mem
&& env
->nb_watchpoints
)
7884 /* Translation stops when a conditional branch is enoutered.
7885 * Otherwise the subsequent code could get translated several times.
7886 * Also stop translation when a page boundary is reached. This
7887 * ensures prefech aborts occur at the right place. */
7888 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
7889 !env
->singlestep_enabled
&&
7890 dc
->pc
< next_page_start
);
7892 /* At this stage dc->condjmp will only be set when the skipped
7893 instruction was a conditional branch or trap, and the PC has
7894 already been written. */
7895 if (__builtin_expect(env
->singlestep_enabled
, 0)) {
7896 /* Make sure the pc is updated, and raise a debug exception. */
7898 gen_set_condexec(dc
);
7899 if (dc
->is_jmp
== DISAS_SWI
) {
7904 gen_set_label(dc
->condlabel
);
7906 if (dc
->condjmp
|| !dc
->is_jmp
) {
7907 gen_op_movl_T0_im((long)dc
->pc
);
7911 gen_set_condexec(dc
);
7912 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
7915 /* FIXME: Single stepping a WFI insn will not halt
7920 /* While branches must always occur at the end of an IT block,
7921 there are a few other things that can cause us to terminate
7922 the TB in the middel of an IT block:
7923 - Exception generating instructions (bkpt, swi, undefined).
7925 - Hardware watchpoints.
7926 Hardware breakpoints have already been handled and skip this code.
7928 gen_set_condexec(dc
);
7929 switch(dc
->is_jmp
) {
7931 gen_goto_tb(dc
, 1, dc
->pc
);
7936 /* indicate that the hash table must be used to find the next TB */
7940 /* nothing more to generate */
7950 gen_set_label(dc
->condlabel
);
7951 gen_set_condexec(dc
);
7952 gen_goto_tb(dc
, 1, dc
->pc
);
7957 *gen_opc_ptr
= INDEX_op_end
;
7960 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
7961 fprintf(logfile
, "----------------\n");
7962 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
7963 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, env
->thumb
);
7964 fprintf(logfile
, "\n");
7968 j
= gen_opc_ptr
- gen_opc_buf
;
7971 gen_opc_instr_start
[lj
++] = 0;
7973 tb
->size
= dc
->pc
- pc_start
;
7978 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
7980 return gen_intermediate_code_internal(env
, tb
, 0);
7983 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
7985 return gen_intermediate_code_internal(env
, tb
, 1);
7988 static const char *cpu_mode_names
[16] = {
7989 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
7990 "???", "???", "???", "und", "???", "???", "???", "sys"
7993 void cpu_dump_state(CPUState
*env
, FILE *f
,
7994 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8003 /* ??? This assumes float64 and double have the same layout.
8004 Oh well, it's only debug dumps. */
8012 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8014 cpu_fprintf(f
, "\n");
8016 cpu_fprintf(f
, " ");
8018 psr
= cpsr_read(env
);
8019 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8021 psr
& (1 << 31) ? 'N' : '-',
8022 psr
& (1 << 30) ? 'Z' : '-',
8023 psr
& (1 << 29) ? 'C' : '-',
8024 psr
& (1 << 28) ? 'V' : '-',
8025 psr
& CPSR_T
? 'T' : 'A',
8026 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8028 for (i
= 0; i
< 16; i
++) {
8029 d
.d
= env
->vfp
.regs
[i
];
8033 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8034 i
* 2, (int)s0
.i
, s0
.s
,
8035 i
* 2 + 1, (int)s1
.i
, s1
.s
,
8036 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
8039 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);