1 /*
2 * ARM translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
21 */
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <inttypes.h>
27
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
32 #include "qemu-log.h"
33
34 #ifdef CONFIG_TRACE
35 #include "trace.h"
36 #endif
37
38 #include "helpers.h"
39 #define GEN_HELPER 1
40 #include "helpers.h"
41
42 #define ENABLE_ARCH_5J 0
43 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
44 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
45 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
46 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
47
48 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
49
50 /* internal defines */
51 typedef struct DisasContext {
52 target_ulong pc;
53 int is_jmp;
54 /* Nonzero if this instruction has been conditionally skipped. */
55 int condjmp;
56 /* The label that will be jumped to when the instruction is skipped. */
57 int condlabel;
58 /* Thumb-2 condtional execution bits. */
59 int condexec_mask;
60 int condexec_cond;
61 int condexec_mask_prev; /* mask at start of instruction/block */
62 struct TranslationBlock *tb;
63 int singlestep_enabled;
64 int thumb;
65 #if !defined(CONFIG_USER_ONLY)
66 int user;
67 #endif
68 } DisasContext;
69
70 #if defined(CONFIG_USER_ONLY)
71 #define IS_USER(s) 1
72 #else
73 #define IS_USER(s) (s->user)
74 #endif
75
76 #ifdef CONFIG_TRACE
77 #include "helpers.h"
78 #endif /* CONFIG_TRACE */
79
80 /* These instructions trap after executing, so defer them until after the
81 conditional executions state has been updated. */
82 #define DISAS_WFI 4
83 #define DISAS_SWI 5
84
85 static TCGv_ptr cpu_env;
86 /* We reuse the same 64-bit temporaries for efficiency. */
87 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
88
89 /* FIXME: These should be removed. */
90 static TCGv cpu_T[2];
91 static TCGv cpu_F0s, cpu_F1s;
92 static TCGv_i64 cpu_F0d, cpu_F1d;
93
94 #define ICOUNT_TEMP cpu_T[0]
95 #include "gen-icount.h"
96
97 /* initialize TCG globals. */
arm_translate_init(void)98 void arm_translate_init(void)
99 {
100 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
101
102 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
103 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
104
105 #define GEN_HELPER 2
106 #include "helpers.h"
107 }
108
109 /* The code generator doesn't like lots of temporaries, so maintain our own
110 cache for reuse within a function. */
111 #define MAX_TEMPS 8
112 static int num_temps;
113 static TCGv temps[MAX_TEMPS];
114
115 /* Allocate a temporary variable. */
new_tmp(void)116 static TCGv_i32 new_tmp(void)
117 {
118 TCGv tmp;
119 if (num_temps == MAX_TEMPS)
120 abort();
121
122 if (GET_TCGV_I32(temps[num_temps]))
123 return temps[num_temps++];
124
125 tmp = tcg_temp_new_i32();
126 temps[num_temps++] = tmp;
127 return tmp;
128 }
129
130 /* Release a temporary variable. */
dead_tmp(TCGv tmp)131 static void dead_tmp(TCGv tmp)
132 {
133 int i;
134 num_temps--;
135 i = num_temps;
136 if (TCGV_EQUAL(temps[i], tmp))
137 return;
138
139 /* Shuffle this temp to the last slot. */
140 while (!TCGV_EQUAL(temps[i], tmp))
141 i--;
142 while (i < num_temps) {
143 temps[i] = temps[i + 1];
144 i++;
145 }
146 temps[i] = tmp;
147 }
148
load_cpu_offset(int offset)149 static inline TCGv load_cpu_offset(int offset)
150 {
151 TCGv tmp = new_tmp();
152 tcg_gen_ld_i32(tmp, cpu_env, offset);
153 return tmp;
154 }
155
156 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
157
store_cpu_offset(TCGv var,int offset)158 static inline void store_cpu_offset(TCGv var, int offset)
159 {
160 tcg_gen_st_i32(var, cpu_env, offset);
161 dead_tmp(var);
162 }
163
164 #define store_cpu_field(var, name) \
165 store_cpu_offset(var, offsetof(CPUState, name))
166
167 /* Set a variable to the value of a CPU register. */
load_reg_var(DisasContext * s,TCGv var,int reg)168 static void load_reg_var(DisasContext *s, TCGv var, int reg)
169 {
170 if (reg == 15) {
171 uint32_t addr;
172 /* normaly, since we updated PC, we need only to add one insn */
173 if (s->thumb)
174 addr = (long)s->pc + 2;
175 else
176 addr = (long)s->pc + 4;
177 tcg_gen_movi_i32(var, addr);
178 } else {
179 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
180 }
181 }
182
183 /* Create a new temporary and set it to the value of a CPU register. */
load_reg(DisasContext * s,int reg)184 static inline TCGv load_reg(DisasContext *s, int reg)
185 {
186 TCGv tmp = new_tmp();
187 load_reg_var(s, tmp, reg);
188 return tmp;
189 }
190
191 /* Set a CPU register. The source must be a temporary and will be
192 marked as dead. */
store_reg(DisasContext * s,int reg,TCGv var)193 static void store_reg(DisasContext *s, int reg, TCGv var)
194 {
195 if (reg == 15) {
196 tcg_gen_andi_i32(var, var, ~1);
197 s->is_jmp = DISAS_JUMP;
198 }
199 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
200 dead_tmp(var);
201 }
202
203
204 /* Basic operations. */
205 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
206 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
207 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
208
209 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
210 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
211 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
213
214 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
215 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
216 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
217 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
218 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
219
220 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
221 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
222 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
223 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
224 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
225 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
226 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
227
228 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
229 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
230
231 /* Value extensions. */
232 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
233 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
234 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
235 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
236
237 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
238 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
239
240 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
241
242 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
243 /* Set NZCV flags from the high 4 bits of var. */
244 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
245
gen_exception(int excp)246 static void gen_exception(int excp)
247 {
248 TCGv tmp = new_tmp();
249 tcg_gen_movi_i32(tmp, excp);
250 gen_helper_exception(tmp);
251 dead_tmp(tmp);
252 }
253
gen_smul_dual(TCGv a,TCGv b)254 static void gen_smul_dual(TCGv a, TCGv b)
255 {
256 TCGv tmp1 = new_tmp();
257 TCGv tmp2 = new_tmp();
258 tcg_gen_ext16s_i32(tmp1, a);
259 tcg_gen_ext16s_i32(tmp2, b);
260 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
261 dead_tmp(tmp2);
262 tcg_gen_sari_i32(a, a, 16);
263 tcg_gen_sari_i32(b, b, 16);
264 tcg_gen_mul_i32(b, b, a);
265 tcg_gen_mov_i32(a, tmp1);
266 dead_tmp(tmp1);
267 }
268
269 /* Byteswap each halfword. */
gen_rev16(TCGv var)270 static void gen_rev16(TCGv var)
271 {
272 TCGv tmp = new_tmp();
273 tcg_gen_shri_i32(tmp, var, 8);
274 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
275 tcg_gen_shli_i32(var, var, 8);
276 tcg_gen_andi_i32(var, var, 0xff00ff00);
277 tcg_gen_or_i32(var, var, tmp);
278 dead_tmp(tmp);
279 }
280
281 /* Byteswap low halfword and sign extend. */
gen_revsh(TCGv var)282 static void gen_revsh(TCGv var)
283 {
284 TCGv tmp = new_tmp();
285 tcg_gen_shri_i32(tmp, var, 8);
286 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
287 tcg_gen_shli_i32(var, var, 8);
288 tcg_gen_ext8s_i32(var, var);
289 tcg_gen_or_i32(var, var, tmp);
290 dead_tmp(tmp);
291 }
292
293 /* Unsigned bitfield extract. */
gen_ubfx(TCGv var,int shift,uint32_t mask)294 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
295 {
296 if (shift)
297 tcg_gen_shri_i32(var, var, shift);
298 tcg_gen_andi_i32(var, var, mask);
299 }
300
301 /* Signed bitfield extract. */
gen_sbfx(TCGv var,int shift,int width)302 static void gen_sbfx(TCGv var, int shift, int width)
303 {
304 uint32_t signbit;
305
306 if (shift)
307 tcg_gen_sari_i32(var, var, shift);
308 if (shift + width < 32) {
309 signbit = 1u << (width - 1);
310 tcg_gen_andi_i32(var, var, (1u << width) - 1);
311 tcg_gen_xori_i32(var, var, signbit);
312 tcg_gen_subi_i32(var, var, signbit);
313 }
314 }
315
316 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
gen_bfi(TCGv dest,TCGv base,TCGv val,int shift,uint32_t mask)317 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
318 {
319 tcg_gen_andi_i32(val, val, mask);
320 tcg_gen_shli_i32(val, val, shift);
321 tcg_gen_andi_i32(base, base, ~(mask << shift));
322 tcg_gen_or_i32(dest, base, val);
323 }
324
325 /* Round the top 32 bits of a 64-bit value. */
gen_roundqd(TCGv a,TCGv b)326 static void gen_roundqd(TCGv a, TCGv b)
327 {
328 tcg_gen_shri_i32(a, a, 31);
329 tcg_gen_add_i32(a, a, b);
330 }
331
332 /* FIXME: Most targets have native widening multiplication.
333 It would be good to use that instead of a full wide multiply. */
334 /* 32x32->64 multiply. Marks inputs as dead. */
gen_mulu_i64_i32(TCGv a,TCGv b)335 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
336 {
337 TCGv_i64 tmp1 = tcg_temp_new_i64();
338 TCGv_i64 tmp2 = tcg_temp_new_i64();
339
340 tcg_gen_extu_i32_i64(tmp1, a);
341 dead_tmp(a);
342 tcg_gen_extu_i32_i64(tmp2, b);
343 dead_tmp(b);
344 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
345 return tmp1;
346 }
347
gen_muls_i64_i32(TCGv a,TCGv b)348 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
349 {
350 TCGv_i64 tmp1 = tcg_temp_new_i64();
351 TCGv_i64 tmp2 = tcg_temp_new_i64();
352
353 tcg_gen_ext_i32_i64(tmp1, a);
354 dead_tmp(a);
355 tcg_gen_ext_i32_i64(tmp2, b);
356 dead_tmp(b);
357 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
358 return tmp1;
359 }
360
361 /* Unsigned 32x32->64 multiply. */
gen_op_mull_T0_T1(void)362 static void gen_op_mull_T0_T1(void)
363 {
364 TCGv_i64 tmp1 = tcg_temp_new_i64();
365 TCGv_i64 tmp2 = tcg_temp_new_i64();
366
367 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
368 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
369 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
370 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
371 tcg_gen_shri_i64(tmp1, tmp1, 32);
372 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
373 }
374
375 /* Signed 32x32->64 multiply. */
gen_imull(TCGv a,TCGv b)376 static void gen_imull(TCGv a, TCGv b)
377 {
378 TCGv_i64 tmp1 = tcg_temp_new_i64();
379 TCGv_i64 tmp2 = tcg_temp_new_i64();
380
381 tcg_gen_ext_i32_i64(tmp1, a);
382 tcg_gen_ext_i32_i64(tmp2, b);
383 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
384 tcg_gen_trunc_i64_i32(a, tmp1);
385 tcg_gen_shri_i64(tmp1, tmp1, 32);
386 tcg_gen_trunc_i64_i32(b, tmp1);
387 }
388 #define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
389
390 /* Swap low and high halfwords. */
gen_swap_half(TCGv var)391 static void gen_swap_half(TCGv var)
392 {
393 TCGv tmp = new_tmp();
394 tcg_gen_shri_i32(tmp, var, 16);
395 tcg_gen_shli_i32(var, var, 16);
396 tcg_gen_or_i32(var, var, tmp);
397 dead_tmp(tmp);
398 }
399
400 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
401 tmp = (t0 ^ t1) & 0x8000;
402 t0 &= ~0x8000;
403 t1 &= ~0x8000;
404 t0 = (t0 + t1) ^ tmp;
405 */
406
gen_add16(TCGv t0,TCGv t1)407 static void gen_add16(TCGv t0, TCGv t1)
408 {
409 TCGv tmp = new_tmp();
410 tcg_gen_xor_i32(tmp, t0, t1);
411 tcg_gen_andi_i32(tmp, tmp, 0x8000);
412 tcg_gen_andi_i32(t0, t0, ~0x8000);
413 tcg_gen_andi_i32(t1, t1, ~0x8000);
414 tcg_gen_add_i32(t0, t0, t1);
415 tcg_gen_xor_i32(t0, t0, tmp);
416 dead_tmp(tmp);
417 dead_tmp(t1);
418 }
419
420 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
421
422 /* Set CF to the top bit of var. */
gen_set_CF_bit31(TCGv var)423 static void gen_set_CF_bit31(TCGv var)
424 {
425 TCGv tmp = new_tmp();
426 tcg_gen_shri_i32(tmp, var, 31);
427 gen_set_CF(tmp);
428 dead_tmp(tmp);
429 }
430
431 /* Set N and Z flags from var. */
gen_logic_CC(TCGv var)432 static inline void gen_logic_CC(TCGv var)
433 {
434 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
435 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
436 }
437
438 /* T0 += T1 + CF. */
gen_adc_T0_T1(void)439 static void gen_adc_T0_T1(void)
440 {
441 TCGv tmp;
442 gen_op_addl_T0_T1();
443 tmp = load_cpu_field(CF);
444 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
445 dead_tmp(tmp);
446 }
447
448 /* dest = T0 + T1 + CF. */
gen_add_carry(TCGv dest,TCGv t0,TCGv t1)449 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
450 {
451 TCGv tmp;
452 tcg_gen_add_i32(dest, t0, t1);
453 tmp = load_cpu_field(CF);
454 tcg_gen_add_i32(dest, dest, tmp);
455 dead_tmp(tmp);
456 }
457
458 /* dest = T0 - T1 + CF - 1. */
gen_sub_carry(TCGv dest,TCGv t0,TCGv t1)459 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
460 {
461 TCGv tmp;
462 tcg_gen_sub_i32(dest, t0, t1);
463 tmp = load_cpu_field(CF);
464 tcg_gen_add_i32(dest, dest, tmp);
465 tcg_gen_subi_i32(dest, dest, 1);
466 dead_tmp(tmp);
467 }
468
469 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
470 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
471
472 /* T0 &= ~T1. Clobbers T1. */
473 /* FIXME: Implement bic natively. */
tcg_gen_bic_i32(TCGv dest,TCGv t0,TCGv t1)474 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
475 {
476 TCGv tmp = new_tmp();
477 tcg_gen_not_i32(tmp, t1);
478 tcg_gen_and_i32(dest, t0, tmp);
479 dead_tmp(tmp);
480 }
gen_op_bicl_T0_T1(void)481 static inline void gen_op_bicl_T0_T1(void)
482 {
483 gen_op_notl_T1();
484 gen_op_andl_T0_T1();
485 }
486
487 /* FIXME: Implement this natively. */
488 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
489
490 /* FIXME: Implement this natively. */
tcg_gen_rori_i32(TCGv t0,TCGv t1,int i)491 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
492 {
493 TCGv tmp;
494
495 if (i == 0)
496 return;
497
498 tmp = new_tmp();
499 tcg_gen_shri_i32(tmp, t1, i);
500 tcg_gen_shli_i32(t1, t1, 32 - i);
501 tcg_gen_or_i32(t0, t1, tmp);
502 dead_tmp(tmp);
503 }
504
shifter_out_im(TCGv var,int shift)505 static void shifter_out_im(TCGv var, int shift)
506 {
507 TCGv tmp = new_tmp();
508 if (shift == 0) {
509 tcg_gen_andi_i32(tmp, var, 1);
510 } else {
511 tcg_gen_shri_i32(tmp, var, shift);
512 if (shift != 31)
513 tcg_gen_andi_i32(tmp, tmp, 1);
514 }
515 gen_set_CF(tmp);
516 dead_tmp(tmp);
517 }
518
519 /* Shift by immediate. Includes special handling for shift == 0. */
gen_arm_shift_im(TCGv var,int shiftop,int shift,int flags)520 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
521 {
522 switch (shiftop) {
523 case 0: /* LSL */
524 if (shift != 0) {
525 if (flags)
526 shifter_out_im(var, 32 - shift);
527 tcg_gen_shli_i32(var, var, shift);
528 }
529 break;
530 case 1: /* LSR */
531 if (shift == 0) {
532 if (flags) {
533 tcg_gen_shri_i32(var, var, 31);
534 gen_set_CF(var);
535 }
536 tcg_gen_movi_i32(var, 0);
537 } else {
538 if (flags)
539 shifter_out_im(var, shift - 1);
540 tcg_gen_shri_i32(var, var, shift);
541 }
542 break;
543 case 2: /* ASR */
544 if (shift == 0)
545 shift = 32;
546 if (flags)
547 shifter_out_im(var, shift - 1);
548 if (shift == 32)
549 shift = 31;
550 tcg_gen_sari_i32(var, var, shift);
551 break;
552 case 3: /* ROR/RRX */
553 if (shift != 0) {
554 if (flags)
555 shifter_out_im(var, shift - 1);
556 tcg_gen_rori_i32(var, var, shift); break;
557 } else {
558 TCGv tmp = load_cpu_field(CF);
559 if (flags)
560 shifter_out_im(var, 0);
561 tcg_gen_shri_i32(var, var, 1);
562 tcg_gen_shli_i32(tmp, tmp, 31);
563 tcg_gen_or_i32(var, var, tmp);
564 dead_tmp(tmp);
565 }
566 }
567 };
568
gen_arm_shift_reg(TCGv var,int shiftop,TCGv shift,int flags)569 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
570 TCGv shift, int flags)
571 {
572 if (flags) {
573 switch (shiftop) {
574 case 0: gen_helper_shl_cc(var, var, shift); break;
575 case 1: gen_helper_shr_cc(var, var, shift); break;
576 case 2: gen_helper_sar_cc(var, var, shift); break;
577 case 3: gen_helper_ror_cc(var, var, shift); break;
578 }
579 } else {
580 switch (shiftop) {
581 case 0: gen_helper_shl(var, var, shift); break;
582 case 1: gen_helper_shr(var, var, shift); break;
583 case 2: gen_helper_sar(var, var, shift); break;
584 case 3: gen_helper_ror(var, var, shift); break;
585 }
586 }
587 dead_tmp(shift);
588 }
589
590 #define PAS_OP(pfx) \
591 switch (op2) { \
592 case 0: gen_pas_helper(glue(pfx,add16)); break; \
593 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
594 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
595 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
596 case 4: gen_pas_helper(glue(pfx,add8)); break; \
597 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
598 }
gen_arm_parallel_addsub(int op1,int op2,TCGv a,TCGv b)599 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
600 {
601 TCGv_ptr tmp;
602
603 switch (op1) {
604 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
605 case 1:
606 tmp = tcg_temp_new_ptr();
607 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
608 PAS_OP(s)
609 break;
610 case 5:
611 tmp = tcg_temp_new_ptr();
612 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
613 PAS_OP(u)
614 break;
615 #undef gen_pas_helper
616 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
617 case 2:
618 PAS_OP(q);
619 break;
620 case 3:
621 PAS_OP(sh);
622 break;
623 case 6:
624 PAS_OP(uq);
625 break;
626 case 7:
627 PAS_OP(uh);
628 break;
629 #undef gen_pas_helper
630 }
631 }
632 #undef PAS_OP
633
634 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
635 #define PAS_OP(pfx) \
636 switch (op2) { \
637 case 0: gen_pas_helper(glue(pfx,add8)); break; \
638 case 1: gen_pas_helper(glue(pfx,add16)); break; \
639 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
640 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
641 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
642 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
643 }
gen_thumb2_parallel_addsub(int op1,int op2,TCGv a,TCGv b)644 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
645 {
646 TCGv_ptr tmp;
647
648 switch (op1) {
649 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
650 case 0:
651 tmp = tcg_temp_new_ptr();
652 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
653 PAS_OP(s)
654 break;
655 case 4:
656 tmp = tcg_temp_new_ptr();
657 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
658 PAS_OP(u)
659 break;
660 #undef gen_pas_helper
661 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
662 case 1:
663 PAS_OP(q);
664 break;
665 case 2:
666 PAS_OP(sh);
667 break;
668 case 5:
669 PAS_OP(uq);
670 break;
671 case 6:
672 PAS_OP(uh);
673 break;
674 #undef gen_pas_helper
675 }
676 }
677 #undef PAS_OP
678
gen_test_cc(int cc,int label)679 static void gen_test_cc(int cc, int label)
680 {
681 TCGv tmp;
682 TCGv tmp2;
683 int inv;
684
685 switch (cc) {
686 case 0: /* eq: Z */
687 tmp = load_cpu_field(ZF);
688 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
689 break;
690 case 1: /* ne: !Z */
691 tmp = load_cpu_field(ZF);
692 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
693 break;
694 case 2: /* cs: C */
695 tmp = load_cpu_field(CF);
696 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
697 break;
698 case 3: /* cc: !C */
699 tmp = load_cpu_field(CF);
700 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
701 break;
702 case 4: /* mi: N */
703 tmp = load_cpu_field(NF);
704 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
705 break;
706 case 5: /* pl: !N */
707 tmp = load_cpu_field(NF);
708 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
709 break;
710 case 6: /* vs: V */
711 tmp = load_cpu_field(VF);
712 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
713 break;
714 case 7: /* vc: !V */
715 tmp = load_cpu_field(VF);
716 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
717 break;
718 case 8: /* hi: C && !Z */
719 inv = gen_new_label();
720 tmp = load_cpu_field(CF);
721 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
722 dead_tmp(tmp);
723 tmp = load_cpu_field(ZF);
724 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
725 gen_set_label(inv);
726 break;
727 case 9: /* ls: !C || Z */
728 tmp = load_cpu_field(CF);
729 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
730 dead_tmp(tmp);
731 tmp = load_cpu_field(ZF);
732 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
733 break;
734 case 10: /* ge: N == V -> N ^ V == 0 */
735 tmp = load_cpu_field(VF);
736 tmp2 = load_cpu_field(NF);
737 tcg_gen_xor_i32(tmp, tmp, tmp2);
738 dead_tmp(tmp2);
739 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
740 break;
741 case 11: /* lt: N != V -> N ^ V != 0 */
742 tmp = load_cpu_field(VF);
743 tmp2 = load_cpu_field(NF);
744 tcg_gen_xor_i32(tmp, tmp, tmp2);
745 dead_tmp(tmp2);
746 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
747 break;
748 case 12: /* gt: !Z && N == V */
749 inv = gen_new_label();
750 tmp = load_cpu_field(ZF);
751 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
752 dead_tmp(tmp);
753 tmp = load_cpu_field(VF);
754 tmp2 = load_cpu_field(NF);
755 tcg_gen_xor_i32(tmp, tmp, tmp2);
756 dead_tmp(tmp2);
757 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
758 gen_set_label(inv);
759 break;
760 case 13: /* le: Z || N != V */
761 tmp = load_cpu_field(ZF);
762 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
763 dead_tmp(tmp);
764 tmp = load_cpu_field(VF);
765 tmp2 = load_cpu_field(NF);
766 tcg_gen_xor_i32(tmp, tmp, tmp2);
767 dead_tmp(tmp2);
768 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
769 break;
770 default:
771 fprintf(stderr, "Bad condition code 0x%x\n", cc);
772 abort();
773 }
774 dead_tmp(tmp);
775 }
776
777 static const uint8_t table_logic_cc[16] = {
778 1, /* and */
779 1, /* xor */
780 0, /* sub */
781 0, /* rsb */
782 0, /* add */
783 0, /* adc */
784 0, /* sbc */
785 0, /* rsc */
786 1, /* andl */
787 1, /* xorl */
788 0, /* cmp */
789 0, /* cmn */
790 1, /* orr */
791 1, /* mov */
792 1, /* bic */
793 1, /* mvn */
794 };
795
796 /* Set PC and Thumb state from an immediate address. */
gen_bx_im(DisasContext * s,uint32_t addr)797 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
798 {
799 TCGv tmp;
800
801 s->is_jmp = DISAS_UPDATE;
802 tmp = new_tmp();
803 if (s->thumb != (addr & 1)) {
804 tcg_gen_movi_i32(tmp, addr & 1);
805 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
806 }
807 tcg_gen_movi_i32(tmp, addr & ~1);
808 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
809 dead_tmp(tmp);
810 }
811
812 /* Set PC and Thumb state from var. var is marked as dead. */
gen_bx(DisasContext * s,TCGv var)813 static inline void gen_bx(DisasContext *s, TCGv var)
814 {
815 TCGv tmp;
816
817 s->is_jmp = DISAS_UPDATE;
818 tmp = new_tmp();
819 tcg_gen_andi_i32(tmp, var, 1);
820 store_cpu_field(tmp, thumb);
821 tcg_gen_andi_i32(var, var, ~1);
822 store_cpu_field(var, regs[15]);
823 }
824
825 /* TODO: This should be removed. Use gen_bx instead. */
gen_bx_T0(DisasContext * s)826 static inline void gen_bx_T0(DisasContext *s)
827 {
828 TCGv tmp = new_tmp();
829 tcg_gen_mov_i32(tmp, cpu_T[0]);
830 gen_bx(s, tmp);
831 }
832
833 /* Variant of store_reg which uses branch&exchange logic when storing
834 to r15 in ARM architecture v7 and above. The source must be a temporary
835 and will be marked as dead. */
store_reg_bx(CPUState * env,DisasContext * s,int reg,TCGv var)836 static inline void store_reg_bx(CPUState *env, DisasContext *s,
837 int reg, TCGv var)
838 {
839 if (reg == 15 && ENABLE_ARCH_7) {
840 gen_bx(s, var);
841 } else {
842 store_reg(s, reg, var);
843 }
844 }
845
gen_ld8s(TCGv addr,int index)846 static inline TCGv gen_ld8s(TCGv addr, int index)
847 {
848 TCGv tmp = new_tmp();
849 tcg_gen_qemu_ld8s(tmp, addr, index);
850 return tmp;
851 }
gen_ld8u(TCGv addr,int index)852 static inline TCGv gen_ld8u(TCGv addr, int index)
853 {
854 TCGv tmp = new_tmp();
855 tcg_gen_qemu_ld8u(tmp, addr, index);
856 return tmp;
857 }
gen_ld16s(TCGv addr,int index)858 static inline TCGv gen_ld16s(TCGv addr, int index)
859 {
860 TCGv tmp = new_tmp();
861 tcg_gen_qemu_ld16s(tmp, addr, index);
862 return tmp;
863 }
gen_ld16u(TCGv addr,int index)864 static inline TCGv gen_ld16u(TCGv addr, int index)
865 {
866 TCGv tmp = new_tmp();
867 tcg_gen_qemu_ld16u(tmp, addr, index);
868 return tmp;
869 }
gen_ld32(TCGv addr,int index)870 static inline TCGv gen_ld32(TCGv addr, int index)
871 {
872 TCGv tmp = new_tmp();
873 tcg_gen_qemu_ld32u(tmp, addr, index);
874 return tmp;
875 }
gen_st8(TCGv val,TCGv addr,int index)876 static inline void gen_st8(TCGv val, TCGv addr, int index)
877 {
878 tcg_gen_qemu_st8(val, addr, index);
879 dead_tmp(val);
880 }
gen_st16(TCGv val,TCGv addr,int index)881 static inline void gen_st16(TCGv val, TCGv addr, int index)
882 {
883 tcg_gen_qemu_st16(val, addr, index);
884 dead_tmp(val);
885 }
gen_st32(TCGv val,TCGv addr,int index)886 static inline void gen_st32(TCGv val, TCGv addr, int index)
887 {
888 tcg_gen_qemu_st32(val, addr, index);
889 dead_tmp(val);
890 }
891
gen_movl_T0_reg(DisasContext * s,int reg)892 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
893 {
894 load_reg_var(s, cpu_T[0], reg);
895 }
896
gen_movl_T1_reg(DisasContext * s,int reg)897 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
898 {
899 load_reg_var(s, cpu_T[1], reg);
900 }
901
gen_movl_T2_reg(DisasContext * s,int reg)902 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
903 {
904 load_reg_var(s, cpu_T[2], reg);
905 }
906
gen_set_pc_im(uint32_t val)907 static inline void gen_set_pc_im(uint32_t val)
908 {
909 TCGv tmp = new_tmp();
910 tcg_gen_movi_i32(tmp, val);
911 store_cpu_field(tmp, regs[15]);
912 }
913
gen_movl_reg_TN(DisasContext * s,int reg,int t)914 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
915 {
916 TCGv tmp;
917 if (reg == 15) {
918 tmp = new_tmp();
919 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
920 } else {
921 tmp = cpu_T[t];
922 }
923 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
924 if (reg == 15) {
925 dead_tmp(tmp);
926 s->is_jmp = DISAS_JUMP;
927 }
928 }
929
gen_movl_reg_T0(DisasContext * s,int reg)930 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
931 {
932 gen_movl_reg_TN(s, reg, 0);
933 }
934
gen_movl_reg_T1(DisasContext * s,int reg)935 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
936 {
937 gen_movl_reg_TN(s, reg, 1);
938 }
939
940 /* Force a TB lookup after an instruction that changes the CPU state. */
gen_lookup_tb(DisasContext * s)941 static inline void gen_lookup_tb(DisasContext *s)
942 {
943 gen_op_movl_T0_im(s->pc);
944 gen_movl_reg_T0(s, 15);
945 s->is_jmp = DISAS_UPDATE;
946 }
947
gen_add_data_offset(DisasContext * s,unsigned int insn,TCGv var)948 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
949 TCGv var)
950 {
951 int val, rm, shift, shiftop;
952 TCGv offset;
953
954 if (!(insn & (1 << 25))) {
955 /* immediate */
956 val = insn & 0xfff;
957 if (!(insn & (1 << 23)))
958 val = -val;
959 if (val != 0)
960 tcg_gen_addi_i32(var, var, val);
961 } else {
962 /* shift/register */
963 rm = (insn) & 0xf;
964 shift = (insn >> 7) & 0x1f;
965 shiftop = (insn >> 5) & 3;
966 offset = load_reg(s, rm);
967 gen_arm_shift_im(offset, shiftop, shift, 0);
968 if (!(insn & (1 << 23)))
969 tcg_gen_sub_i32(var, var, offset);
970 else
971 tcg_gen_add_i32(var, var, offset);
972 dead_tmp(offset);
973 }
974 }
975
gen_add_datah_offset(DisasContext * s,unsigned int insn,int extra,TCGv var)976 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
977 int extra, TCGv var)
978 {
979 int val, rm;
980 TCGv offset;
981
982 if (insn & (1 << 22)) {
983 /* immediate */
984 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
985 if (!(insn & (1 << 23)))
986 val = -val;
987 val += extra;
988 if (val != 0)
989 tcg_gen_addi_i32(var, var, val);
990 } else {
991 /* register */
992 if (extra)
993 tcg_gen_addi_i32(var, var, extra);
994 rm = (insn) & 0xf;
995 offset = load_reg(s, rm);
996 if (!(insn & (1 << 23)))
997 tcg_gen_sub_i32(var, var, offset);
998 else
999 tcg_gen_add_i32(var, var, offset);
1000 dead_tmp(offset);
1001 }
1002 }
1003
1004 #define VFP_OP2(name) \
1005 static inline void gen_vfp_##name(int dp) \
1006 { \
1007 if (dp) \
1008 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
1009 else \
1010 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1011 }
1012
1013 VFP_OP2(add)
VFP_OP2(sub)1014 VFP_OP2(sub)
1015 VFP_OP2(mul)
1016 VFP_OP2(div)
1017
1018 #undef VFP_OP2
1019
1020 static inline void gen_vfp_abs(int dp)
1021 {
1022 if (dp)
1023 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1024 else
1025 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1026 }
1027
gen_vfp_neg(int dp)1028 static inline void gen_vfp_neg(int dp)
1029 {
1030 if (dp)
1031 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1032 else
1033 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1034 }
1035
gen_vfp_sqrt(int dp)1036 static inline void gen_vfp_sqrt(int dp)
1037 {
1038 if (dp)
1039 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1040 else
1041 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1042 }
1043
gen_vfp_cmp(int dp)1044 static inline void gen_vfp_cmp(int dp)
1045 {
1046 if (dp)
1047 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1048 else
1049 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1050 }
1051
gen_vfp_cmpe(int dp)1052 static inline void gen_vfp_cmpe(int dp)
1053 {
1054 if (dp)
1055 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1056 else
1057 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1058 }
1059
gen_vfp_F1_ld0(int dp)1060 static inline void gen_vfp_F1_ld0(int dp)
1061 {
1062 if (dp)
1063 tcg_gen_movi_i64(cpu_F1d, 0);
1064 else
1065 tcg_gen_movi_i32(cpu_F1s, 0);
1066 }
1067
gen_vfp_uito(int dp)1068 static inline void gen_vfp_uito(int dp)
1069 {
1070 if (dp)
1071 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1072 else
1073 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1074 }
1075
gen_vfp_sito(int dp)1076 static inline void gen_vfp_sito(int dp)
1077 {
1078 if (dp)
1079 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1080 else
1081 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1082 }
1083
gen_vfp_toui(int dp)1084 static inline void gen_vfp_toui(int dp)
1085 {
1086 if (dp)
1087 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1088 else
1089 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1090 }
1091
gen_vfp_touiz(int dp)1092 static inline void gen_vfp_touiz(int dp)
1093 {
1094 if (dp)
1095 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1096 else
1097 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1098 }
1099
gen_vfp_tosi(int dp)1100 static inline void gen_vfp_tosi(int dp)
1101 {
1102 if (dp)
1103 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1104 else
1105 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1106 }
1107
gen_vfp_tosiz(int dp)1108 static inline void gen_vfp_tosiz(int dp)
1109 {
1110 if (dp)
1111 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1112 else
1113 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1114 }
1115
1116 #define VFP_GEN_FIX(name) \
1117 static inline void gen_vfp_##name(int dp, int shift) \
1118 { \
1119 if (dp) \
1120 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1121 else \
1122 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1123 }
1124 VFP_GEN_FIX(tosh)
VFP_GEN_FIX(tosl)1125 VFP_GEN_FIX(tosl)
1126 VFP_GEN_FIX(touh)
1127 VFP_GEN_FIX(toul)
1128 VFP_GEN_FIX(shto)
1129 VFP_GEN_FIX(slto)
1130 VFP_GEN_FIX(uhto)
1131 VFP_GEN_FIX(ulto)
1132 #undef VFP_GEN_FIX
1133
1134 static inline void gen_vfp_ld(DisasContext *s, int dp)
1135 {
1136 if (dp)
1137 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1138 else
1139 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1140 }
1141
gen_vfp_st(DisasContext * s,int dp)1142 static inline void gen_vfp_st(DisasContext *s, int dp)
1143 {
1144 if (dp)
1145 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1146 else
1147 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1148 }
1149
1150 static inline long
vfp_reg_offset(int dp,int reg)1151 vfp_reg_offset (int dp, int reg)
1152 {
1153 if (dp)
1154 return offsetof(CPUARMState, vfp.regs[reg]);
1155 else if (reg & 1) {
1156 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1157 + offsetof(CPU_DoubleU, l.upper);
1158 } else {
1159 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1160 + offsetof(CPU_DoubleU, l.lower);
1161 }
1162 }
1163
1164 /* Return the offset of a 32-bit piece of a NEON register.
1165 zero is the least significant end of the register. */
1166 static inline long
neon_reg_offset(int reg,int n)1167 neon_reg_offset (int reg, int n)
1168 {
1169 int sreg;
1170 sreg = reg * 2 + n;
1171 return vfp_reg_offset(0, sreg);
1172 }
1173
1174 /* FIXME: Remove these. */
1175 #define neon_T0 cpu_T[0]
1176 #define neon_T1 cpu_T[1]
1177 #define NEON_GET_REG(T, reg, n) \
1178 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1179 #define NEON_SET_REG(T, reg, n) \
1180 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1181
neon_load_reg(int reg,int pass)1182 static TCGv neon_load_reg(int reg, int pass)
1183 {
1184 TCGv tmp = new_tmp();
1185 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1186 return tmp;
1187 }
1188
neon_store_reg(int reg,int pass,TCGv var)1189 static void neon_store_reg(int reg, int pass, TCGv var)
1190 {
1191 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1192 dead_tmp(var);
1193 }
1194
neon_load_reg64(TCGv_i64 var,int reg)1195 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1196 {
1197 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1198 }
1199
neon_store_reg64(TCGv_i64 var,int reg)1200 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1201 {
1202 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1203 }
1204
1205 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1206 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1207 #define tcg_gen_st_f32 tcg_gen_st_i32
1208 #define tcg_gen_st_f64 tcg_gen_st_i64
1209
gen_mov_F0_vreg(int dp,int reg)1210 static inline void gen_mov_F0_vreg(int dp, int reg)
1211 {
1212 if (dp)
1213 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1214 else
1215 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1216 }
1217
gen_mov_F1_vreg(int dp,int reg)1218 static inline void gen_mov_F1_vreg(int dp, int reg)
1219 {
1220 if (dp)
1221 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1222 else
1223 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1224 }
1225
gen_mov_vreg_F0(int dp,int reg)1226 static inline void gen_mov_vreg_F0(int dp, int reg)
1227 {
1228 if (dp)
1229 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1230 else
1231 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1232 }
1233
1234 #define ARM_CP_RW_BIT (1 << 20)
1235
iwmmxt_load_reg(TCGv_i64 var,int reg)1236 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1237 {
1238 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1239 }
1240
iwmmxt_store_reg(TCGv_i64 var,int reg)1241 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1242 {
1243 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1244 }
1245
gen_op_iwmmxt_movl_wCx_T0(int reg)1246 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1247 {
1248 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1249 }
1250
gen_op_iwmmxt_movl_T0_wCx(int reg)1251 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1252 {
1253 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1254 }
1255
gen_op_iwmmxt_movl_T1_wCx(int reg)1256 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1257 {
1258 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1259 }
1260
gen_op_iwmmxt_movq_wRn_M0(int rn)1261 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1262 {
1263 iwmmxt_store_reg(cpu_M0, rn);
1264 }
1265
gen_op_iwmmxt_movq_M0_wRn(int rn)1266 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1267 {
1268 iwmmxt_load_reg(cpu_M0, rn);
1269 }
1270
gen_op_iwmmxt_orq_M0_wRn(int rn)1271 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1272 {
1273 iwmmxt_load_reg(cpu_V1, rn);
1274 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1275 }
1276
gen_op_iwmmxt_andq_M0_wRn(int rn)1277 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1278 {
1279 iwmmxt_load_reg(cpu_V1, rn);
1280 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1281 }
1282
gen_op_iwmmxt_xorq_M0_wRn(int rn)1283 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1284 {
1285 iwmmxt_load_reg(cpu_V1, rn);
1286 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1287 }
1288
1289 #define IWMMXT_OP(name) \
1290 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1291 { \
1292 iwmmxt_load_reg(cpu_V1, rn); \
1293 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1294 }
1295
1296 #define IWMMXT_OP_ENV(name) \
1297 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1298 { \
1299 iwmmxt_load_reg(cpu_V1, rn); \
1300 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1301 }
1302
1303 #define IWMMXT_OP_ENV_SIZE(name) \
1304 IWMMXT_OP_ENV(name##b) \
1305 IWMMXT_OP_ENV(name##w) \
1306 IWMMXT_OP_ENV(name##l)
1307
1308 #define IWMMXT_OP_ENV1(name) \
1309 static inline void gen_op_iwmmxt_##name##_M0(void) \
1310 { \
1311 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1312 }
1313
1314 IWMMXT_OP(maddsq)
IWMMXT_OP(madduq)1315 IWMMXT_OP(madduq)
1316 IWMMXT_OP(sadb)
1317 IWMMXT_OP(sadw)
1318 IWMMXT_OP(mulslw)
1319 IWMMXT_OP(mulshw)
1320 IWMMXT_OP(mululw)
1321 IWMMXT_OP(muluhw)
1322 IWMMXT_OP(macsw)
1323 IWMMXT_OP(macuw)
1324
1325 IWMMXT_OP_ENV_SIZE(unpackl)
1326 IWMMXT_OP_ENV_SIZE(unpackh)
1327
1328 IWMMXT_OP_ENV1(unpacklub)
1329 IWMMXT_OP_ENV1(unpackluw)
1330 IWMMXT_OP_ENV1(unpacklul)
1331 IWMMXT_OP_ENV1(unpackhub)
1332 IWMMXT_OP_ENV1(unpackhuw)
1333 IWMMXT_OP_ENV1(unpackhul)
1334 IWMMXT_OP_ENV1(unpacklsb)
1335 IWMMXT_OP_ENV1(unpacklsw)
1336 IWMMXT_OP_ENV1(unpacklsl)
1337 IWMMXT_OP_ENV1(unpackhsb)
1338 IWMMXT_OP_ENV1(unpackhsw)
1339 IWMMXT_OP_ENV1(unpackhsl)
1340
1341 IWMMXT_OP_ENV_SIZE(cmpeq)
1342 IWMMXT_OP_ENV_SIZE(cmpgtu)
1343 IWMMXT_OP_ENV_SIZE(cmpgts)
1344
1345 IWMMXT_OP_ENV_SIZE(mins)
1346 IWMMXT_OP_ENV_SIZE(minu)
1347 IWMMXT_OP_ENV_SIZE(maxs)
1348 IWMMXT_OP_ENV_SIZE(maxu)
1349
1350 IWMMXT_OP_ENV_SIZE(subn)
1351 IWMMXT_OP_ENV_SIZE(addn)
1352 IWMMXT_OP_ENV_SIZE(subu)
1353 IWMMXT_OP_ENV_SIZE(addu)
1354 IWMMXT_OP_ENV_SIZE(subs)
1355 IWMMXT_OP_ENV_SIZE(adds)
1356
1357 IWMMXT_OP_ENV(avgb0)
1358 IWMMXT_OP_ENV(avgb1)
1359 IWMMXT_OP_ENV(avgw0)
1360 IWMMXT_OP_ENV(avgw1)
1361
1362 IWMMXT_OP(msadb)
1363
1364 IWMMXT_OP_ENV(packuw)
1365 IWMMXT_OP_ENV(packul)
1366 IWMMXT_OP_ENV(packuq)
1367 IWMMXT_OP_ENV(packsw)
1368 IWMMXT_OP_ENV(packsl)
1369 IWMMXT_OP_ENV(packsq)
1370
1371 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1372 {
1373 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1374 }
1375
gen_op_iwmmxt_muladdsw_M0_T0_T1(void)1376 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1377 {
1378 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1379 }
1380
gen_op_iwmmxt_muladdswl_M0_T0_T1(void)1381 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1382 {
1383 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1384 }
1385
gen_op_iwmmxt_align_M0_T0_wRn(int rn)1386 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1387 {
1388 iwmmxt_load_reg(cpu_V1, rn);
1389 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1390 }
1391
gen_op_iwmmxt_insr_M0_T0_T1(int shift)1392 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1393 {
1394 TCGv tmp = tcg_const_i32(shift);
1395 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1396 }
1397
gen_op_iwmmxt_extrsb_T0_M0(int shift)1398 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1399 {
1400 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1401 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1402 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1403 }
1404
gen_op_iwmmxt_extrsw_T0_M0(int shift)1405 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1406 {
1407 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1408 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1409 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1410 }
1411
gen_op_iwmmxt_extru_T0_M0(int shift,uint32_t mask)1412 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1413 {
1414 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1415 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1416 if (mask != ~0u)
1417 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1418 }
1419
gen_op_iwmmxt_set_mup(void)1420 static void gen_op_iwmmxt_set_mup(void)
1421 {
1422 TCGv tmp;
1423 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1424 tcg_gen_ori_i32(tmp, tmp, 2);
1425 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1426 }
1427
gen_op_iwmmxt_set_cup(void)1428 static void gen_op_iwmmxt_set_cup(void)
1429 {
1430 TCGv tmp;
1431 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1432 tcg_gen_ori_i32(tmp, tmp, 1);
1433 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1434 }
1435
gen_op_iwmmxt_setpsr_nz(void)1436 static void gen_op_iwmmxt_setpsr_nz(void)
1437 {
1438 TCGv tmp = new_tmp();
1439 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1440 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1441 }
1442
gen_op_iwmmxt_addl_M0_wRn(int rn)1443 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1444 {
1445 iwmmxt_load_reg(cpu_V1, rn);
1446 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1447 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1448 }
1449
1450
gen_iwmmxt_movl_T0_T1_wRn(int rn)1451 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1452 {
1453 iwmmxt_load_reg(cpu_V0, rn);
1454 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1455 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1456 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1457 }
1458
gen_iwmmxt_movl_wRn_T0_T1(int rn)1459 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1460 {
1461 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1462 iwmmxt_store_reg(cpu_V0, rn);
1463 }
1464
gen_iwmmxt_address(DisasContext * s,uint32_t insn)1465 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1466 {
1467 int rd;
1468 uint32_t offset;
1469
1470 rd = (insn >> 16) & 0xf;
1471 gen_movl_T1_reg(s, rd);
1472
1473 offset = (insn & 0xff) << ((insn >> 7) & 2);
1474 if (insn & (1 << 24)) {
1475 /* Pre indexed */
1476 if (insn & (1 << 23))
1477 gen_op_addl_T1_im(offset);
1478 else
1479 gen_op_addl_T1_im(-offset);
1480
1481 if (insn & (1 << 21))
1482 gen_movl_reg_T1(s, rd);
1483 } else if (insn & (1 << 21)) {
1484 /* Post indexed */
1485 if (insn & (1 << 23))
1486 gen_op_movl_T0_im(offset);
1487 else
1488 gen_op_movl_T0_im(- offset);
1489 gen_op_addl_T0_T1();
1490 gen_movl_reg_T0(s, rd);
1491 } else if (!(insn & (1 << 23)))
1492 return 1;
1493 return 0;
1494 }
1495
gen_iwmmxt_shift(uint32_t insn,uint32_t mask)1496 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1497 {
1498 int rd = (insn >> 0) & 0xf;
1499
1500 if (insn & (1 << 8))
1501 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1502 return 1;
1503 else
1504 gen_op_iwmmxt_movl_T0_wCx(rd);
1505 else
1506 gen_iwmmxt_movl_T0_T1_wRn(rd);
1507
1508 gen_op_movl_T1_im(mask);
1509 gen_op_andl_T0_T1();
1510 return 0;
1511 }
1512
1513 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1514 (ie. an undefined instruction). */
disas_iwmmxt_insn(CPUState * env,DisasContext * s,uint32_t insn)1515 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1516 {
1517 int rd, wrd;
1518 int rdhi, rdlo, rd0, rd1, i;
1519 TCGv tmp;
1520
1521 if ((insn & 0x0e000e00) == 0x0c000000) {
1522 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1523 wrd = insn & 0xf;
1524 rdlo = (insn >> 12) & 0xf;
1525 rdhi = (insn >> 16) & 0xf;
1526 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1527 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1528 gen_movl_reg_T0(s, rdlo);
1529 gen_movl_reg_T1(s, rdhi);
1530 } else { /* TMCRR */
1531 gen_movl_T0_reg(s, rdlo);
1532 gen_movl_T1_reg(s, rdhi);
1533 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1534 gen_op_iwmmxt_set_mup();
1535 }
1536 return 0;
1537 }
1538
1539 wrd = (insn >> 12) & 0xf;
1540 if (gen_iwmmxt_address(s, insn))
1541 return 1;
1542 if (insn & ARM_CP_RW_BIT) {
1543 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1544 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1545 tcg_gen_mov_i32(cpu_T[0], tmp);
1546 dead_tmp(tmp);
1547 gen_op_iwmmxt_movl_wCx_T0(wrd);
1548 } else {
1549 i = 1;
1550 if (insn & (1 << 8)) {
1551 if (insn & (1 << 22)) { /* WLDRD */
1552 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1553 i = 0;
1554 } else { /* WLDRW wRd */
1555 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1556 }
1557 } else {
1558 if (insn & (1 << 22)) { /* WLDRH */
1559 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1560 } else { /* WLDRB */
1561 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1562 }
1563 }
1564 if (i) {
1565 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1566 dead_tmp(tmp);
1567 }
1568 gen_op_iwmmxt_movq_wRn_M0(wrd);
1569 }
1570 } else {
1571 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1572 gen_op_iwmmxt_movl_T0_wCx(wrd);
1573 tmp = new_tmp();
1574 tcg_gen_mov_i32(tmp, cpu_T[0]);
1575 gen_st32(tmp, cpu_T[1], IS_USER(s));
1576 } else {
1577 gen_op_iwmmxt_movq_M0_wRn(wrd);
1578 tmp = new_tmp();
1579 if (insn & (1 << 8)) {
1580 if (insn & (1 << 22)) { /* WSTRD */
1581 dead_tmp(tmp);
1582 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1583 } else { /* WSTRW wRd */
1584 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1585 gen_st32(tmp, cpu_T[1], IS_USER(s));
1586 }
1587 } else {
1588 if (insn & (1 << 22)) { /* WSTRH */
1589 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1590 gen_st16(tmp, cpu_T[1], IS_USER(s));
1591 } else { /* WSTRB */
1592 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1593 gen_st8(tmp, cpu_T[1], IS_USER(s));
1594 }
1595 }
1596 }
1597 }
1598 return 0;
1599 }
1600
1601 if ((insn & 0x0f000000) != 0x0e000000)
1602 return 1;
1603
1604 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1605 case 0x000: /* WOR */
1606 wrd = (insn >> 12) & 0xf;
1607 rd0 = (insn >> 0) & 0xf;
1608 rd1 = (insn >> 16) & 0xf;
1609 gen_op_iwmmxt_movq_M0_wRn(rd0);
1610 gen_op_iwmmxt_orq_M0_wRn(rd1);
1611 gen_op_iwmmxt_setpsr_nz();
1612 gen_op_iwmmxt_movq_wRn_M0(wrd);
1613 gen_op_iwmmxt_set_mup();
1614 gen_op_iwmmxt_set_cup();
1615 break;
1616 case 0x011: /* TMCR */
1617 if (insn & 0xf)
1618 return 1;
1619 rd = (insn >> 12) & 0xf;
1620 wrd = (insn >> 16) & 0xf;
1621 switch (wrd) {
1622 case ARM_IWMMXT_wCID:
1623 case ARM_IWMMXT_wCASF:
1624 break;
1625 case ARM_IWMMXT_wCon:
1626 gen_op_iwmmxt_set_cup();
1627 /* Fall through. */
1628 case ARM_IWMMXT_wCSSF:
1629 gen_op_iwmmxt_movl_T0_wCx(wrd);
1630 gen_movl_T1_reg(s, rd);
1631 gen_op_bicl_T0_T1();
1632 gen_op_iwmmxt_movl_wCx_T0(wrd);
1633 break;
1634 case ARM_IWMMXT_wCGR0:
1635 case ARM_IWMMXT_wCGR1:
1636 case ARM_IWMMXT_wCGR2:
1637 case ARM_IWMMXT_wCGR3:
1638 gen_op_iwmmxt_set_cup();
1639 gen_movl_reg_T0(s, rd);
1640 gen_op_iwmmxt_movl_wCx_T0(wrd);
1641 break;
1642 default:
1643 return 1;
1644 }
1645 break;
1646 case 0x100: /* WXOR */
1647 wrd = (insn >> 12) & 0xf;
1648 rd0 = (insn >> 0) & 0xf;
1649 rd1 = (insn >> 16) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0);
1651 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1652 gen_op_iwmmxt_setpsr_nz();
1653 gen_op_iwmmxt_movq_wRn_M0(wrd);
1654 gen_op_iwmmxt_set_mup();
1655 gen_op_iwmmxt_set_cup();
1656 break;
1657 case 0x111: /* TMRC */
1658 if (insn & 0xf)
1659 return 1;
1660 rd = (insn >> 12) & 0xf;
1661 wrd = (insn >> 16) & 0xf;
1662 gen_op_iwmmxt_movl_T0_wCx(wrd);
1663 gen_movl_reg_T0(s, rd);
1664 break;
1665 case 0x300: /* WANDN */
1666 wrd = (insn >> 12) & 0xf;
1667 rd0 = (insn >> 0) & 0xf;
1668 rd1 = (insn >> 16) & 0xf;
1669 gen_op_iwmmxt_movq_M0_wRn(rd0);
1670 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1671 gen_op_iwmmxt_andq_M0_wRn(rd1);
1672 gen_op_iwmmxt_setpsr_nz();
1673 gen_op_iwmmxt_movq_wRn_M0(wrd);
1674 gen_op_iwmmxt_set_mup();
1675 gen_op_iwmmxt_set_cup();
1676 break;
1677 case 0x200: /* WAND */
1678 wrd = (insn >> 12) & 0xf;
1679 rd0 = (insn >> 0) & 0xf;
1680 rd1 = (insn >> 16) & 0xf;
1681 gen_op_iwmmxt_movq_M0_wRn(rd0);
1682 gen_op_iwmmxt_andq_M0_wRn(rd1);
1683 gen_op_iwmmxt_setpsr_nz();
1684 gen_op_iwmmxt_movq_wRn_M0(wrd);
1685 gen_op_iwmmxt_set_mup();
1686 gen_op_iwmmxt_set_cup();
1687 break;
1688 case 0x810: case 0xa10: /* WMADD */
1689 wrd = (insn >> 12) & 0xf;
1690 rd0 = (insn >> 0) & 0xf;
1691 rd1 = (insn >> 16) & 0xf;
1692 gen_op_iwmmxt_movq_M0_wRn(rd0);
1693 if (insn & (1 << 21))
1694 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1695 else
1696 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1697 gen_op_iwmmxt_movq_wRn_M0(wrd);
1698 gen_op_iwmmxt_set_mup();
1699 break;
1700 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1701 wrd = (insn >> 12) & 0xf;
1702 rd0 = (insn >> 16) & 0xf;
1703 rd1 = (insn >> 0) & 0xf;
1704 gen_op_iwmmxt_movq_M0_wRn(rd0);
1705 switch ((insn >> 22) & 3) {
1706 case 0:
1707 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1708 break;
1709 case 1:
1710 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1711 break;
1712 case 2:
1713 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1714 break;
1715 case 3:
1716 return 1;
1717 }
1718 gen_op_iwmmxt_movq_wRn_M0(wrd);
1719 gen_op_iwmmxt_set_mup();
1720 gen_op_iwmmxt_set_cup();
1721 break;
1722 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1723 wrd = (insn >> 12) & 0xf;
1724 rd0 = (insn >> 16) & 0xf;
1725 rd1 = (insn >> 0) & 0xf;
1726 gen_op_iwmmxt_movq_M0_wRn(rd0);
1727 switch ((insn >> 22) & 3) {
1728 case 0:
1729 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1730 break;
1731 case 1:
1732 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1733 break;
1734 case 2:
1735 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1736 break;
1737 case 3:
1738 return 1;
1739 }
1740 gen_op_iwmmxt_movq_wRn_M0(wrd);
1741 gen_op_iwmmxt_set_mup();
1742 gen_op_iwmmxt_set_cup();
1743 break;
1744 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1745 wrd = (insn >> 12) & 0xf;
1746 rd0 = (insn >> 16) & 0xf;
1747 rd1 = (insn >> 0) & 0xf;
1748 gen_op_iwmmxt_movq_M0_wRn(rd0);
1749 if (insn & (1 << 22))
1750 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1751 else
1752 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1753 if (!(insn & (1 << 20)))
1754 gen_op_iwmmxt_addl_M0_wRn(wrd);
1755 gen_op_iwmmxt_movq_wRn_M0(wrd);
1756 gen_op_iwmmxt_set_mup();
1757 break;
1758 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1759 wrd = (insn >> 12) & 0xf;
1760 rd0 = (insn >> 16) & 0xf;
1761 rd1 = (insn >> 0) & 0xf;
1762 gen_op_iwmmxt_movq_M0_wRn(rd0);
1763 if (insn & (1 << 21)) {
1764 if (insn & (1 << 20))
1765 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1766 else
1767 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1768 } else {
1769 if (insn & (1 << 20))
1770 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1771 else
1772 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1773 }
1774 gen_op_iwmmxt_movq_wRn_M0(wrd);
1775 gen_op_iwmmxt_set_mup();
1776 break;
1777 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1778 wrd = (insn >> 12) & 0xf;
1779 rd0 = (insn >> 16) & 0xf;
1780 rd1 = (insn >> 0) & 0xf;
1781 gen_op_iwmmxt_movq_M0_wRn(rd0);
1782 if (insn & (1 << 21))
1783 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1784 else
1785 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1786 if (!(insn & (1 << 20))) {
1787 iwmmxt_load_reg(cpu_V1, wrd);
1788 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1789 }
1790 gen_op_iwmmxt_movq_wRn_M0(wrd);
1791 gen_op_iwmmxt_set_mup();
1792 break;
1793 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1794 wrd = (insn >> 12) & 0xf;
1795 rd0 = (insn >> 16) & 0xf;
1796 rd1 = (insn >> 0) & 0xf;
1797 gen_op_iwmmxt_movq_M0_wRn(rd0);
1798 switch ((insn >> 22) & 3) {
1799 case 0:
1800 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1801 break;
1802 case 1:
1803 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1804 break;
1805 case 2:
1806 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1807 break;
1808 case 3:
1809 return 1;
1810 }
1811 gen_op_iwmmxt_movq_wRn_M0(wrd);
1812 gen_op_iwmmxt_set_mup();
1813 gen_op_iwmmxt_set_cup();
1814 break;
1815 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1816 wrd = (insn >> 12) & 0xf;
1817 rd0 = (insn >> 16) & 0xf;
1818 rd1 = (insn >> 0) & 0xf;
1819 gen_op_iwmmxt_movq_M0_wRn(rd0);
1820 if (insn & (1 << 22)) {
1821 if (insn & (1 << 20))
1822 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1823 else
1824 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1825 } else {
1826 if (insn & (1 << 20))
1827 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1828 else
1829 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1830 }
1831 gen_op_iwmmxt_movq_wRn_M0(wrd);
1832 gen_op_iwmmxt_set_mup();
1833 gen_op_iwmmxt_set_cup();
1834 break;
1835 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1836 wrd = (insn >> 12) & 0xf;
1837 rd0 = (insn >> 16) & 0xf;
1838 rd1 = (insn >> 0) & 0xf;
1839 gen_op_iwmmxt_movq_M0_wRn(rd0);
1840 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1841 gen_op_movl_T1_im(7);
1842 gen_op_andl_T0_T1();
1843 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1844 gen_op_iwmmxt_movq_wRn_M0(wrd);
1845 gen_op_iwmmxt_set_mup();
1846 break;
1847 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1848 rd = (insn >> 12) & 0xf;
1849 wrd = (insn >> 16) & 0xf;
1850 gen_movl_T0_reg(s, rd);
1851 gen_op_iwmmxt_movq_M0_wRn(wrd);
1852 switch ((insn >> 6) & 3) {
1853 case 0:
1854 gen_op_movl_T1_im(0xff);
1855 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1856 break;
1857 case 1:
1858 gen_op_movl_T1_im(0xffff);
1859 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1860 break;
1861 case 2:
1862 gen_op_movl_T1_im(0xffffffff);
1863 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1864 break;
1865 case 3:
1866 return 1;
1867 }
1868 gen_op_iwmmxt_movq_wRn_M0(wrd);
1869 gen_op_iwmmxt_set_mup();
1870 break;
1871 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1872 rd = (insn >> 12) & 0xf;
1873 wrd = (insn >> 16) & 0xf;
1874 if (rd == 15)
1875 return 1;
1876 gen_op_iwmmxt_movq_M0_wRn(wrd);
1877 switch ((insn >> 22) & 3) {
1878 case 0:
1879 if (insn & 8)
1880 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1881 else {
1882 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1883 }
1884 break;
1885 case 1:
1886 if (insn & 8)
1887 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1888 else {
1889 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1890 }
1891 break;
1892 case 2:
1893 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1894 break;
1895 case 3:
1896 return 1;
1897 }
1898 gen_movl_reg_T0(s, rd);
1899 break;
1900 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1901 if ((insn & 0x000ff008) != 0x0003f000)
1902 return 1;
1903 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1904 switch ((insn >> 22) & 3) {
1905 case 0:
1906 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1907 break;
1908 case 1:
1909 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1910 break;
1911 case 2:
1912 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1913 break;
1914 case 3:
1915 return 1;
1916 }
1917 gen_op_shll_T1_im(28);
1918 gen_set_nzcv(cpu_T[1]);
1919 break;
1920 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1921 rd = (insn >> 12) & 0xf;
1922 wrd = (insn >> 16) & 0xf;
1923 gen_movl_T0_reg(s, rd);
1924 switch ((insn >> 6) & 3) {
1925 case 0:
1926 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1927 break;
1928 case 1:
1929 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1930 break;
1931 case 2:
1932 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1933 break;
1934 case 3:
1935 return 1;
1936 }
1937 gen_op_iwmmxt_movq_wRn_M0(wrd);
1938 gen_op_iwmmxt_set_mup();
1939 break;
1940 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1941 if ((insn & 0x000ff00f) != 0x0003f000)
1942 return 1;
1943 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1944 switch ((insn >> 22) & 3) {
1945 case 0:
1946 for (i = 0; i < 7; i ++) {
1947 gen_op_shll_T1_im(4);
1948 gen_op_andl_T0_T1();
1949 }
1950 break;
1951 case 1:
1952 for (i = 0; i < 3; i ++) {
1953 gen_op_shll_T1_im(8);
1954 gen_op_andl_T0_T1();
1955 }
1956 break;
1957 case 2:
1958 gen_op_shll_T1_im(16);
1959 gen_op_andl_T0_T1();
1960 break;
1961 case 3:
1962 return 1;
1963 }
1964 gen_set_nzcv(cpu_T[0]);
1965 break;
1966 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1967 wrd = (insn >> 12) & 0xf;
1968 rd0 = (insn >> 16) & 0xf;
1969 gen_op_iwmmxt_movq_M0_wRn(rd0);
1970 switch ((insn >> 22) & 3) {
1971 case 0:
1972 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1973 break;
1974 case 1:
1975 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1976 break;
1977 case 2:
1978 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1979 break;
1980 case 3:
1981 return 1;
1982 }
1983 gen_op_iwmmxt_movq_wRn_M0(wrd);
1984 gen_op_iwmmxt_set_mup();
1985 break;
1986 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1987 if ((insn & 0x000ff00f) != 0x0003f000)
1988 return 1;
1989 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1990 switch ((insn >> 22) & 3) {
1991 case 0:
1992 for (i = 0; i < 7; i ++) {
1993 gen_op_shll_T1_im(4);
1994 gen_op_orl_T0_T1();
1995 }
1996 break;
1997 case 1:
1998 for (i = 0; i < 3; i ++) {
1999 gen_op_shll_T1_im(8);
2000 gen_op_orl_T0_T1();
2001 }
2002 break;
2003 case 2:
2004 gen_op_shll_T1_im(16);
2005 gen_op_orl_T0_T1();
2006 break;
2007 case 3:
2008 return 1;
2009 }
2010 gen_set_nzcv(cpu_T[0]);
2011 break;
2012 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2013 rd = (insn >> 12) & 0xf;
2014 rd0 = (insn >> 16) & 0xf;
2015 if ((insn & 0xf) != 0)
2016 return 1;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0);
2018 switch ((insn >> 22) & 3) {
2019 case 0:
2020 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2021 break;
2022 case 1:
2023 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2024 break;
2025 case 2:
2026 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2027 break;
2028 case 3:
2029 return 1;
2030 }
2031 gen_movl_reg_T0(s, rd);
2032 break;
2033 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2034 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2035 wrd = (insn >> 12) & 0xf;
2036 rd0 = (insn >> 16) & 0xf;
2037 rd1 = (insn >> 0) & 0xf;
2038 gen_op_iwmmxt_movq_M0_wRn(rd0);
2039 switch ((insn >> 22) & 3) {
2040 case 0:
2041 if (insn & (1 << 21))
2042 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2043 else
2044 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2045 break;
2046 case 1:
2047 if (insn & (1 << 21))
2048 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2049 else
2050 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2051 break;
2052 case 2:
2053 if (insn & (1 << 21))
2054 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2055 else
2056 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2057 break;
2058 case 3:
2059 return 1;
2060 }
2061 gen_op_iwmmxt_movq_wRn_M0(wrd);
2062 gen_op_iwmmxt_set_mup();
2063 gen_op_iwmmxt_set_cup();
2064 break;
2065 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2066 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2067 wrd = (insn >> 12) & 0xf;
2068 rd0 = (insn >> 16) & 0xf;
2069 gen_op_iwmmxt_movq_M0_wRn(rd0);
2070 switch ((insn >> 22) & 3) {
2071 case 0:
2072 if (insn & (1 << 21))
2073 gen_op_iwmmxt_unpacklsb_M0();
2074 else
2075 gen_op_iwmmxt_unpacklub_M0();
2076 break;
2077 case 1:
2078 if (insn & (1 << 21))
2079 gen_op_iwmmxt_unpacklsw_M0();
2080 else
2081 gen_op_iwmmxt_unpackluw_M0();
2082 break;
2083 case 2:
2084 if (insn & (1 << 21))
2085 gen_op_iwmmxt_unpacklsl_M0();
2086 else
2087 gen_op_iwmmxt_unpacklul_M0();
2088 break;
2089 case 3:
2090 return 1;
2091 }
2092 gen_op_iwmmxt_movq_wRn_M0(wrd);
2093 gen_op_iwmmxt_set_mup();
2094 gen_op_iwmmxt_set_cup();
2095 break;
2096 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2097 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2098 wrd = (insn >> 12) & 0xf;
2099 rd0 = (insn >> 16) & 0xf;
2100 gen_op_iwmmxt_movq_M0_wRn(rd0);
2101 switch ((insn >> 22) & 3) {
2102 case 0:
2103 if (insn & (1 << 21))
2104 gen_op_iwmmxt_unpackhsb_M0();
2105 else
2106 gen_op_iwmmxt_unpackhub_M0();
2107 break;
2108 case 1:
2109 if (insn & (1 << 21))
2110 gen_op_iwmmxt_unpackhsw_M0();
2111 else
2112 gen_op_iwmmxt_unpackhuw_M0();
2113 break;
2114 case 2:
2115 if (insn & (1 << 21))
2116 gen_op_iwmmxt_unpackhsl_M0();
2117 else
2118 gen_op_iwmmxt_unpackhul_M0();
2119 break;
2120 case 3:
2121 return 1;
2122 }
2123 gen_op_iwmmxt_movq_wRn_M0(wrd);
2124 gen_op_iwmmxt_set_mup();
2125 gen_op_iwmmxt_set_cup();
2126 break;
2127 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2128 case 0x214: case 0x614: case 0xa14: case 0xe14:
2129 wrd = (insn >> 12) & 0xf;
2130 rd0 = (insn >> 16) & 0xf;
2131 gen_op_iwmmxt_movq_M0_wRn(rd0);
2132 if (gen_iwmmxt_shift(insn, 0xff))
2133 return 1;
2134 switch ((insn >> 22) & 3) {
2135 case 0:
2136 return 1;
2137 case 1:
2138 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2139 break;
2140 case 2:
2141 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2142 break;
2143 case 3:
2144 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2145 break;
2146 }
2147 gen_op_iwmmxt_movq_wRn_M0(wrd);
2148 gen_op_iwmmxt_set_mup();
2149 gen_op_iwmmxt_set_cup();
2150 break;
2151 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2152 case 0x014: case 0x414: case 0x814: case 0xc14:
2153 wrd = (insn >> 12) & 0xf;
2154 rd0 = (insn >> 16) & 0xf;
2155 gen_op_iwmmxt_movq_M0_wRn(rd0);
2156 if (gen_iwmmxt_shift(insn, 0xff))
2157 return 1;
2158 switch ((insn >> 22) & 3) {
2159 case 0:
2160 return 1;
2161 case 1:
2162 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2163 break;
2164 case 2:
2165 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2166 break;
2167 case 3:
2168 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2169 break;
2170 }
2171 gen_op_iwmmxt_movq_wRn_M0(wrd);
2172 gen_op_iwmmxt_set_mup();
2173 gen_op_iwmmxt_set_cup();
2174 break;
2175 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2176 case 0x114: case 0x514: case 0x914: case 0xd14:
2177 wrd = (insn >> 12) & 0xf;
2178 rd0 = (insn >> 16) & 0xf;
2179 gen_op_iwmmxt_movq_M0_wRn(rd0);
2180 if (gen_iwmmxt_shift(insn, 0xff))
2181 return 1;
2182 switch ((insn >> 22) & 3) {
2183 case 0:
2184 return 1;
2185 case 1:
2186 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2187 break;
2188 case 2:
2189 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2190 break;
2191 case 3:
2192 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2193 break;
2194 }
2195 gen_op_iwmmxt_movq_wRn_M0(wrd);
2196 gen_op_iwmmxt_set_mup();
2197 gen_op_iwmmxt_set_cup();
2198 break;
2199 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2200 case 0x314: case 0x714: case 0xb14: case 0xf14:
2201 wrd = (insn >> 12) & 0xf;
2202 rd0 = (insn >> 16) & 0xf;
2203 gen_op_iwmmxt_movq_M0_wRn(rd0);
2204 switch ((insn >> 22) & 3) {
2205 case 0:
2206 return 1;
2207 case 1:
2208 if (gen_iwmmxt_shift(insn, 0xf))
2209 return 1;
2210 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2211 break;
2212 case 2:
2213 if (gen_iwmmxt_shift(insn, 0x1f))
2214 return 1;
2215 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2216 break;
2217 case 3:
2218 if (gen_iwmmxt_shift(insn, 0x3f))
2219 return 1;
2220 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2221 break;
2222 }
2223 gen_op_iwmmxt_movq_wRn_M0(wrd);
2224 gen_op_iwmmxt_set_mup();
2225 gen_op_iwmmxt_set_cup();
2226 break;
2227 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2228 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2229 wrd = (insn >> 12) & 0xf;
2230 rd0 = (insn >> 16) & 0xf;
2231 rd1 = (insn >> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0);
2233 switch ((insn >> 22) & 3) {
2234 case 0:
2235 if (insn & (1 << 21))
2236 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2237 else
2238 gen_op_iwmmxt_minub_M0_wRn(rd1);
2239 break;
2240 case 1:
2241 if (insn & (1 << 21))
2242 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2243 else
2244 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2245 break;
2246 case 2:
2247 if (insn & (1 << 21))
2248 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2249 else
2250 gen_op_iwmmxt_minul_M0_wRn(rd1);
2251 break;
2252 case 3:
2253 return 1;
2254 }
2255 gen_op_iwmmxt_movq_wRn_M0(wrd);
2256 gen_op_iwmmxt_set_mup();
2257 break;
2258 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2259 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2260 wrd = (insn >> 12) & 0xf;
2261 rd0 = (insn >> 16) & 0xf;
2262 rd1 = (insn >> 0) & 0xf;
2263 gen_op_iwmmxt_movq_M0_wRn(rd0);
2264 switch ((insn >> 22) & 3) {
2265 case 0:
2266 if (insn & (1 << 21))
2267 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2268 else
2269 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2270 break;
2271 case 1:
2272 if (insn & (1 << 21))
2273 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2274 else
2275 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2276 break;
2277 case 2:
2278 if (insn & (1 << 21))
2279 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2280 else
2281 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2282 break;
2283 case 3:
2284 return 1;
2285 }
2286 gen_op_iwmmxt_movq_wRn_M0(wrd);
2287 gen_op_iwmmxt_set_mup();
2288 break;
2289 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2290 case 0x402: case 0x502: case 0x602: case 0x702:
2291 wrd = (insn >> 12) & 0xf;
2292 rd0 = (insn >> 16) & 0xf;
2293 rd1 = (insn >> 0) & 0xf;
2294 gen_op_iwmmxt_movq_M0_wRn(rd0);
2295 gen_op_movl_T0_im((insn >> 20) & 3);
2296 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2297 gen_op_iwmmxt_movq_wRn_M0(wrd);
2298 gen_op_iwmmxt_set_mup();
2299 break;
2300 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2301 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2302 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2303 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2304 wrd = (insn >> 12) & 0xf;
2305 rd0 = (insn >> 16) & 0xf;
2306 rd1 = (insn >> 0) & 0xf;
2307 gen_op_iwmmxt_movq_M0_wRn(rd0);
2308 switch ((insn >> 20) & 0xf) {
2309 case 0x0:
2310 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2311 break;
2312 case 0x1:
2313 gen_op_iwmmxt_subub_M0_wRn(rd1);
2314 break;
2315 case 0x3:
2316 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2317 break;
2318 case 0x4:
2319 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2320 break;
2321 case 0x5:
2322 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2323 break;
2324 case 0x7:
2325 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2326 break;
2327 case 0x8:
2328 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2329 break;
2330 case 0x9:
2331 gen_op_iwmmxt_subul_M0_wRn(rd1);
2332 break;
2333 case 0xb:
2334 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2335 break;
2336 default:
2337 return 1;
2338 }
2339 gen_op_iwmmxt_movq_wRn_M0(wrd);
2340 gen_op_iwmmxt_set_mup();
2341 gen_op_iwmmxt_set_cup();
2342 break;
2343 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2344 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2345 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2346 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2347 wrd = (insn >> 12) & 0xf;
2348 rd0 = (insn >> 16) & 0xf;
2349 gen_op_iwmmxt_movq_M0_wRn(rd0);
2350 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2351 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2352 gen_op_iwmmxt_movq_wRn_M0(wrd);
2353 gen_op_iwmmxt_set_mup();
2354 gen_op_iwmmxt_set_cup();
2355 break;
2356 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2357 case 0x418: case 0x518: case 0x618: case 0x718:
2358 case 0x818: case 0x918: case 0xa18: case 0xb18:
2359 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2360 wrd = (insn >> 12) & 0xf;
2361 rd0 = (insn >> 16) & 0xf;
2362 rd1 = (insn >> 0) & 0xf;
2363 gen_op_iwmmxt_movq_M0_wRn(rd0);
2364 switch ((insn >> 20) & 0xf) {
2365 case 0x0:
2366 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2367 break;
2368 case 0x1:
2369 gen_op_iwmmxt_addub_M0_wRn(rd1);
2370 break;
2371 case 0x3:
2372 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2373 break;
2374 case 0x4:
2375 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2376 break;
2377 case 0x5:
2378 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2379 break;
2380 case 0x7:
2381 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2382 break;
2383 case 0x8:
2384 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2385 break;
2386 case 0x9:
2387 gen_op_iwmmxt_addul_M0_wRn(rd1);
2388 break;
2389 case 0xb:
2390 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2391 break;
2392 default:
2393 return 1;
2394 }
2395 gen_op_iwmmxt_movq_wRn_M0(wrd);
2396 gen_op_iwmmxt_set_mup();
2397 gen_op_iwmmxt_set_cup();
2398 break;
2399 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2400 case 0x408: case 0x508: case 0x608: case 0x708:
2401 case 0x808: case 0x908: case 0xa08: case 0xb08:
2402 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2403 wrd = (insn >> 12) & 0xf;
2404 rd0 = (insn >> 16) & 0xf;
2405 rd1 = (insn >> 0) & 0xf;
2406 gen_op_iwmmxt_movq_M0_wRn(rd0);
2407 if (!(insn & (1 << 20)))
2408 return 1;
2409 switch ((insn >> 22) & 3) {
2410 case 0:
2411 return 1;
2412 case 1:
2413 if (insn & (1 << 21))
2414 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2415 else
2416 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2417 break;
2418 case 2:
2419 if (insn & (1 << 21))
2420 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2421 else
2422 gen_op_iwmmxt_packul_M0_wRn(rd1);
2423 break;
2424 case 3:
2425 if (insn & (1 << 21))
2426 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2427 else
2428 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2429 break;
2430 }
2431 gen_op_iwmmxt_movq_wRn_M0(wrd);
2432 gen_op_iwmmxt_set_mup();
2433 gen_op_iwmmxt_set_cup();
2434 break;
2435 case 0x201: case 0x203: case 0x205: case 0x207:
2436 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2437 case 0x211: case 0x213: case 0x215: case 0x217:
2438 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2439 wrd = (insn >> 5) & 0xf;
2440 rd0 = (insn >> 12) & 0xf;
2441 rd1 = (insn >> 0) & 0xf;
2442 if (rd0 == 0xf || rd1 == 0xf)
2443 return 1;
2444 gen_op_iwmmxt_movq_M0_wRn(wrd);
2445 switch ((insn >> 16) & 0xf) {
2446 case 0x0: /* TMIA */
2447 gen_movl_T0_reg(s, rd0);
2448 gen_movl_T1_reg(s, rd1);
2449 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2450 break;
2451 case 0x8: /* TMIAPH */
2452 gen_movl_T0_reg(s, rd0);
2453 gen_movl_T1_reg(s, rd1);
2454 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2455 break;
2456 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2457 gen_movl_T1_reg(s, rd0);
2458 if (insn & (1 << 16))
2459 gen_op_shrl_T1_im(16);
2460 gen_op_movl_T0_T1();
2461 gen_movl_T1_reg(s, rd1);
2462 if (insn & (1 << 17))
2463 gen_op_shrl_T1_im(16);
2464 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2465 break;
2466 default:
2467 return 1;
2468 }
2469 gen_op_iwmmxt_movq_wRn_M0(wrd);
2470 gen_op_iwmmxt_set_mup();
2471 break;
2472 default:
2473 return 1;
2474 }
2475
2476 return 0;
2477 }
2478
2479 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2480 (ie. an undefined instruction). */
disas_dsp_insn(CPUState * env,DisasContext * s,uint32_t insn)2481 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2482 {
2483 int acc, rd0, rd1, rdhi, rdlo;
2484
2485 if ((insn & 0x0ff00f10) == 0x0e200010) {
2486 /* Multiply with Internal Accumulate Format */
2487 rd0 = (insn >> 12) & 0xf;
2488 rd1 = insn & 0xf;
2489 acc = (insn >> 5) & 7;
2490
2491 if (acc != 0)
2492 return 1;
2493
2494 switch ((insn >> 16) & 0xf) {
2495 case 0x0: /* MIA */
2496 gen_movl_T0_reg(s, rd0);
2497 gen_movl_T1_reg(s, rd1);
2498 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2499 break;
2500 case 0x8: /* MIAPH */
2501 gen_movl_T0_reg(s, rd0);
2502 gen_movl_T1_reg(s, rd1);
2503 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2504 break;
2505 case 0xc: /* MIABB */
2506 case 0xd: /* MIABT */
2507 case 0xe: /* MIATB */
2508 case 0xf: /* MIATT */
2509 gen_movl_T1_reg(s, rd0);
2510 if (insn & (1 << 16))
2511 gen_op_shrl_T1_im(16);
2512 gen_op_movl_T0_T1();
2513 gen_movl_T1_reg(s, rd1);
2514 if (insn & (1 << 17))
2515 gen_op_shrl_T1_im(16);
2516 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2517 break;
2518 default:
2519 return 1;
2520 }
2521
2522 gen_op_iwmmxt_movq_wRn_M0(acc);
2523 return 0;
2524 }
2525
2526 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2527 /* Internal Accumulator Access Format */
2528 rdhi = (insn >> 16) & 0xf;
2529 rdlo = (insn >> 12) & 0xf;
2530 acc = insn & 7;
2531
2532 if (acc != 0)
2533 return 1;
2534
2535 if (insn & ARM_CP_RW_BIT) { /* MRA */
2536 gen_iwmmxt_movl_T0_T1_wRn(acc);
2537 gen_movl_reg_T0(s, rdlo);
2538 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2539 gen_op_andl_T0_T1();
2540 gen_movl_reg_T0(s, rdhi);
2541 } else { /* MAR */
2542 gen_movl_T0_reg(s, rdlo);
2543 gen_movl_T1_reg(s, rdhi);
2544 gen_iwmmxt_movl_wRn_T0_T1(acc);
2545 }
2546 return 0;
2547 }
2548
2549 return 1;
2550 }
2551
2552 /* Disassemble system coprocessor instruction. Return nonzero if
2553 instruction is not defined. */
disas_cp_insn(CPUState * env,DisasContext * s,uint32_t insn)2554 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2555 {
2556 TCGv tmp;
2557 uint32_t rd = (insn >> 12) & 0xf;
2558 uint32_t cp = (insn >> 8) & 0xf;
2559 if (IS_USER(s)) {
2560 return 1;
2561 }
2562
2563 if (insn & ARM_CP_RW_BIT) {
2564 if (!env->cp[cp].cp_read)
2565 return 1;
2566 gen_set_pc_im(s->pc);
2567 tmp = new_tmp();
2568 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2569 store_reg(s, rd, tmp);
2570 } else {
2571 if (!env->cp[cp].cp_write)
2572 return 1;
2573 gen_set_pc_im(s->pc);
2574 tmp = load_reg(s, rd);
2575 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2576 dead_tmp(tmp);
2577 }
2578 return 0;
2579 }
2580
cp15_user_ok(uint32_t insn)2581 static int cp15_user_ok(uint32_t insn)
2582 {
2583 int cpn = (insn >> 16) & 0xf;
2584 int cpm = insn & 0xf;
2585 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2586
2587 if (cpn == 13 && cpm == 0) {
2588 /* TLS register. */
2589 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2590 return 1;
2591 }
2592 if (cpn == 7) {
2593 /* ISB, DSB, DMB. */
2594 if ((cpm == 5 && op == 4)
2595 || (cpm == 10 && (op == 4 || op == 5)))
2596 return 1;
2597 }
2598 return 0;
2599 }
2600
2601 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2602 instruction is not defined. */
disas_cp15_insn(CPUState * env,DisasContext * s,uint32_t insn)2603 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2604 {
2605 uint32_t rd;
2606 TCGv tmp;
2607
2608 /* M profile cores use memory mapped registers instead of cp15. */
2609 if (arm_feature(env, ARM_FEATURE_M))
2610 return 1;
2611
2612 if ((insn & (1 << 25)) == 0) {
2613 if (insn & (1 << 20)) {
2614 /* mrrc */
2615 return 1;
2616 }
2617 /* mcrr. Used for block cache operations, so implement as no-op. */
2618 return 0;
2619 }
2620 if ((insn & (1 << 4)) == 0) {
2621 /* cdp */
2622 return 1;
2623 }
2624 if (IS_USER(s) && !cp15_user_ok(insn)) {
2625 return 1;
2626 }
2627 if ((insn & 0x0fff0fff) == 0x0e070f90
2628 || (insn & 0x0fff0fff) == 0x0e070f58) {
2629 /* Wait for interrupt. */
2630 gen_set_pc_im(s->pc);
2631 s->is_jmp = DISAS_WFI;
2632 return 0;
2633 }
2634 rd = (insn >> 12) & 0xf;
2635 if (insn & ARM_CP_RW_BIT) {
2636 tmp = new_tmp();
2637 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2638 /* If the destination register is r15 then sets condition codes. */
2639 if (rd != 15)
2640 store_reg(s, rd, tmp);
2641 else
2642 dead_tmp(tmp);
2643 } else {
2644 tmp = load_reg(s, rd);
2645 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2646 dead_tmp(tmp);
2647 /* Normally we would always end the TB here, but Linux
2648 * arch/arm/mach-pxa/sleep.S expects two instructions following
2649 * an MMU enable to execute from cache. Imitate this behaviour. */
2650 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2651 (insn & 0x0fff0fff) != 0x0e010f10)
2652 gen_lookup_tb(s);
2653 }
2654 return 0;
2655 }
2656
2657 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2658 #define VFP_SREG(insn, bigbit, smallbit) \
2659 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2660 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2661 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2662 reg = (((insn) >> (bigbit)) & 0x0f) \
2663 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2664 } else { \
2665 if (insn & (1 << (smallbit))) \
2666 return 1; \
2667 reg = ((insn) >> (bigbit)) & 0x0f; \
2668 }} while (0)
2669
2670 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2671 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2672 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2673 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2674 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2675 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2676
2677 /* Move between integer and VFP cores. */
gen_vfp_mrs(void)2678 static TCGv gen_vfp_mrs(void)
2679 {
2680 TCGv tmp = new_tmp();
2681 tcg_gen_mov_i32(tmp, cpu_F0s);
2682 return tmp;
2683 }
2684
gen_vfp_msr(TCGv tmp)2685 static void gen_vfp_msr(TCGv tmp)
2686 {
2687 tcg_gen_mov_i32(cpu_F0s, tmp);
2688 dead_tmp(tmp);
2689 }
2690
2691 static inline int
vfp_enabled(CPUState * env)2692 vfp_enabled(CPUState * env)
2693 {
2694 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2695 }
2696
gen_neon_dup_u8(TCGv var,int shift)2697 static void gen_neon_dup_u8(TCGv var, int shift)
2698 {
2699 TCGv tmp = new_tmp();
2700 if (shift)
2701 tcg_gen_shri_i32(var, var, shift);
2702 tcg_gen_ext8u_i32(var, var);
2703 tcg_gen_shli_i32(tmp, var, 8);
2704 tcg_gen_or_i32(var, var, tmp);
2705 tcg_gen_shli_i32(tmp, var, 16);
2706 tcg_gen_or_i32(var, var, tmp);
2707 dead_tmp(tmp);
2708 }
2709
gen_neon_dup_low16(TCGv var)2710 static void gen_neon_dup_low16(TCGv var)
2711 {
2712 TCGv tmp = new_tmp();
2713 tcg_gen_ext16u_i32(var, var);
2714 tcg_gen_shli_i32(tmp, var, 16);
2715 tcg_gen_or_i32(var, var, tmp);
2716 dead_tmp(tmp);
2717 }
2718
gen_neon_dup_high16(TCGv var)2719 static void gen_neon_dup_high16(TCGv var)
2720 {
2721 TCGv tmp = new_tmp();
2722 tcg_gen_andi_i32(var, var, 0xffff0000);
2723 tcg_gen_shri_i32(tmp, var, 16);
2724 tcg_gen_or_i32(var, var, tmp);
2725 dead_tmp(tmp);
2726 }
2727
2728 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2729 (ie. an undefined instruction). */
disas_vfp_insn(CPUState * env,DisasContext * s,uint32_t insn)2730 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2731 {
2732 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2733 int dp, veclen;
2734 TCGv tmp;
2735 TCGv tmp2;
2736
2737 if (!arm_feature(env, ARM_FEATURE_VFP))
2738 return 1;
2739
2740 if (!vfp_enabled(env)) {
2741 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2742 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2743 return 1;
2744 rn = (insn >> 16) & 0xf;
2745 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2746 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2747 return 1;
2748 }
2749 dp = ((insn & 0xf00) == 0xb00);
2750 switch ((insn >> 24) & 0xf) {
2751 case 0xe:
2752 if (insn & (1 << 4)) {
2753 /* single register transfer */
2754 rd = (insn >> 12) & 0xf;
2755 if (dp) {
2756 int size;
2757 int pass;
2758
2759 VFP_DREG_N(rn, insn);
2760 if (insn & 0xf)
2761 return 1;
2762 if (insn & 0x00c00060
2763 && !arm_feature(env, ARM_FEATURE_NEON))
2764 return 1;
2765
2766 pass = (insn >> 21) & 1;
2767 if (insn & (1 << 22)) {
2768 size = 0;
2769 offset = ((insn >> 5) & 3) * 8;
2770 } else if (insn & (1 << 5)) {
2771 size = 1;
2772 offset = (insn & (1 << 6)) ? 16 : 0;
2773 } else {
2774 size = 2;
2775 offset = 0;
2776 }
2777 if (insn & ARM_CP_RW_BIT) {
2778 /* vfp->arm */
2779 tmp = neon_load_reg(rn, pass);
2780 switch (size) {
2781 case 0:
2782 if (offset)
2783 tcg_gen_shri_i32(tmp, tmp, offset);
2784 if (insn & (1 << 23))
2785 gen_uxtb(tmp);
2786 else
2787 gen_sxtb(tmp);
2788 break;
2789 case 1:
2790 if (insn & (1 << 23)) {
2791 if (offset) {
2792 tcg_gen_shri_i32(tmp, tmp, 16);
2793 } else {
2794 gen_uxth(tmp);
2795 }
2796 } else {
2797 if (offset) {
2798 tcg_gen_sari_i32(tmp, tmp, 16);
2799 } else {
2800 gen_sxth(tmp);
2801 }
2802 }
2803 break;
2804 case 2:
2805 break;
2806 }
2807 store_reg(s, rd, tmp);
2808 } else {
2809 /* arm->vfp */
2810 tmp = load_reg(s, rd);
2811 if (insn & (1 << 23)) {
2812 /* VDUP */
2813 if (size == 0) {
2814 gen_neon_dup_u8(tmp, 0);
2815 } else if (size == 1) {
2816 gen_neon_dup_low16(tmp);
2817 }
2818 for (n = 0; n <= pass * 2; n++) {
2819 tmp2 = new_tmp();
2820 tcg_gen_mov_i32(tmp2, tmp);
2821 neon_store_reg(rn, n, tmp2);
2822 }
2823 neon_store_reg(rn, n, tmp);
2824 } else {
2825 /* VMOV */
2826 switch (size) {
2827 case 0:
2828 tmp2 = neon_load_reg(rn, pass);
2829 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2830 dead_tmp(tmp2);
2831 break;
2832 case 1:
2833 tmp2 = neon_load_reg(rn, pass);
2834 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2835 dead_tmp(tmp2);
2836 break;
2837 case 2:
2838 break;
2839 }
2840 neon_store_reg(rn, pass, tmp);
2841 }
2842 }
2843 } else { /* !dp */
2844 if ((insn & 0x6f) != 0x00)
2845 return 1;
2846 rn = VFP_SREG_N(insn);
2847 if (insn & ARM_CP_RW_BIT) {
2848 /* vfp->arm */
2849 if (insn & (1 << 21)) {
2850 /* system register */
2851 rn >>= 1;
2852
2853 switch (rn) {
2854 case ARM_VFP_FPSID:
2855 /* VFP2 allows access to FSID from userspace.
2856 VFP3 restricts all id registers to privileged
2857 accesses. */
2858 if (IS_USER(s)
2859 && arm_feature(env, ARM_FEATURE_VFP3))
2860 return 1;
2861 tmp = load_cpu_field(vfp.xregs[rn]);
2862 break;
2863 case ARM_VFP_FPEXC:
2864 if (IS_USER(s))
2865 return 1;
2866 tmp = load_cpu_field(vfp.xregs[rn]);
2867 break;
2868 case ARM_VFP_FPINST:
2869 case ARM_VFP_FPINST2:
2870 /* Not present in VFP3. */
2871 if (IS_USER(s)
2872 || arm_feature(env, ARM_FEATURE_VFP3))
2873 return 1;
2874 tmp = load_cpu_field(vfp.xregs[rn]);
2875 break;
2876 case ARM_VFP_FPSCR:
2877 if (rd == 15) {
2878 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2879 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2880 } else {
2881 tmp = new_tmp();
2882 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2883 }
2884 break;
2885 case ARM_VFP_MVFR0:
2886 case ARM_VFP_MVFR1:
2887 if (IS_USER(s)
2888 || !arm_feature(env, ARM_FEATURE_VFP3))
2889 return 1;
2890 tmp = load_cpu_field(vfp.xregs[rn]);
2891 break;
2892 default:
2893 return 1;
2894 }
2895 } else {
2896 gen_mov_F0_vreg(0, rn);
2897 tmp = gen_vfp_mrs();
2898 }
2899 if (rd == 15) {
2900 /* Set the 4 flag bits in the CPSR. */
2901 gen_set_nzcv(tmp);
2902 dead_tmp(tmp);
2903 } else {
2904 store_reg(s, rd, tmp);
2905 }
2906 } else {
2907 /* arm->vfp */
2908 tmp = load_reg(s, rd);
2909 if (insn & (1 << 21)) {
2910 rn >>= 1;
2911 /* system register */
2912 switch (rn) {
2913 case ARM_VFP_FPSID:
2914 case ARM_VFP_MVFR0:
2915 case ARM_VFP_MVFR1:
2916 /* Writes are ignored. */
2917 break;
2918 case ARM_VFP_FPSCR:
2919 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2920 dead_tmp(tmp);
2921 gen_lookup_tb(s);
2922 break;
2923 case ARM_VFP_FPEXC:
2924 if (IS_USER(s))
2925 return 1;
2926 store_cpu_field(tmp, vfp.xregs[rn]);
2927 gen_lookup_tb(s);
2928 break;
2929 case ARM_VFP_FPINST:
2930 case ARM_VFP_FPINST2:
2931 store_cpu_field(tmp, vfp.xregs[rn]);
2932 break;
2933 default:
2934 return 1;
2935 }
2936 } else {
2937 gen_vfp_msr(tmp);
2938 gen_mov_vreg_F0(0, rn);
2939 }
2940 }
2941 }
2942 } else {
2943 /* data processing */
2944 /* The opcode is in bits 23, 21, 20 and 6. */
2945 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2946 if (dp) {
2947 if (op == 15) {
2948 /* rn is opcode */
2949 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2950 } else {
2951 /* rn is register number */
2952 VFP_DREG_N(rn, insn);
2953 }
2954
2955 if (op == 15 && (rn == 15 || rn > 17)) {
2956 /* Integer or single precision destination. */
2957 rd = VFP_SREG_D(insn);
2958 } else {
2959 VFP_DREG_D(rd, insn);
2960 }
2961
2962 if (op == 15 && (rn == 16 || rn == 17)) {
2963 /* Integer source. */
2964 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2965 } else {
2966 VFP_DREG_M(rm, insn);
2967 }
2968 } else {
2969 rn = VFP_SREG_N(insn);
2970 if (op == 15 && rn == 15) {
2971 /* Double precision destination. */
2972 VFP_DREG_D(rd, insn);
2973 } else {
2974 rd = VFP_SREG_D(insn);
2975 }
2976 rm = VFP_SREG_M(insn);
2977 }
2978
2979 veclen = env->vfp.vec_len;
2980 if (op == 15 && rn > 3)
2981 veclen = 0;
2982
2983 /* Shut up compiler warnings. */
2984 delta_m = 0;
2985 delta_d = 0;
2986 bank_mask = 0;
2987
2988 if (veclen > 0) {
2989 if (dp)
2990 bank_mask = 0xc;
2991 else
2992 bank_mask = 0x18;
2993
2994 /* Figure out what type of vector operation this is. */
2995 if ((rd & bank_mask) == 0) {
2996 /* scalar */
2997 veclen = 0;
2998 } else {
2999 if (dp)
3000 delta_d = (env->vfp.vec_stride >> 1) + 1;
3001 else
3002 delta_d = env->vfp.vec_stride + 1;
3003
3004 if ((rm & bank_mask) == 0) {
3005 /* mixed scalar/vector */
3006 delta_m = 0;
3007 } else {
3008 /* vector */
3009 delta_m = delta_d;
3010 }
3011 }
3012 }
3013
3014 /* Load the initial operands. */
3015 if (op == 15) {
3016 switch (rn) {
3017 case 16:
3018 case 17:
3019 /* Integer source */
3020 gen_mov_F0_vreg(0, rm);
3021 break;
3022 case 8:
3023 case 9:
3024 /* Compare */
3025 gen_mov_F0_vreg(dp, rd);
3026 gen_mov_F1_vreg(dp, rm);
3027 break;
3028 case 10:
3029 case 11:
3030 /* Compare with zero */
3031 gen_mov_F0_vreg(dp, rd);
3032 gen_vfp_F1_ld0(dp);
3033 break;
3034 case 20:
3035 case 21:
3036 case 22:
3037 case 23:
3038 case 28:
3039 case 29:
3040 case 30:
3041 case 31:
3042 /* Source and destination the same. */
3043 gen_mov_F0_vreg(dp, rd);
3044 break;
3045 default:
3046 /* One source operand. */
3047 gen_mov_F0_vreg(dp, rm);
3048 break;
3049 }
3050 } else {
3051 /* Two source operands. */
3052 gen_mov_F0_vreg(dp, rn);
3053 gen_mov_F1_vreg(dp, rm);
3054 }
3055
3056 for (;;) {
3057 /* Perform the calculation. */
3058 switch (op) {
3059 case 0: /* mac: fd + (fn * fm) */
3060 gen_vfp_mul(dp);
3061 gen_mov_F1_vreg(dp, rd);
3062 gen_vfp_add(dp);
3063 break;
3064 case 1: /* nmac: fd - (fn * fm) */
3065 gen_vfp_mul(dp);
3066 gen_vfp_neg(dp);
3067 gen_mov_F1_vreg(dp, rd);
3068 gen_vfp_add(dp);
3069 break;
3070 case 2: /* msc: -fd + (fn * fm) */
3071 gen_vfp_mul(dp);
3072 gen_mov_F1_vreg(dp, rd);
3073 gen_vfp_sub(dp);
3074 break;
3075 case 3: /* nmsc: -fd - (fn * fm) */
3076 gen_vfp_mul(dp);
3077 gen_vfp_neg(dp);
3078 gen_mov_F1_vreg(dp, rd);
3079 gen_vfp_sub(dp);
3080 break;
3081 case 4: /* mul: fn * fm */
3082 gen_vfp_mul(dp);
3083 break;
3084 case 5: /* nmul: -(fn * fm) */
3085 gen_vfp_mul(dp);
3086 gen_vfp_neg(dp);
3087 break;
3088 case 6: /* add: fn + fm */
3089 gen_vfp_add(dp);
3090 break;
3091 case 7: /* sub: fn - fm */
3092 gen_vfp_sub(dp);
3093 break;
3094 case 8: /* div: fn / fm */
3095 gen_vfp_div(dp);
3096 break;
3097 case 14: /* fconst */
3098 if (!arm_feature(env, ARM_FEATURE_VFP3))
3099 return 1;
3100
3101 n = (insn << 12) & 0x80000000;
3102 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3103 if (dp) {
3104 if (i & 0x40)
3105 i |= 0x3f80;
3106 else
3107 i |= 0x4000;
3108 n |= i << 16;
3109 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3110 } else {
3111 if (i & 0x40)
3112 i |= 0x780;
3113 else
3114 i |= 0x800;
3115 n |= i << 19;
3116 tcg_gen_movi_i32(cpu_F0s, n);
3117 }
3118 break;
3119 case 15: /* extension space */
3120 switch (rn) {
3121 case 0: /* cpy */
3122 /* no-op */
3123 break;
3124 case 1: /* abs */
3125 gen_vfp_abs(dp);
3126 break;
3127 case 2: /* neg */
3128 gen_vfp_neg(dp);
3129 break;
3130 case 3: /* sqrt */
3131 gen_vfp_sqrt(dp);
3132 break;
3133 case 8: /* cmp */
3134 gen_vfp_cmp(dp);
3135 break;
3136 case 9: /* cmpe */
3137 gen_vfp_cmpe(dp);
3138 break;
3139 case 10: /* cmpz */
3140 gen_vfp_cmp(dp);
3141 break;
3142 case 11: /* cmpez */
3143 gen_vfp_F1_ld0(dp);
3144 gen_vfp_cmpe(dp);
3145 break;
3146 case 15: /* single<->double conversion */
3147 if (dp)
3148 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3149 else
3150 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3151 break;
3152 case 16: /* fuito */
3153 gen_vfp_uito(dp);
3154 break;
3155 case 17: /* fsito */
3156 gen_vfp_sito(dp);
3157 break;
3158 case 20: /* fshto */
3159 if (!arm_feature(env, ARM_FEATURE_VFP3))
3160 return 1;
3161 gen_vfp_shto(dp, 16 - rm);
3162 break;
3163 case 21: /* fslto */
3164 if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 return 1;
3166 gen_vfp_slto(dp, 32 - rm);
3167 break;
3168 case 22: /* fuhto */
3169 if (!arm_feature(env, ARM_FEATURE_VFP3))
3170 return 1;
3171 gen_vfp_uhto(dp, 16 - rm);
3172 break;
3173 case 23: /* fulto */
3174 if (!arm_feature(env, ARM_FEATURE_VFP3))
3175 return 1;
3176 gen_vfp_ulto(dp, 32 - rm);
3177 break;
3178 case 24: /* ftoui */
3179 gen_vfp_toui(dp);
3180 break;
3181 case 25: /* ftouiz */
3182 gen_vfp_touiz(dp);
3183 break;
3184 case 26: /* ftosi */
3185 gen_vfp_tosi(dp);
3186 break;
3187 case 27: /* ftosiz */
3188 gen_vfp_tosiz(dp);
3189 break;
3190 case 28: /* ftosh */
3191 if (!arm_feature(env, ARM_FEATURE_VFP3))
3192 return 1;
3193 gen_vfp_tosh(dp, 16 - rm);
3194 break;
3195 case 29: /* ftosl */
3196 if (!arm_feature(env, ARM_FEATURE_VFP3))
3197 return 1;
3198 gen_vfp_tosl(dp, 32 - rm);
3199 break;
3200 case 30: /* ftouh */
3201 if (!arm_feature(env, ARM_FEATURE_VFP3))
3202 return 1;
3203 gen_vfp_touh(dp, 16 - rm);
3204 break;
3205 case 31: /* ftoul */
3206 if (!arm_feature(env, ARM_FEATURE_VFP3))
3207 return 1;
3208 gen_vfp_toul(dp, 32 - rm);
3209 break;
3210 default: /* undefined */
3211 printf ("rn:%d\n", rn);
3212 return 1;
3213 }
3214 break;
3215 default: /* undefined */
3216 printf ("op:%d\n", op);
3217 return 1;
3218 }
3219
3220 /* Write back the result. */
3221 if (op == 15 && (rn >= 8 && rn <= 11))
3222 ; /* Comparison, do nothing. */
3223 else if (op == 15 && rn > 17)
3224 /* Integer result. */
3225 gen_mov_vreg_F0(0, rd);
3226 else if (op == 15 && rn == 15)
3227 /* conversion */
3228 gen_mov_vreg_F0(!dp, rd);
3229 else
3230 gen_mov_vreg_F0(dp, rd);
3231
3232 /* break out of the loop if we have finished */
3233 if (veclen == 0)
3234 break;
3235
3236 if (op == 15 && delta_m == 0) {
3237 /* single source one-many */
3238 while (veclen--) {
3239 rd = ((rd + delta_d) & (bank_mask - 1))
3240 | (rd & bank_mask);
3241 gen_mov_vreg_F0(dp, rd);
3242 }
3243 break;
3244 }
3245 /* Setup the next operands. */
3246 veclen--;
3247 rd = ((rd + delta_d) & (bank_mask - 1))
3248 | (rd & bank_mask);
3249
3250 if (op == 15) {
3251 /* One source operand. */
3252 rm = ((rm + delta_m) & (bank_mask - 1))
3253 | (rm & bank_mask);
3254 gen_mov_F0_vreg(dp, rm);
3255 } else {
3256 /* Two source operands. */
3257 rn = ((rn + delta_d) & (bank_mask - 1))
3258 | (rn & bank_mask);
3259 gen_mov_F0_vreg(dp, rn);
3260 if (delta_m) {
3261 rm = ((rm + delta_m) & (bank_mask - 1))
3262 | (rm & bank_mask);
3263 gen_mov_F1_vreg(dp, rm);
3264 }
3265 }
3266 }
3267 }
3268 break;
3269 case 0xc:
3270 case 0xd:
3271 if (dp && (insn & 0x03e00000) == 0x00400000) {
3272 /* two-register transfer */
3273 rn = (insn >> 16) & 0xf;
3274 rd = (insn >> 12) & 0xf;
3275 if (dp) {
3276 VFP_DREG_M(rm, insn);
3277 } else {
3278 rm = VFP_SREG_M(insn);
3279 }
3280
3281 if (insn & ARM_CP_RW_BIT) {
3282 /* vfp->arm */
3283 if (dp) {
3284 gen_mov_F0_vreg(0, rm * 2);
3285 tmp = gen_vfp_mrs();
3286 store_reg(s, rd, tmp);
3287 gen_mov_F0_vreg(0, rm * 2 + 1);
3288 tmp = gen_vfp_mrs();
3289 store_reg(s, rn, tmp);
3290 } else {
3291 gen_mov_F0_vreg(0, rm);
3292 tmp = gen_vfp_mrs();
3293 store_reg(s, rn, tmp);
3294 gen_mov_F0_vreg(0, rm + 1);
3295 tmp = gen_vfp_mrs();
3296 store_reg(s, rd, tmp);
3297 }
3298 } else {
3299 /* arm->vfp */
3300 if (dp) {
3301 tmp = load_reg(s, rd);
3302 gen_vfp_msr(tmp);
3303 gen_mov_vreg_F0(0, rm * 2);
3304 tmp = load_reg(s, rn);
3305 gen_vfp_msr(tmp);
3306 gen_mov_vreg_F0(0, rm * 2 + 1);
3307 } else {
3308 tmp = load_reg(s, rn);
3309 gen_vfp_msr(tmp);
3310 gen_mov_vreg_F0(0, rm);
3311 tmp = load_reg(s, rd);
3312 gen_vfp_msr(tmp);
3313 gen_mov_vreg_F0(0, rm + 1);
3314 }
3315 }
3316 } else {
3317 /* Load/store */
3318 rn = (insn >> 16) & 0xf;
3319 if (dp)
3320 VFP_DREG_D(rd, insn);
3321 else
3322 rd = VFP_SREG_D(insn);
3323 if (s->thumb && rn == 15) {
3324 gen_op_movl_T1_im(s->pc & ~2);
3325 } else {
3326 gen_movl_T1_reg(s, rn);
3327 }
3328 if ((insn & 0x01200000) == 0x01000000) {
3329 /* Single load/store */
3330 offset = (insn & 0xff) << 2;
3331 if ((insn & (1 << 23)) == 0)
3332 offset = -offset;
3333 gen_op_addl_T1_im(offset);
3334 if (insn & (1 << 20)) {
3335 gen_vfp_ld(s, dp);
3336 gen_mov_vreg_F0(dp, rd);
3337 } else {
3338 gen_mov_F0_vreg(dp, rd);
3339 gen_vfp_st(s, dp);
3340 }
3341 } else {
3342 /* load/store multiple */
3343 if (dp)
3344 n = (insn >> 1) & 0x7f;
3345 else
3346 n = insn & 0xff;
3347
3348 if (insn & (1 << 24)) /* pre-decrement */
3349 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3350
3351 if (dp)
3352 offset = 8;
3353 else
3354 offset = 4;
3355 for (i = 0; i < n; i++) {
3356 if (insn & ARM_CP_RW_BIT) {
3357 /* load */
3358 gen_vfp_ld(s, dp);
3359 gen_mov_vreg_F0(dp, rd + i);
3360 } else {
3361 /* store */
3362 gen_mov_F0_vreg(dp, rd + i);
3363 gen_vfp_st(s, dp);
3364 }
3365 gen_op_addl_T1_im(offset);
3366 }
3367 if (insn & (1 << 21)) {
3368 /* writeback */
3369 if (insn & (1 << 24))
3370 offset = -offset * n;
3371 else if (dp && (insn & 1))
3372 offset = 4;
3373 else
3374 offset = 0;
3375
3376 if (offset != 0)
3377 gen_op_addl_T1_im(offset);
3378 gen_movl_reg_T1(s, rn);
3379 }
3380 }
3381 }
3382 break;
3383 default:
3384 /* Should never happen. */
3385 return 1;
3386 }
3387 return 0;
3388 }
3389
gen_goto_tb(DisasContext * s,int n,uint32_t dest)3390 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3391 {
3392 TranslationBlock *tb;
3393
3394 tb = s->tb;
3395 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3396 tcg_gen_goto_tb(n);
3397 gen_set_pc_im(dest);
3398 tcg_gen_exit_tb((long)tb + n);
3399 } else {
3400 gen_set_pc_im(dest);
3401 tcg_gen_exit_tb(0);
3402 }
3403 }
3404
gen_jmp(DisasContext * s,uint32_t dest)3405 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3406 {
3407 if (unlikely(s->singlestep_enabled)) {
3408 /* An indirect jump so that we still trigger the debug exception. */
3409 if (s->thumb)
3410 dest |= 1;
3411 gen_bx_im(s, dest);
3412 } else {
3413 gen_goto_tb(s, 0, dest);
3414 s->is_jmp = DISAS_TB_JUMP;
3415 }
3416 }
3417
gen_mulxy(TCGv t0,TCGv t1,int x,int y)3418 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3419 {
3420 if (x)
3421 tcg_gen_sari_i32(t0, t0, 16);
3422 else
3423 gen_sxth(t0);
3424 if (y)
3425 tcg_gen_sari_i32(t1, t1, 16);
3426 else
3427 gen_sxth(t1);
3428 tcg_gen_mul_i32(t0, t0, t1);
3429 }
3430
3431 /* Return the mask of PSR bits set by a MSR instruction. */
msr_mask(CPUState * env,DisasContext * s,int flags,int spsr)3432 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3433 uint32_t mask;
3434
3435 mask = 0;
3436 if (flags & (1 << 0))
3437 mask |= 0xff;
3438 if (flags & (1 << 1))
3439 mask |= 0xff00;
3440 if (flags & (1 << 2))
3441 mask |= 0xff0000;
3442 if (flags & (1 << 3))
3443 mask |= 0xff000000;
3444
3445 /* Mask out undefined bits. */
3446 mask &= ~CPSR_RESERVED;
3447 if (!arm_feature(env, ARM_FEATURE_V6))
3448 mask &= ~(CPSR_E | CPSR_GE);
3449 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3450 mask &= ~CPSR_IT;
3451 /* Mask out execution state bits. */
3452 if (!spsr)
3453 mask &= ~CPSR_EXEC;
3454 /* Mask out privileged bits. */
3455 if (IS_USER(s))
3456 mask &= CPSR_USER;
3457 return mask;
3458 }
3459
3460 /* Returns nonzero if access to the PSR is not permitted. */
gen_set_psr_T0(DisasContext * s,uint32_t mask,int spsr)3461 static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3462 {
3463 TCGv tmp;
3464 if (spsr) {
3465 /* ??? This is also undefined in system mode. */
3466 if (IS_USER(s))
3467 return 1;
3468
3469 tmp = load_cpu_field(spsr);
3470 tcg_gen_andi_i32(tmp, tmp, ~mask);
3471 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3472 tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3473 store_cpu_field(tmp, spsr);
3474 } else {
3475 gen_set_cpsr(cpu_T[0], mask);
3476 }
3477 gen_lookup_tb(s);
3478 return 0;
3479 }
3480
3481 /* Generate an old-style exception return. Marks pc as dead. */
gen_exception_return(DisasContext * s,TCGv pc)3482 static void gen_exception_return(DisasContext *s, TCGv pc)
3483 {
3484 TCGv tmp;
3485 store_reg(s, 15, pc);
3486 tmp = load_cpu_field(spsr);
3487 gen_set_cpsr(tmp, 0xffffffff);
3488 dead_tmp(tmp);
3489 s->is_jmp = DISAS_UPDATE;
3490 }
3491
3492 /* Generate a v6 exception return. Marks both values as dead. */
gen_rfe(DisasContext * s,TCGv pc,TCGv cpsr)3493 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3494 {
3495 gen_set_cpsr(cpsr, 0xffffffff);
3496 dead_tmp(cpsr);
3497 store_reg(s, 15, pc);
3498 s->is_jmp = DISAS_UPDATE;
3499 }
3500
3501 static inline void
gen_set_condexec(DisasContext * s)3502 gen_set_condexec (DisasContext *s)
3503 {
3504 if (s->condexec_mask) {
3505 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3506 TCGv tmp = new_tmp();
3507 tcg_gen_movi_i32(tmp, val);
3508 store_cpu_field(tmp, condexec_bits);
3509 }
3510 else if (s->condexec_mask_prev != 0) {
3511 TCGv tmp = new_tmp();
3512 tcg_gen_movi_i32(tmp, 0);
3513 store_cpu_field(tmp, condexec_bits);
3514 }
3515 }
3516
gen_nop_hint(DisasContext * s,int val)3517 static void gen_nop_hint(DisasContext *s, int val)
3518 {
3519 switch (val) {
3520 case 3: /* wfi */
3521 gen_set_pc_im(s->pc);
3522 s->is_jmp = DISAS_WFI;
3523 break;
3524 case 2: /* wfe */
3525 case 4: /* sev */
3526 /* TODO: Implement SEV and WFE. May help SMP performance. */
3527 default: /* nop */
3528 break;
3529 }
3530 }
3531
3532 /* These macros help make the code more readable when migrating from the
3533 old dyngen helpers. They should probably be removed when
3534 T0/T1 are removed. */
3535 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3536 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3537
3538 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3539
gen_neon_add(int size)3540 static inline int gen_neon_add(int size)
3541 {
3542 switch (size) {
3543 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3544 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3545 case 2: gen_op_addl_T0_T1(); break;
3546 default: return 1;
3547 }
3548 return 0;
3549 }
3550
gen_neon_rsb(int size)3551 static inline void gen_neon_rsb(int size)
3552 {
3553 switch (size) {
3554 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3555 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3556 case 2: gen_op_rsbl_T0_T1(); break;
3557 default: return;
3558 }
3559 }
3560
3561 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3562 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3563 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3564 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3565 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3566
3567 /* FIXME: This is wrong. They set the wrong overflow bit. */
3568 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3569 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3570 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3571 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3572
3573 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3574 switch ((size << 1) | u) { \
3575 case 0: \
3576 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3577 break; \
3578 case 1: \
3579 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3580 break; \
3581 case 2: \
3582 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3583 break; \
3584 case 3: \
3585 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3586 break; \
3587 case 4: \
3588 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3589 break; \
3590 case 5: \
3591 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3592 break; \
3593 default: return 1; \
3594 }} while (0)
3595
3596 #define GEN_NEON_INTEGER_OP(name) do { \
3597 switch ((size << 1) | u) { \
3598 case 0: \
3599 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3600 break; \
3601 case 1: \
3602 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3603 break; \
3604 case 2: \
3605 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3606 break; \
3607 case 3: \
3608 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3609 break; \
3610 case 4: \
3611 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3612 break; \
3613 case 5: \
3614 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3615 break; \
3616 default: return 1; \
3617 }} while (0)
3618
3619 static inline void
gen_neon_movl_scratch_T0(int scratch)3620 gen_neon_movl_scratch_T0(int scratch)
3621 {
3622 uint32_t offset;
3623
3624 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3625 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3626 }
3627
3628 static inline void
gen_neon_movl_scratch_T1(int scratch)3629 gen_neon_movl_scratch_T1(int scratch)
3630 {
3631 uint32_t offset;
3632
3633 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3634 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3635 }
3636
3637 static inline void
gen_neon_movl_T0_scratch(int scratch)3638 gen_neon_movl_T0_scratch(int scratch)
3639 {
3640 uint32_t offset;
3641
3642 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3643 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3644 }
3645
3646 static inline void
gen_neon_movl_T1_scratch(int scratch)3647 gen_neon_movl_T1_scratch(int scratch)
3648 {
3649 uint32_t offset;
3650
3651 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3652 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3653 }
3654
gen_neon_get_scalar(int size,int reg)3655 static inline void gen_neon_get_scalar(int size, int reg)
3656 {
3657 if (size == 1) {
3658 NEON_GET_REG(T0, reg >> 1, reg & 1);
3659 } else {
3660 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3661 if (reg & 1)
3662 gen_neon_dup_low16(cpu_T[0]);
3663 else
3664 gen_neon_dup_high16(cpu_T[0]);
3665 }
3666 }
3667
gen_neon_unzip(int reg,int q,int tmp,int size)3668 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3669 {
3670 int n;
3671
3672 for (n = 0; n < q + 1; n += 2) {
3673 NEON_GET_REG(T0, reg, n);
3674 NEON_GET_REG(T0, reg, n + n);
3675 switch (size) {
3676 case 0: gen_helper_neon_unzip_u8(); break;
3677 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3678 case 2: /* no-op */; break;
3679 default: abort();
3680 }
3681 gen_neon_movl_scratch_T0(tmp + n);
3682 gen_neon_movl_scratch_T1(tmp + n + 1);
3683 }
3684 }
3685
3686 static struct {
3687 int nregs;
3688 int interleave;
3689 int spacing;
3690 } neon_ls_element_type[11] = {
3691 {4, 4, 1},
3692 {4, 4, 2},
3693 {4, 1, 1},
3694 {4, 2, 1},
3695 {3, 3, 1},
3696 {3, 3, 2},
3697 {3, 1, 1},
3698 {1, 1, 1},
3699 {2, 2, 1},
3700 {2, 2, 2},
3701 {2, 1, 1}
3702 };
3703
3704 /* Translate a NEON load/store element instruction. Return nonzero if the
3705 instruction is invalid. */
disas_neon_ls_insn(CPUState * env,DisasContext * s,uint32_t insn)3706 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3707 {
3708 int rd, rn, rm;
3709 int op;
3710 int nregs;
3711 int interleave;
3712 int stride;
3713 int size;
3714 int reg;
3715 int pass;
3716 int load;
3717 int shift;
3718 int n;
3719 TCGv tmp;
3720 TCGv tmp2;
3721
3722 if (!vfp_enabled(env))
3723 return 1;
3724 VFP_DREG_D(rd, insn);
3725 rn = (insn >> 16) & 0xf;
3726 rm = insn & 0xf;
3727 load = (insn & (1 << 21)) != 0;
3728 if ((insn & (1 << 23)) == 0) {
3729 /* Load store all elements. */
3730 op = (insn >> 8) & 0xf;
3731 size = (insn >> 6) & 3;
3732 if (op > 10 || size == 3)
3733 return 1;
3734 nregs = neon_ls_element_type[op].nregs;
3735 interleave = neon_ls_element_type[op].interleave;
3736 gen_movl_T1_reg(s, rn);
3737 stride = (1 << size) * interleave;
3738 for (reg = 0; reg < nregs; reg++) {
3739 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3740 gen_movl_T1_reg(s, rn);
3741 gen_op_addl_T1_im((1 << size) * reg);
3742 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3743 gen_movl_T1_reg(s, rn);
3744 gen_op_addl_T1_im(1 << size);
3745 }
3746 for (pass = 0; pass < 2; pass++) {
3747 if (size == 2) {
3748 if (load) {
3749 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3750 neon_store_reg(rd, pass, tmp);
3751 } else {
3752 tmp = neon_load_reg(rd, pass);
3753 gen_st32(tmp, cpu_T[1], IS_USER(s));
3754 }
3755 gen_op_addl_T1_im(stride);
3756 } else if (size == 1) {
3757 if (load) {
3758 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3759 gen_op_addl_T1_im(stride);
3760 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3761 gen_op_addl_T1_im(stride);
3762 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3763 dead_tmp(tmp2);
3764 neon_store_reg(rd, pass, tmp);
3765 } else {
3766 tmp = neon_load_reg(rd, pass);
3767 tmp2 = new_tmp();
3768 tcg_gen_shri_i32(tmp2, tmp, 16);
3769 gen_st16(tmp, cpu_T[1], IS_USER(s));
3770 gen_op_addl_T1_im(stride);
3771 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3772 gen_op_addl_T1_im(stride);
3773 }
3774 } else /* size == 0 */ {
3775 if (load) {
3776 TCGV_UNUSED(tmp2);
3777 for (n = 0; n < 4; n++) {
3778 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3779 gen_op_addl_T1_im(stride);
3780 if (n == 0) {
3781 tmp2 = tmp;
3782 } else {
3783 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3784 dead_tmp(tmp);
3785 }
3786 }
3787 neon_store_reg(rd, pass, tmp2);
3788 } else {
3789 tmp2 = neon_load_reg(rd, pass);
3790 for (n = 0; n < 4; n++) {
3791 tmp = new_tmp();
3792 if (n == 0) {
3793 tcg_gen_mov_i32(tmp, tmp2);
3794 } else {
3795 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3796 }
3797 gen_st8(tmp, cpu_T[1], IS_USER(s));
3798 gen_op_addl_T1_im(stride);
3799 }
3800 dead_tmp(tmp2);
3801 }
3802 }
3803 }
3804 rd += neon_ls_element_type[op].spacing;
3805 }
3806 stride = nregs * 8;
3807 } else {
3808 size = (insn >> 10) & 3;
3809 if (size == 3) {
3810 /* Load single element to all lanes. */
3811 if (!load)
3812 return 1;
3813 size = (insn >> 6) & 3;
3814 nregs = ((insn >> 8) & 3) + 1;
3815 stride = (insn & (1 << 5)) ? 2 : 1;
3816 gen_movl_T1_reg(s, rn);
3817 for (reg = 0; reg < nregs; reg++) {
3818 switch (size) {
3819 case 0:
3820 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3821 gen_neon_dup_u8(tmp, 0);
3822 break;
3823 case 1:
3824 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3825 gen_neon_dup_low16(tmp);
3826 break;
3827 case 2:
3828 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3829 break;
3830 case 3:
3831 return 1;
3832 default: /* Avoid compiler warnings. */
3833 abort();
3834 }
3835 gen_op_addl_T1_im(1 << size);
3836 tmp2 = new_tmp();
3837 tcg_gen_mov_i32(tmp2, tmp);
3838 neon_store_reg(rd, 0, tmp2);
3839 neon_store_reg(rd, 1, tmp);
3840 rd += stride;
3841 }
3842 stride = (1 << size) * nregs;
3843 } else {
3844 /* Single element. */
3845 pass = (insn >> 7) & 1;
3846 switch (size) {
3847 case 0:
3848 shift = ((insn >> 5) & 3) * 8;
3849 stride = 1;
3850 break;
3851 case 1:
3852 shift = ((insn >> 6) & 1) * 16;
3853 stride = (insn & (1 << 5)) ? 2 : 1;
3854 break;
3855 case 2:
3856 shift = 0;
3857 stride = (insn & (1 << 6)) ? 2 : 1;
3858 break;
3859 default:
3860 abort();
3861 }
3862 nregs = ((insn >> 8) & 3) + 1;
3863 gen_movl_T1_reg(s, rn);
3864 for (reg = 0; reg < nregs; reg++) {
3865 if (load) {
3866 switch (size) {
3867 case 0:
3868 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3869 break;
3870 case 1:
3871 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3872 break;
3873 case 2:
3874 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3875 break;
3876 default: /* Avoid compiler warnings. */
3877 abort();
3878 }
3879 if (size != 2) {
3880 tmp2 = neon_load_reg(rd, pass);
3881 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3882 dead_tmp(tmp2);
3883 }
3884 neon_store_reg(rd, pass, tmp);
3885 } else { /* Store */
3886 tmp = neon_load_reg(rd, pass);
3887 if (shift)
3888 tcg_gen_shri_i32(tmp, tmp, shift);
3889 switch (size) {
3890 case 0:
3891 gen_st8(tmp, cpu_T[1], IS_USER(s));
3892 break;
3893 case 1:
3894 gen_st16(tmp, cpu_T[1], IS_USER(s));
3895 break;
3896 case 2:
3897 gen_st32(tmp, cpu_T[1], IS_USER(s));
3898 break;
3899 }
3900 }
3901 rd += stride;
3902 gen_op_addl_T1_im(1 << size);
3903 }
3904 stride = nregs * (1 << size);
3905 }
3906 }
3907 if (rm != 15) {
3908 TCGv base;
3909
3910 base = load_reg(s, rn);
3911 if (rm == 13) {
3912 tcg_gen_addi_i32(base, base, stride);
3913 } else {
3914 TCGv index;
3915 index = load_reg(s, rm);
3916 tcg_gen_add_i32(base, base, index);
3917 dead_tmp(index);
3918 }
3919 store_reg(s, rn, base);
3920 }
3921 return 0;
3922 }
3923
3924 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
gen_neon_bsl(TCGv dest,TCGv t,TCGv f,TCGv c)3925 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3926 {
3927 tcg_gen_and_i32(t, t, c);
3928 tcg_gen_bic_i32(f, f, c);
3929 tcg_gen_or_i32(dest, t, f);
3930 }
3931
gen_neon_narrow(int size,TCGv dest,TCGv_i64 src)3932 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3933 {
3934 switch (size) {
3935 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3936 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3937 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3938 default: abort();
3939 }
3940 }
3941
gen_neon_narrow_sats(int size,TCGv dest,TCGv_i64 src)3942 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3943 {
3944 switch (size) {
3945 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3946 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3947 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3948 default: abort();
3949 }
3950 }
3951
gen_neon_narrow_satu(int size,TCGv dest,TCGv_i64 src)3952 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3953 {
3954 switch (size) {
3955 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3956 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3957 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3958 default: abort();
3959 }
3960 }
3961
gen_neon_shift_narrow(int size,TCGv var,TCGv shift,int q,int u)3962 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3963 int q, int u)
3964 {
3965 if (q) {
3966 if (u) {
3967 switch (size) {
3968 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3969 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3970 default: abort();
3971 }
3972 } else {
3973 switch (size) {
3974 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3975 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3976 default: abort();
3977 }
3978 }
3979 } else {
3980 if (u) {
3981 switch (size) {
3982 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3983 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3984 default: abort();
3985 }
3986 } else {
3987 switch (size) {
3988 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3989 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3990 default: abort();
3991 }
3992 }
3993 }
3994 }
3995
gen_neon_widen(TCGv_i64 dest,TCGv src,int size,int u)3996 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3997 {
3998 if (u) {
3999 switch (size) {
4000 case 0: gen_helper_neon_widen_u8(dest, src); break;
4001 case 1: gen_helper_neon_widen_u16(dest, src); break;
4002 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4003 default: abort();
4004 }
4005 } else {
4006 switch (size) {
4007 case 0: gen_helper_neon_widen_s8(dest, src); break;
4008 case 1: gen_helper_neon_widen_s16(dest, src); break;
4009 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4010 default: abort();
4011 }
4012 }
4013 dead_tmp(src);
4014 }
4015
gen_neon_addl(int size)4016 static inline void gen_neon_addl(int size)
4017 {
4018 switch (size) {
4019 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4020 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4021 case 2: tcg_gen_add_i64(CPU_V001); break;
4022 default: abort();
4023 }
4024 }
4025
gen_neon_subl(int size)4026 static inline void gen_neon_subl(int size)
4027 {
4028 switch (size) {
4029 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4030 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4031 case 2: tcg_gen_sub_i64(CPU_V001); break;
4032 default: abort();
4033 }
4034 }
4035
gen_neon_negl(TCGv_i64 var,int size)4036 static inline void gen_neon_negl(TCGv_i64 var, int size)
4037 {
4038 switch (size) {
4039 case 0: gen_helper_neon_negl_u16(var, var); break;
4040 case 1: gen_helper_neon_negl_u32(var, var); break;
4041 case 2: gen_helper_neon_negl_u64(var, var); break;
4042 default: abort();
4043 }
4044 }
4045
gen_neon_addl_saturate(TCGv_i64 op0,TCGv_i64 op1,int size)4046 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4047 {
4048 switch (size) {
4049 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4050 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4051 default: abort();
4052 }
4053 }
4054
gen_neon_mull(TCGv_i64 dest,TCGv a,TCGv b,int size,int u)4055 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4056 {
4057 TCGv_i64 tmp;
4058
4059 switch ((size << 1) | u) {
4060 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4061 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4062 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4063 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4064 case 4:
4065 tmp = gen_muls_i64_i32(a, b);
4066 tcg_gen_mov_i64(dest, tmp);
4067 break;
4068 case 5:
4069 tmp = gen_mulu_i64_i32(a, b);
4070 tcg_gen_mov_i64(dest, tmp);
4071 break;
4072 default: abort();
4073 }
4074 if (size < 2) {
4075 dead_tmp(b);
4076 dead_tmp(a);
4077 }
4078 }
4079
4080 /* Translate a NEON data processing instruction. Return nonzero if the
4081 instruction is invalid.
4082 We process data in a mixture of 32-bit and 64-bit chunks.
4083 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4084
disas_neon_data_insn(CPUState * env,DisasContext * s,uint32_t insn)4085 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4086 {
4087 int op;
4088 int q;
4089 int rd, rn, rm;
4090 int size;
4091 int shift;
4092 int pass;
4093 int count;
4094 int pairwise;
4095 int u;
4096 int n;
4097 uint32_t imm;
4098 TCGv tmp;
4099 TCGv tmp2;
4100 TCGv tmp3;
4101 TCGv_i64 tmp64;
4102
4103 if (!vfp_enabled(env))
4104 return 1;
4105 q = (insn & (1 << 6)) != 0;
4106 u = (insn >> 24) & 1;
4107 VFP_DREG_D(rd, insn);
4108 VFP_DREG_N(rn, insn);
4109 VFP_DREG_M(rm, insn);
4110 size = (insn >> 20) & 3;
4111 if ((insn & (1 << 23)) == 0) {
4112 /* Three register same length. */
4113 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4114 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4115 || op == 10 || op == 11 || op == 16)) {
4116 /* 64-bit element instructions. */
4117 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4118 neon_load_reg64(cpu_V0, rn + pass);
4119 neon_load_reg64(cpu_V1, rm + pass);
4120 switch (op) {
4121 case 1: /* VQADD */
4122 if (u) {
4123 gen_helper_neon_add_saturate_u64(CPU_V001);
4124 } else {
4125 gen_helper_neon_add_saturate_s64(CPU_V001);
4126 }
4127 break;
4128 case 5: /* VQSUB */
4129 if (u) {
4130 gen_helper_neon_sub_saturate_u64(CPU_V001);
4131 } else {
4132 gen_helper_neon_sub_saturate_s64(CPU_V001);
4133 }
4134 break;
4135 case 8: /* VSHL */
4136 if (u) {
4137 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4138 } else {
4139 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4140 }
4141 break;
4142 case 9: /* VQSHL */
4143 if (u) {
4144 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4145 cpu_V0, cpu_V0);
4146 } else {
4147 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4148 cpu_V1, cpu_V0);
4149 }
4150 break;
4151 case 10: /* VRSHL */
4152 if (u) {
4153 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4154 } else {
4155 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4156 }
4157 break;
4158 case 11: /* VQRSHL */
4159 if (u) {
4160 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4161 cpu_V1, cpu_V0);
4162 } else {
4163 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4164 cpu_V1, cpu_V0);
4165 }
4166 break;
4167 case 16:
4168 if (u) {
4169 tcg_gen_sub_i64(CPU_V001);
4170 } else {
4171 tcg_gen_add_i64(CPU_V001);
4172 }
4173 break;
4174 default:
4175 abort();
4176 }
4177 neon_store_reg64(cpu_V0, rd + pass);
4178 }
4179 return 0;
4180 }
4181 switch (op) {
4182 case 8: /* VSHL */
4183 case 9: /* VQSHL */
4184 case 10: /* VRSHL */
4185 case 11: /* VQRSHL */
4186 {
4187 int rtmp;
4188 /* Shift instruction operands are reversed. */
4189 rtmp = rn;
4190 rn = rm;
4191 rm = rtmp;
4192 pairwise = 0;
4193 }
4194 break;
4195 case 20: /* VPMAX */
4196 case 21: /* VPMIN */
4197 case 23: /* VPADD */
4198 pairwise = 1;
4199 break;
4200 case 26: /* VPADD (float) */
4201 pairwise = (u && size < 2);
4202 break;
4203 case 30: /* VPMIN/VPMAX (float) */
4204 pairwise = u;
4205 break;
4206 default:
4207 pairwise = 0;
4208 break;
4209 }
4210 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4211
4212 if (pairwise) {
4213 /* Pairwise. */
4214 if (q)
4215 n = (pass & 1) * 2;
4216 else
4217 n = 0;
4218 if (pass < q + 1) {
4219 NEON_GET_REG(T0, rn, n);
4220 NEON_GET_REG(T1, rn, n + 1);
4221 } else {
4222 NEON_GET_REG(T0, rm, n);
4223 NEON_GET_REG(T1, rm, n + 1);
4224 }
4225 } else {
4226 /* Elementwise. */
4227 NEON_GET_REG(T0, rn, pass);
4228 NEON_GET_REG(T1, rm, pass);
4229 }
4230 switch (op) {
4231 case 0: /* VHADD */
4232 GEN_NEON_INTEGER_OP(hadd);
4233 break;
4234 case 1: /* VQADD */
4235 GEN_NEON_INTEGER_OP_ENV(qadd);
4236 break;
4237 case 2: /* VRHADD */
4238 GEN_NEON_INTEGER_OP(rhadd);
4239 break;
4240 case 3: /* Logic ops. */
4241 switch ((u << 2) | size) {
4242 case 0: /* VAND */
4243 gen_op_andl_T0_T1();
4244 break;
4245 case 1: /* BIC */
4246 gen_op_bicl_T0_T1();
4247 break;
4248 case 2: /* VORR */
4249 gen_op_orl_T0_T1();
4250 break;
4251 case 3: /* VORN */
4252 gen_op_notl_T1();
4253 gen_op_orl_T0_T1();
4254 break;
4255 case 4: /* VEOR */
4256 gen_op_xorl_T0_T1();
4257 break;
4258 case 5: /* VBSL */
4259 tmp = neon_load_reg(rd, pass);
4260 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4261 dead_tmp(tmp);
4262 break;
4263 case 6: /* VBIT */
4264 tmp = neon_load_reg(rd, pass);
4265 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4266 dead_tmp(tmp);
4267 break;
4268 case 7: /* VBIF */
4269 tmp = neon_load_reg(rd, pass);
4270 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4271 dead_tmp(tmp);
4272 break;
4273 }
4274 break;
4275 case 4: /* VHSUB */
4276 GEN_NEON_INTEGER_OP(hsub);
4277 break;
4278 case 5: /* VQSUB */
4279 GEN_NEON_INTEGER_OP_ENV(qsub);
4280 break;
4281 case 6: /* VCGT */
4282 GEN_NEON_INTEGER_OP(cgt);
4283 break;
4284 case 7: /* VCGE */
4285 GEN_NEON_INTEGER_OP(cge);
4286 break;
4287 case 8: /* VSHL */
4288 GEN_NEON_INTEGER_OP(shl);
4289 break;
4290 case 9: /* VQSHL */
4291 GEN_NEON_INTEGER_OP_ENV(qshl);
4292 break;
4293 case 10: /* VRSHL */
4294 GEN_NEON_INTEGER_OP(rshl);
4295 break;
4296 case 11: /* VQRSHL */
4297 GEN_NEON_INTEGER_OP_ENV(qrshl);
4298 break;
4299 case 12: /* VMAX */
4300 GEN_NEON_INTEGER_OP(max);
4301 break;
4302 case 13: /* VMIN */
4303 GEN_NEON_INTEGER_OP(min);
4304 break;
4305 case 14: /* VABD */
4306 GEN_NEON_INTEGER_OP(abd);
4307 break;
4308 case 15: /* VABA */
4309 GEN_NEON_INTEGER_OP(abd);
4310 NEON_GET_REG(T1, rd, pass);
4311 gen_neon_add(size);
4312 break;
4313 case 16:
4314 if (!u) { /* VADD */
4315 if (gen_neon_add(size))
4316 return 1;
4317 } else { /* VSUB */
4318 switch (size) {
4319 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4320 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4321 case 2: gen_op_subl_T0_T1(); break;
4322 default: return 1;
4323 }
4324 }
4325 break;
4326 case 17:
4327 if (!u) { /* VTST */
4328 switch (size) {
4329 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4330 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4331 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4332 default: return 1;
4333 }
4334 } else { /* VCEQ */
4335 switch (size) {
4336 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4337 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4338 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4339 default: return 1;
4340 }
4341 }
4342 break;
4343 case 18: /* Multiply. */
4344 switch (size) {
4345 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4346 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4347 case 2: gen_op_mul_T0_T1(); break;
4348 default: return 1;
4349 }
4350 NEON_GET_REG(T1, rd, pass);
4351 if (u) { /* VMLS */
4352 gen_neon_rsb(size);
4353 } else { /* VMLA */
4354 gen_neon_add(size);
4355 }
4356 break;
4357 case 19: /* VMUL */
4358 if (u) { /* polynomial */
4359 gen_helper_neon_mul_p8(CPU_T001);
4360 } else { /* Integer */
4361 switch (size) {
4362 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4363 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4364 case 2: gen_op_mul_T0_T1(); break;
4365 default: return 1;
4366 }
4367 }
4368 break;
4369 case 20: /* VPMAX */
4370 GEN_NEON_INTEGER_OP(pmax);
4371 break;
4372 case 21: /* VPMIN */
4373 GEN_NEON_INTEGER_OP(pmin);
4374 break;
4375 case 22: /* Hultiply high. */
4376 if (!u) { /* VQDMULH */
4377 switch (size) {
4378 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4379 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4380 default: return 1;
4381 }
4382 } else { /* VQRDHMUL */
4383 switch (size) {
4384 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4385 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4386 default: return 1;
4387 }
4388 }
4389 break;
4390 case 23: /* VPADD */
4391 if (u)
4392 return 1;
4393 switch (size) {
4394 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4395 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4396 case 2: gen_op_addl_T0_T1(); break;
4397 default: return 1;
4398 }
4399 break;
4400 case 26: /* Floating point arithnetic. */
4401 switch ((u << 2) | size) {
4402 case 0: /* VADD */
4403 gen_helper_neon_add_f32(CPU_T001);
4404 break;
4405 case 2: /* VSUB */
4406 gen_helper_neon_sub_f32(CPU_T001);
4407 break;
4408 case 4: /* VPADD */
4409 gen_helper_neon_add_f32(CPU_T001);
4410 break;
4411 case 6: /* VABD */
4412 gen_helper_neon_abd_f32(CPU_T001);
4413 break;
4414 default:
4415 return 1;
4416 }
4417 break;
4418 case 27: /* Float multiply. */
4419 gen_helper_neon_mul_f32(CPU_T001);
4420 if (!u) {
4421 NEON_GET_REG(T1, rd, pass);
4422 if (size == 0) {
4423 gen_helper_neon_add_f32(CPU_T001);
4424 } else {
4425 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4426 }
4427 }
4428 break;
4429 case 28: /* Float compare. */
4430 if (!u) {
4431 gen_helper_neon_ceq_f32(CPU_T001);
4432 } else {
4433 if (size == 0)
4434 gen_helper_neon_cge_f32(CPU_T001);
4435 else
4436 gen_helper_neon_cgt_f32(CPU_T001);
4437 }
4438 break;
4439 case 29: /* Float compare absolute. */
4440 if (!u)
4441 return 1;
4442 if (size == 0)
4443 gen_helper_neon_acge_f32(CPU_T001);
4444 else
4445 gen_helper_neon_acgt_f32(CPU_T001);
4446 break;
4447 case 30: /* Float min/max. */
4448 if (size == 0)
4449 gen_helper_neon_max_f32(CPU_T001);
4450 else
4451 gen_helper_neon_min_f32(CPU_T001);
4452 break;
4453 case 31:
4454 if (size == 0)
4455 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4456 else
4457 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4458 break;
4459 default:
4460 abort();
4461 }
4462 /* Save the result. For elementwise operations we can put it
4463 straight into the destination register. For pairwise operations
4464 we have to be careful to avoid clobbering the source operands. */
4465 if (pairwise && rd == rm) {
4466 gen_neon_movl_scratch_T0(pass);
4467 } else {
4468 NEON_SET_REG(T0, rd, pass);
4469 }
4470
4471 } /* for pass */
4472 if (pairwise && rd == rm) {
4473 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4474 gen_neon_movl_T0_scratch(pass);
4475 NEON_SET_REG(T0, rd, pass);
4476 }
4477 }
4478 /* End of 3 register same size operations. */
4479 } else if (insn & (1 << 4)) {
4480 if ((insn & 0x00380080) != 0) {
4481 /* Two registers and shift. */
4482 op = (insn >> 8) & 0xf;
4483 if (insn & (1 << 7)) {
4484 /* 64-bit shift. */
4485 size = 3;
4486 } else {
4487 size = 2;
4488 while ((insn & (1 << (size + 19))) == 0)
4489 size--;
4490 }
4491 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4492 /* To avoid excessive dumplication of ops we implement shift
4493 by immediate using the variable shift operations. */
4494 if (op < 8) {
4495 /* Shift by immediate:
4496 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4497 /* Right shifts are encoded as N - shift, where N is the
4498 element size in bits. */
4499 if (op <= 4)
4500 shift = shift - (1 << (size + 3));
4501 if (size == 3) {
4502 count = q + 1;
4503 } else {
4504 count = q ? 4: 2;
4505 }
4506 switch (size) {
4507 case 0:
4508 imm = (uint8_t) shift;
4509 imm |= imm << 8;
4510 imm |= imm << 16;
4511 break;
4512 case 1:
4513 imm = (uint16_t) shift;
4514 imm |= imm << 16;
4515 break;
4516 case 2:
4517 case 3:
4518 imm = shift;
4519 break;
4520 default:
4521 abort();
4522 }
4523
4524 for (pass = 0; pass < count; pass++) {
4525 if (size == 3) {
4526 neon_load_reg64(cpu_V0, rm + pass);
4527 tcg_gen_movi_i64(cpu_V1, imm);
4528 switch (op) {
4529 case 0: /* VSHR */
4530 case 1: /* VSRA */
4531 if (u)
4532 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4533 else
4534 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4535 break;
4536 case 2: /* VRSHR */
4537 case 3: /* VRSRA */
4538 if (u)
4539 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4540 else
4541 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4542 break;
4543 case 4: /* VSRI */
4544 if (!u)
4545 return 1;
4546 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4547 break;
4548 case 5: /* VSHL, VSLI */
4549 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4550 break;
4551 case 6: /* VQSHL */
4552 if (u)
4553 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4554 else
4555 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4556 break;
4557 case 7: /* VQSHLU */
4558 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4559 break;
4560 }
4561 if (op == 1 || op == 3) {
4562 /* Accumulate. */
4563 neon_load_reg64(cpu_V0, rd + pass);
4564 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4565 } else if (op == 4 || (op == 5 && u)) {
4566 /* Insert */
4567 cpu_abort(env, "VS[LR]I.64 not implemented");
4568 }
4569 neon_store_reg64(cpu_V0, rd + pass);
4570 } else { /* size < 3 */
4571 /* Operands in T0 and T1. */
4572 gen_op_movl_T1_im(imm);
4573 NEON_GET_REG(T0, rm, pass);
4574 switch (op) {
4575 case 0: /* VSHR */
4576 case 1: /* VSRA */
4577 GEN_NEON_INTEGER_OP(shl);
4578 break;
4579 case 2: /* VRSHR */
4580 case 3: /* VRSRA */
4581 GEN_NEON_INTEGER_OP(rshl);
4582 break;
4583 case 4: /* VSRI */
4584 if (!u)
4585 return 1;
4586 GEN_NEON_INTEGER_OP(shl);
4587 break;
4588 case 5: /* VSHL, VSLI */
4589 switch (size) {
4590 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4591 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4592 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4593 default: return 1;
4594 }
4595 break;
4596 case 6: /* VQSHL */
4597 GEN_NEON_INTEGER_OP_ENV(qshl);
4598 break;
4599 case 7: /* VQSHLU */
4600 switch (size) {
4601 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4602 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4603 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4604 default: return 1;
4605 }
4606 break;
4607 }
4608
4609 if (op == 1 || op == 3) {
4610 /* Accumulate. */
4611 NEON_GET_REG(T1, rd, pass);
4612 gen_neon_add(size);
4613 } else if (op == 4 || (op == 5 && u)) {
4614 /* Insert */
4615 switch (size) {
4616 case 0:
4617 if (op == 4)
4618 imm = 0xff >> -shift;
4619 else
4620 imm = (uint8_t)(0xff << shift);
4621 imm |= imm << 8;
4622 imm |= imm << 16;
4623 break;
4624 case 1:
4625 if (op == 4)
4626 imm = 0xffff >> -shift;
4627 else
4628 imm = (uint16_t)(0xffff << shift);
4629 imm |= imm << 16;
4630 break;
4631 case 2:
4632 if (op == 4)
4633 imm = 0xffffffffu >> -shift;
4634 else
4635 imm = 0xffffffffu << shift;
4636 break;
4637 default:
4638 abort();
4639 }
4640 tmp = neon_load_reg(rd, pass);
4641 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4642 tcg_gen_andi_i32(tmp, tmp, ~imm);
4643 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4644 }
4645 NEON_SET_REG(T0, rd, pass);
4646 }
4647 } /* for pass */
4648 } else if (op < 10) {
4649 /* Shift by immediate and narrow:
4650 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4651 shift = shift - (1 << (size + 3));
4652 size++;
4653 switch (size) {
4654 case 1:
4655 imm = (uint16_t)shift;
4656 imm |= imm << 16;
4657 tmp2 = tcg_const_i32(imm);
4658 TCGV_UNUSED_I64(tmp64);
4659 break;
4660 case 2:
4661 imm = (uint32_t)shift;
4662 tmp2 = tcg_const_i32(imm);
4663 TCGV_UNUSED_I64(tmp64);
4664 break;
4665 case 3:
4666 tmp64 = tcg_const_i64(shift);
4667 TCGV_UNUSED(tmp2);
4668 break;
4669 default:
4670 abort();
4671 }
4672
4673 for (pass = 0; pass < 2; pass++) {
4674 if (size == 3) {
4675 neon_load_reg64(cpu_V0, rm + pass);
4676 if (q) {
4677 if (u)
4678 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4679 else
4680 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4681 } else {
4682 if (u)
4683 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4684 else
4685 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4686 }
4687 } else {
4688 tmp = neon_load_reg(rm + pass, 0);
4689 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4690 tmp3 = neon_load_reg(rm + pass, 1);
4691 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4692 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4693 dead_tmp(tmp);
4694 dead_tmp(tmp3);
4695 }
4696 tmp = new_tmp();
4697 if (op == 8 && !u) {
4698 gen_neon_narrow(size - 1, tmp, cpu_V0);
4699 } else {
4700 if (op == 8)
4701 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4702 else
4703 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4704 }
4705 if (pass == 0) {
4706 tmp2 = tmp;
4707 } else {
4708 neon_store_reg(rd, 0, tmp2);
4709 neon_store_reg(rd, 1, tmp);
4710 }
4711 } /* for pass */
4712 } else if (op == 10) {
4713 /* VSHLL */
4714 if (q || size == 3)
4715 return 1;
4716 tmp = neon_load_reg(rm, 0);
4717 tmp2 = neon_load_reg(rm, 1);
4718 for (pass = 0; pass < 2; pass++) {
4719 if (pass == 1)
4720 tmp = tmp2;
4721
4722 gen_neon_widen(cpu_V0, tmp, size, u);
4723
4724 if (shift != 0) {
4725 /* The shift is less than the width of the source
4726 type, so we can just shift the whole register. */
4727 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4728 if (size < 2 || !u) {
4729 uint64_t imm64;
4730 if (size == 0) {
4731 imm = (0xffu >> (8 - shift));
4732 imm |= imm << 16;
4733 } else {
4734 imm = 0xffff >> (16 - shift);
4735 }
4736 imm64 = imm | (((uint64_t)imm) << 32);
4737 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4738 }
4739 }
4740 neon_store_reg64(cpu_V0, rd + pass);
4741 }
4742 } else if (op == 15 || op == 16) {
4743 /* VCVT fixed-point. */
4744 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4745 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4746 if (op & 1) {
4747 if (u)
4748 gen_vfp_ulto(0, shift);
4749 else
4750 gen_vfp_slto(0, shift);
4751 } else {
4752 if (u)
4753 gen_vfp_toul(0, shift);
4754 else
4755 gen_vfp_tosl(0, shift);
4756 }
4757 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4758 }
4759 } else {
4760 return 1;
4761 }
4762 } else { /* (insn & 0x00380080) == 0 */
4763 int invert;
4764
4765 op = (insn >> 8) & 0xf;
4766 /* One register and immediate. */
4767 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4768 invert = (insn & (1 << 5)) != 0;
4769 switch (op) {
4770 case 0: case 1:
4771 /* no-op */
4772 break;
4773 case 2: case 3:
4774 imm <<= 8;
4775 break;
4776 case 4: case 5:
4777 imm <<= 16;
4778 break;
4779 case 6: case 7:
4780 imm <<= 24;
4781 break;
4782 case 8: case 9:
4783 imm |= imm << 16;
4784 break;
4785 case 10: case 11:
4786 imm = (imm << 8) | (imm << 24);
4787 break;
4788 case 12:
4789 imm = (imm < 8) | 0xff;
4790 break;
4791 case 13:
4792 imm = (imm << 16) | 0xffff;
4793 break;
4794 case 14:
4795 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4796 if (invert)
4797 imm = ~imm;
4798 break;
4799 case 15:
4800 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4801 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4802 break;
4803 }
4804 if (invert)
4805 imm = ~imm;
4806
4807 if (op != 14 || !invert)
4808 gen_op_movl_T1_im(imm);
4809
4810 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4811 if (op & 1 && op < 12) {
4812 tmp = neon_load_reg(rd, pass);
4813 if (invert) {
4814 /* The immediate value has already been inverted, so
4815 BIC becomes AND. */
4816 tcg_gen_andi_i32(tmp, tmp, imm);
4817 } else {
4818 tcg_gen_ori_i32(tmp, tmp, imm);
4819 }
4820 } else {
4821 /* VMOV, VMVN. */
4822 tmp = new_tmp();
4823 if (op == 14 && invert) {
4824 uint32_t val;
4825 val = 0;
4826 for (n = 0; n < 4; n++) {
4827 if (imm & (1 << (n + (pass & 1) * 4)))
4828 val |= 0xff << (n * 8);
4829 }
4830 tcg_gen_movi_i32(tmp, val);
4831 } else {
4832 tcg_gen_movi_i32(tmp, imm);
4833 }
4834 }
4835 neon_store_reg(rd, pass, tmp);
4836 }
4837 }
4838 } else { /* (insn & 0x00800010 == 0x00800000) */
4839 if (size != 3) {
4840 op = (insn >> 8) & 0xf;
4841 if ((insn & (1 << 6)) == 0) {
4842 /* Three registers of different lengths. */
4843 int src1_wide;
4844 int src2_wide;
4845 int prewiden;
4846 /* prewiden, src1_wide, src2_wide */
4847 static const int neon_3reg_wide[16][3] = {
4848 {1, 0, 0}, /* VADDL */
4849 {1, 1, 0}, /* VADDW */
4850 {1, 0, 0}, /* VSUBL */
4851 {1, 1, 0}, /* VSUBW */
4852 {0, 1, 1}, /* VADDHN */
4853 {0, 0, 0}, /* VABAL */
4854 {0, 1, 1}, /* VSUBHN */
4855 {0, 0, 0}, /* VABDL */
4856 {0, 0, 0}, /* VMLAL */
4857 {0, 0, 0}, /* VQDMLAL */
4858 {0, 0, 0}, /* VMLSL */
4859 {0, 0, 0}, /* VQDMLSL */
4860 {0, 0, 0}, /* Integer VMULL */
4861 {0, 0, 0}, /* VQDMULL */
4862 {0, 0, 0} /* Polynomial VMULL */
4863 };
4864
4865 prewiden = neon_3reg_wide[op][0];
4866 src1_wide = neon_3reg_wide[op][1];
4867 src2_wide = neon_3reg_wide[op][2];
4868
4869 if (size == 0 && (op == 9 || op == 11 || op == 13))
4870 return 1;
4871
4872 /* Avoid overlapping operands. Wide source operands are
4873 always aligned so will never overlap with wide
4874 destinations in problematic ways. */
4875 if (rd == rm && !src2_wide) {
4876 NEON_GET_REG(T0, rm, 1);
4877 gen_neon_movl_scratch_T0(2);
4878 } else if (rd == rn && !src1_wide) {
4879 NEON_GET_REG(T0, rn, 1);
4880 gen_neon_movl_scratch_T0(2);
4881 }
4882 TCGV_UNUSED(tmp3);
4883 for (pass = 0; pass < 2; pass++) {
4884 if (src1_wide) {
4885 neon_load_reg64(cpu_V0, rn + pass);
4886 TCGV_UNUSED(tmp);
4887 } else {
4888 if (pass == 1 && rd == rn) {
4889 gen_neon_movl_T0_scratch(2);
4890 tmp = new_tmp();
4891 tcg_gen_mov_i32(tmp, cpu_T[0]);
4892 } else {
4893 tmp = neon_load_reg(rn, pass);
4894 }
4895 if (prewiden) {
4896 gen_neon_widen(cpu_V0, tmp, size, u);
4897 }
4898 }
4899 if (src2_wide) {
4900 neon_load_reg64(cpu_V1, rm + pass);
4901 TCGV_UNUSED(tmp2);
4902 } else {
4903 if (pass == 1 && rd == rm) {
4904 gen_neon_movl_T0_scratch(2);
4905 tmp2 = new_tmp();
4906 tcg_gen_mov_i32(tmp2, cpu_T[0]);
4907 } else {
4908 tmp2 = neon_load_reg(rm, pass);
4909 }
4910 if (prewiden) {
4911 gen_neon_widen(cpu_V1, tmp2, size, u);
4912 }
4913 }
4914 switch (op) {
4915 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4916 gen_neon_addl(size);
4917 break;
4918 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4919 gen_neon_subl(size);
4920 break;
4921 case 5: case 7: /* VABAL, VABDL */
4922 switch ((size << 1) | u) {
4923 case 0:
4924 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4925 break;
4926 case 1:
4927 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4928 break;
4929 case 2:
4930 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4931 break;
4932 case 3:
4933 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4934 break;
4935 case 4:
4936 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4937 break;
4938 case 5:
4939 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4940 break;
4941 default: abort();
4942 }
4943 dead_tmp(tmp2);
4944 dead_tmp(tmp);
4945 break;
4946 case 8: case 9: case 10: case 11: case 12: case 13:
4947 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4948 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4949 break;
4950 case 14: /* Polynomial VMULL */
4951 cpu_abort(env, "Polynomial VMULL not implemented");
4952
4953 default: /* 15 is RESERVED. */
4954 return 1;
4955 }
4956 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4957 /* Accumulate. */
4958 if (op == 10 || op == 11) {
4959 gen_neon_negl(cpu_V0, size);
4960 }
4961
4962 if (op != 13) {
4963 neon_load_reg64(cpu_V1, rd + pass);
4964 }
4965
4966 switch (op) {
4967 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4968 gen_neon_addl(size);
4969 break;
4970 case 9: case 11: /* VQDMLAL, VQDMLSL */
4971 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4972 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4973 break;
4974 /* Fall through. */
4975 case 13: /* VQDMULL */
4976 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4977 break;
4978 default:
4979 abort();
4980 }
4981 neon_store_reg64(cpu_V0, rd + pass);
4982 } else if (op == 4 || op == 6) {
4983 /* Narrowing operation. */
4984 tmp = new_tmp();
4985 if (u) {
4986 switch (size) {
4987 case 0:
4988 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4989 break;
4990 case 1:
4991 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4992 break;
4993 case 2:
4994 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4995 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4996 break;
4997 default: abort();
4998 }
4999 } else {
5000 switch (size) {
5001 case 0:
5002 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5003 break;
5004 case 1:
5005 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5006 break;
5007 case 2:
5008 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5009 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5010 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5011 break;
5012 default: abort();
5013 }
5014 }
5015 if (pass == 0) {
5016 tmp3 = tmp;
5017 } else {
5018 neon_store_reg(rd, 0, tmp3);
5019 neon_store_reg(rd, 1, tmp);
5020 }
5021 } else {
5022 /* Write back the result. */
5023 neon_store_reg64(cpu_V0, rd + pass);
5024 }
5025 }
5026 } else {
5027 /* Two registers and a scalar. */
5028 switch (op) {
5029 case 0: /* Integer VMLA scalar */
5030 case 1: /* Float VMLA scalar */
5031 case 4: /* Integer VMLS scalar */
5032 case 5: /* Floating point VMLS scalar */
5033 case 8: /* Integer VMUL scalar */
5034 case 9: /* Floating point VMUL scalar */
5035 case 12: /* VQDMULH scalar */
5036 case 13: /* VQRDMULH scalar */
5037 gen_neon_get_scalar(size, rm);
5038 gen_neon_movl_scratch_T0(0);
5039 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5040 if (pass != 0)
5041 gen_neon_movl_T0_scratch(0);
5042 NEON_GET_REG(T1, rn, pass);
5043 if (op == 12) {
5044 if (size == 1) {
5045 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5046 } else {
5047 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5048 }
5049 } else if (op == 13) {
5050 if (size == 1) {
5051 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5052 } else {
5053 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5054 }
5055 } else if (op & 1) {
5056 gen_helper_neon_mul_f32(CPU_T001);
5057 } else {
5058 switch (size) {
5059 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5060 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5061 case 2: gen_op_mul_T0_T1(); break;
5062 default: return 1;
5063 }
5064 }
5065 if (op < 8) {
5066 /* Accumulate. */
5067 NEON_GET_REG(T1, rd, pass);
5068 switch (op) {
5069 case 0:
5070 gen_neon_add(size);
5071 break;
5072 case 1:
5073 gen_helper_neon_add_f32(CPU_T001);
5074 break;
5075 case 4:
5076 gen_neon_rsb(size);
5077 break;
5078 case 5:
5079 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5080 break;
5081 default:
5082 abort();
5083 }
5084 }
5085 NEON_SET_REG(T0, rd, pass);
5086 }
5087 break;
5088 case 2: /* VMLAL sclar */
5089 case 3: /* VQDMLAL scalar */
5090 case 6: /* VMLSL scalar */
5091 case 7: /* VQDMLSL scalar */
5092 case 10: /* VMULL scalar */
5093 case 11: /* VQDMULL scalar */
5094 if (size == 0 && (op == 3 || op == 7 || op == 11))
5095 return 1;
5096
5097 gen_neon_get_scalar(size, rm);
5098 NEON_GET_REG(T1, rn, 1);
5099
5100 for (pass = 0; pass < 2; pass++) {
5101 if (pass == 0) {
5102 tmp = neon_load_reg(rn, 0);
5103 } else {
5104 tmp = new_tmp();
5105 tcg_gen_mov_i32(tmp, cpu_T[1]);
5106 }
5107 tmp2 = new_tmp();
5108 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5109 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5110 if (op == 6 || op == 7) {
5111 gen_neon_negl(cpu_V0, size);
5112 }
5113 if (op != 11) {
5114 neon_load_reg64(cpu_V1, rd + pass);
5115 }
5116 switch (op) {
5117 case 2: case 6:
5118 gen_neon_addl(size);
5119 break;
5120 case 3: case 7:
5121 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5122 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5123 break;
5124 case 10:
5125 /* no-op */
5126 break;
5127 case 11:
5128 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5129 break;
5130 default:
5131 abort();
5132 }
5133 neon_store_reg64(cpu_V0, rd + pass);
5134 }
5135 break;
5136 default: /* 14 and 15 are RESERVED */
5137 return 1;
5138 }
5139 }
5140 } else { /* size == 3 */
5141 if (!u) {
5142 /* Extract. */
5143 imm = (insn >> 8) & 0xf;
5144 count = q + 1;
5145
5146 if (imm > 7 && !q)
5147 return 1;
5148
5149 if (imm == 0) {
5150 neon_load_reg64(cpu_V0, rn);
5151 if (q) {
5152 neon_load_reg64(cpu_V1, rn + 1);
5153 }
5154 } else if (imm == 8) {
5155 neon_load_reg64(cpu_V0, rn + 1);
5156 if (q) {
5157 neon_load_reg64(cpu_V1, rm);
5158 }
5159 } else if (q) {
5160 tmp64 = tcg_temp_new_i64();
5161 if (imm < 8) {
5162 neon_load_reg64(cpu_V0, rn);
5163 neon_load_reg64(tmp64, rn + 1);
5164 } else {
5165 neon_load_reg64(cpu_V0, rn + 1);
5166 neon_load_reg64(tmp64, rm);
5167 }
5168 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5169 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5170 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5171 if (imm < 8) {
5172 neon_load_reg64(cpu_V1, rm);
5173 } else {
5174 neon_load_reg64(cpu_V1, rm + 1);
5175 imm -= 8;
5176 }
5177 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5178 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5179 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5180 } else {
5181 /* BUGFIX */
5182 neon_load_reg64(cpu_V0, rn);
5183 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5184 neon_load_reg64(cpu_V1, rm);
5185 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5186 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5187 }
5188 neon_store_reg64(cpu_V0, rd);
5189 if (q) {
5190 neon_store_reg64(cpu_V1, rd + 1);
5191 }
5192 } else if ((insn & (1 << 11)) == 0) {
5193 /* Two register misc. */
5194 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5195 size = (insn >> 18) & 3;
5196 switch (op) {
5197 case 0: /* VREV64 */
5198 if (size == 3)
5199 return 1;
5200 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5201 NEON_GET_REG(T0, rm, pass * 2);
5202 NEON_GET_REG(T1, rm, pass * 2 + 1);
5203 switch (size) {
5204 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5205 case 1: gen_swap_half(cpu_T[0]); break;
5206 case 2: /* no-op */ break;
5207 default: abort();
5208 }
5209 NEON_SET_REG(T0, rd, pass * 2 + 1);
5210 if (size == 2) {
5211 NEON_SET_REG(T1, rd, pass * 2);
5212 } else {
5213 gen_op_movl_T0_T1();
5214 switch (size) {
5215 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5216 case 1: gen_swap_half(cpu_T[0]); break;
5217 default: abort();
5218 }
5219 NEON_SET_REG(T0, rd, pass * 2);
5220 }
5221 }
5222 break;
5223 case 4: case 5: /* VPADDL */
5224 case 12: case 13: /* VPADAL */
5225 if (size == 3)
5226 return 1;
5227 for (pass = 0; pass < q + 1; pass++) {
5228 tmp = neon_load_reg(rm, pass * 2);
5229 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5230 tmp = neon_load_reg(rm, pass * 2 + 1);
5231 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5232 switch (size) {
5233 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5234 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5235 case 2: tcg_gen_add_i64(CPU_V001); break;
5236 default: abort();
5237 }
5238 if (op >= 12) {
5239 /* Accumulate. */
5240 neon_load_reg64(cpu_V1, rd + pass);
5241 gen_neon_addl(size);
5242 }
5243 neon_store_reg64(cpu_V0, rd + pass);
5244 }
5245 break;
5246 case 33: /* VTRN */
5247 if (size == 2) {
5248 for (n = 0; n < (q ? 4 : 2); n += 2) {
5249 NEON_GET_REG(T0, rm, n);
5250 NEON_GET_REG(T1, rd, n + 1);
5251 NEON_SET_REG(T1, rm, n);
5252 NEON_SET_REG(T0, rd, n + 1);
5253 }
5254 } else {
5255 goto elementwise;
5256 }
5257 break;
5258 case 34: /* VUZP */
5259 /* Reg Before After
5260 Rd A3 A2 A1 A0 B2 B0 A2 A0
5261 Rm B3 B2 B1 B0 B3 B1 A3 A1
5262 */
5263 if (size == 3)
5264 return 1;
5265 gen_neon_unzip(rd, q, 0, size);
5266 gen_neon_unzip(rm, q, 4, size);
5267 if (q) {
5268 static int unzip_order_q[8] =
5269 {0, 2, 4, 6, 1, 3, 5, 7};
5270 for (n = 0; n < 8; n++) {
5271 int reg = (n < 4) ? rd : rm;
5272 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5273 NEON_SET_REG(T0, reg, n % 4);
5274 }
5275 } else {
5276 static int unzip_order[4] =
5277 {0, 4, 1, 5};
5278 for (n = 0; n < 4; n++) {
5279 int reg = (n < 2) ? rd : rm;
5280 gen_neon_movl_T0_scratch(unzip_order[n]);
5281 NEON_SET_REG(T0, reg, n % 2);
5282 }
5283 }
5284 break;
5285 case 35: /* VZIP */
5286 /* Reg Before After
5287 Rd A3 A2 A1 A0 B1 A1 B0 A0
5288 Rm B3 B2 B1 B0 B3 A3 B2 A2
5289 */
5290 if (size == 3)
5291 return 1;
5292 count = (q ? 4 : 2);
5293 for (n = 0; n < count; n++) {
5294 NEON_GET_REG(T0, rd, n);
5295 NEON_GET_REG(T1, rd, n);
5296 switch (size) {
5297 case 0: gen_helper_neon_zip_u8(); break;
5298 case 1: gen_helper_neon_zip_u16(); break;
5299 case 2: /* no-op */; break;
5300 default: abort();
5301 }
5302 gen_neon_movl_scratch_T0(n * 2);
5303 gen_neon_movl_scratch_T1(n * 2 + 1);
5304 }
5305 for (n = 0; n < count * 2; n++) {
5306 int reg = (n < count) ? rd : rm;
5307 gen_neon_movl_T0_scratch(n);
5308 NEON_SET_REG(T0, reg, n % count);
5309 }
5310 break;
5311 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5312 if (size == 3)
5313 return 1;
5314 TCGV_UNUSED(tmp2);
5315 for (pass = 0; pass < 2; pass++) {
5316 neon_load_reg64(cpu_V0, rm + pass);
5317 tmp = new_tmp();
5318 if (op == 36 && q == 0) {
5319 gen_neon_narrow(size, tmp, cpu_V0);
5320 } else if (q) {
5321 gen_neon_narrow_satu(size, tmp, cpu_V0);
5322 } else {
5323 gen_neon_narrow_sats(size, tmp, cpu_V0);
5324 }
5325 if (pass == 0) {
5326 tmp2 = tmp;
5327 } else {
5328 neon_store_reg(rd, 0, tmp2);
5329 neon_store_reg(rd, 1, tmp);
5330 }
5331 }
5332 break;
5333 case 38: /* VSHLL */
5334 if (q || size == 3)
5335 return 1;
5336 tmp = neon_load_reg(rm, 0);
5337 tmp2 = neon_load_reg(rm, 1);
5338 for (pass = 0; pass < 2; pass++) {
5339 if (pass == 1)
5340 tmp = tmp2;
5341 gen_neon_widen(cpu_V0, tmp, size, 1);
5342 neon_store_reg64(cpu_V0, rd + pass);
5343 }
5344 break;
5345 default:
5346 elementwise:
5347 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5348 if (op == 30 || op == 31 || op >= 58) {
5349 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5350 neon_reg_offset(rm, pass));
5351 } else {
5352 NEON_GET_REG(T0, rm, pass);
5353 }
5354 switch (op) {
5355 case 1: /* VREV32 */
5356 switch (size) {
5357 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5358 case 1: gen_swap_half(cpu_T[0]); break;
5359 default: return 1;
5360 }
5361 break;
5362 case 2: /* VREV16 */
5363 if (size != 0)
5364 return 1;
5365 gen_rev16(cpu_T[0]);
5366 break;
5367 case 8: /* CLS */
5368 switch (size) {
5369 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5370 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5371 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5372 default: return 1;
5373 }
5374 break;
5375 case 9: /* CLZ */
5376 switch (size) {
5377 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5378 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5379 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5380 default: return 1;
5381 }
5382 break;
5383 case 10: /* CNT */
5384 if (size != 0)
5385 return 1;
5386 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5387 break;
5388 case 11: /* VNOT */
5389 if (size != 0)
5390 return 1;
5391 gen_op_notl_T0();
5392 break;
5393 case 14: /* VQABS */
5394 switch (size) {
5395 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5396 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5397 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5398 default: return 1;
5399 }
5400 break;
5401 case 15: /* VQNEG */
5402 switch (size) {
5403 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5404 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5405 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5406 default: return 1;
5407 }
5408 break;
5409 case 16: case 19: /* VCGT #0, VCLE #0 */
5410 gen_op_movl_T1_im(0);
5411 switch(size) {
5412 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5413 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5414 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5415 default: return 1;
5416 }
5417 if (op == 19)
5418 gen_op_notl_T0();
5419 break;
5420 case 17: case 20: /* VCGE #0, VCLT #0 */
5421 gen_op_movl_T1_im(0);
5422 switch(size) {
5423 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5424 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5425 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5426 default: return 1;
5427 }
5428 if (op == 20)
5429 gen_op_notl_T0();
5430 break;
5431 case 18: /* VCEQ #0 */
5432 gen_op_movl_T1_im(0);
5433 switch(size) {
5434 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5435 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5436 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5437 default: return 1;
5438 }
5439 break;
5440 case 22: /* VABS */
5441 switch(size) {
5442 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5443 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5444 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5445 default: return 1;
5446 }
5447 break;
5448 case 23: /* VNEG */
5449 gen_op_movl_T1_im(0);
5450 if (size == 3)
5451 return 1;
5452 gen_neon_rsb(size);
5453 break;
5454 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5455 gen_op_movl_T1_im(0);
5456 gen_helper_neon_cgt_f32(CPU_T001);
5457 if (op == 27)
5458 gen_op_notl_T0();
5459 break;
5460 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5461 gen_op_movl_T1_im(0);
5462 gen_helper_neon_cge_f32(CPU_T001);
5463 if (op == 28)
5464 gen_op_notl_T0();
5465 break;
5466 case 26: /* Float VCEQ #0 */
5467 gen_op_movl_T1_im(0);
5468 gen_helper_neon_ceq_f32(CPU_T001);
5469 break;
5470 case 30: /* Float VABS */
5471 gen_vfp_abs(0);
5472 break;
5473 case 31: /* Float VNEG */
5474 gen_vfp_neg(0);
5475 break;
5476 case 32: /* VSWP */
5477 NEON_GET_REG(T1, rd, pass);
5478 NEON_SET_REG(T1, rm, pass);
5479 break;
5480 case 33: /* VTRN */
5481 NEON_GET_REG(T1, rd, pass);
5482 switch (size) {
5483 case 0: gen_helper_neon_trn_u8(); break;
5484 case 1: gen_helper_neon_trn_u16(); break;
5485 case 2: abort();
5486 default: return 1;
5487 }
5488 NEON_SET_REG(T1, rm, pass);
5489 break;
5490 case 56: /* Integer VRECPE */
5491 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5492 break;
5493 case 57: /* Integer VRSQRTE */
5494 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5495 break;
5496 case 58: /* Float VRECPE */
5497 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5498 break;
5499 case 59: /* Float VRSQRTE */
5500 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5501 break;
5502 case 60: /* VCVT.F32.S32 */
5503 gen_vfp_tosiz(0);
5504 break;
5505 case 61: /* VCVT.F32.U32 */
5506 gen_vfp_touiz(0);
5507 break;
5508 case 62: /* VCVT.S32.F32 */
5509 gen_vfp_sito(0);
5510 break;
5511 case 63: /* VCVT.U32.F32 */
5512 gen_vfp_uito(0);
5513 break;
5514 default:
5515 /* Reserved: 21, 29, 39-56 */
5516 return 1;
5517 }
5518 if (op == 30 || op == 31 || op >= 58) {
5519 tcg_gen_st_f32(cpu_F0s, cpu_env,
5520 neon_reg_offset(rd, pass));
5521 } else {
5522 NEON_SET_REG(T0, rd, pass);
5523 }
5524 }
5525 break;
5526 }
5527 } else if ((insn & (1 << 10)) == 0) {
5528 /* VTBL, VTBX. */
5529 n = ((insn >> 5) & 0x18) + 8;
5530 if (insn & (1 << 6)) {
5531 tmp = neon_load_reg(rd, 0);
5532 } else {
5533 tmp = new_tmp();
5534 tcg_gen_movi_i32(tmp, 0);
5535 }
5536 tmp2 = neon_load_reg(rm, 0);
5537 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5538 tcg_const_i32(n));
5539 dead_tmp(tmp);
5540 if (insn & (1 << 6)) {
5541 tmp = neon_load_reg(rd, 1);
5542 } else {
5543 tmp = new_tmp();
5544 tcg_gen_movi_i32(tmp, 0);
5545 }
5546 tmp3 = neon_load_reg(rm, 1);
5547 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5548 tcg_const_i32(n));
5549 neon_store_reg(rd, 0, tmp2);
5550 neon_store_reg(rd, 1, tmp3);
5551 dead_tmp(tmp);
5552 } else if ((insn & 0x380) == 0) {
5553 /* VDUP */
5554 if (insn & (1 << 19)) {
5555 NEON_SET_REG(T0, rm, 1);
5556 } else {
5557 NEON_SET_REG(T0, rm, 0);
5558 }
5559 if (insn & (1 << 16)) {
5560 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5561 } else if (insn & (1 << 17)) {
5562 if ((insn >> 18) & 1)
5563 gen_neon_dup_high16(cpu_T[0]);
5564 else
5565 gen_neon_dup_low16(cpu_T[0]);
5566 }
5567 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5568 NEON_SET_REG(T0, rd, pass);
5569 }
5570 } else {
5571 return 1;
5572 }
5573 }
5574 }
5575 return 0;
5576 }
5577
disas_cp14_read(CPUState * env,DisasContext * s,uint32_t insn)5578 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5579 {
5580 int crn = (insn >> 16) & 0xf;
5581 int crm = insn & 0xf;
5582 int op1 = (insn >> 21) & 7;
5583 int op2 = (insn >> 5) & 7;
5584 int rt = (insn >> 12) & 0xf;
5585 TCGv tmp;
5586
5587 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5588 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5589 /* TEECR */
5590 if (IS_USER(s))
5591 return 1;
5592 tmp = load_cpu_field(teecr);
5593 store_reg(s, rt, tmp);
5594 return 0;
5595 }
5596 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5597 /* TEEHBR */
5598 if (IS_USER(s) && (env->teecr & 1))
5599 return 1;
5600 tmp = load_cpu_field(teehbr);
5601 store_reg(s, rt, tmp);
5602 return 0;
5603 }
5604 }
5605 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5606 op1, crn, crm, op2);
5607 return 1;
5608 }
5609
disas_cp14_write(CPUState * env,DisasContext * s,uint32_t insn)5610 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5611 {
5612 int crn = (insn >> 16) & 0xf;
5613 int crm = insn & 0xf;
5614 int op1 = (insn >> 21) & 7;
5615 int op2 = (insn >> 5) & 7;
5616 int rt = (insn >> 12) & 0xf;
5617 TCGv tmp;
5618
5619 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5620 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5621 /* TEECR */
5622 if (IS_USER(s))
5623 return 1;
5624 tmp = load_reg(s, rt);
5625 gen_helper_set_teecr(cpu_env, tmp);
5626 dead_tmp(tmp);
5627 return 0;
5628 }
5629 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5630 /* TEEHBR */
5631 if (IS_USER(s) && (env->teecr & 1))
5632 return 1;
5633 tmp = load_reg(s, rt);
5634 store_cpu_field(tmp, teehbr);
5635 return 0;
5636 }
5637 }
5638 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5639 op1, crn, crm, op2);
5640 return 1;
5641 }
5642
disas_coproc_insn(CPUState * env,DisasContext * s,uint32_t insn)5643 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5644 {
5645 int cpnum;
5646
5647 cpnum = (insn >> 8) & 0xf;
5648 if (arm_feature(env, ARM_FEATURE_XSCALE)
5649 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5650 return 1;
5651
5652 switch (cpnum) {
5653 case 0:
5654 case 1:
5655 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5656 return disas_iwmmxt_insn(env, s, insn);
5657 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5658 return disas_dsp_insn(env, s, insn);
5659 }
5660 return 1;
5661 case 10:
5662 case 11:
5663 return disas_vfp_insn (env, s, insn);
5664 case 14:
5665 /* Coprocessors 7-15 are architecturally reserved by ARM.
5666 Unfortunately Intel decided to ignore this. */
5667 if (arm_feature(env, ARM_FEATURE_XSCALE))
5668 goto board;
5669 if (insn & (1 << 20))
5670 return disas_cp14_read(env, s, insn);
5671 else
5672 return disas_cp14_write(env, s, insn);
5673 case 15:
5674 return disas_cp15_insn (env, s, insn);
5675 default:
5676 board:
5677 /* Unknown coprocessor. See if the board has hooked it. */
5678 return disas_cp_insn (env, s, insn);
5679 }
5680 }
5681
5682
5683 /* Store a 64-bit value to a register pair. Clobbers val. */
gen_storeq_reg(DisasContext * s,int rlow,int rhigh,TCGv_i64 val)5684 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5685 {
5686 TCGv tmp;
5687 tmp = new_tmp();
5688 tcg_gen_trunc_i64_i32(tmp, val);
5689 store_reg(s, rlow, tmp);
5690 tmp = new_tmp();
5691 tcg_gen_shri_i64(val, val, 32);
5692 tcg_gen_trunc_i64_i32(tmp, val);
5693 store_reg(s, rhigh, tmp);
5694 }
5695
5696 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
gen_addq_lo(DisasContext * s,TCGv_i64 val,int rlow)5697 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5698 {
5699 TCGv_i64 tmp;
5700 TCGv tmp2;
5701
5702 /* Load value and extend to 64 bits. */
5703 tmp = tcg_temp_new_i64();
5704 tmp2 = load_reg(s, rlow);
5705 tcg_gen_extu_i32_i64(tmp, tmp2);
5706 dead_tmp(tmp2);
5707 tcg_gen_add_i64(val, val, tmp);
5708 }
5709
5710 /* load and add a 64-bit value from a register pair. */
gen_addq(DisasContext * s,TCGv_i64 val,int rlow,int rhigh)5711 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5712 {
5713 TCGv_i64 tmp;
5714 TCGv tmpl;
5715 TCGv tmph;
5716
5717 /* Load 64-bit value rd:rn. */
5718 tmpl = load_reg(s, rlow);
5719 tmph = load_reg(s, rhigh);
5720 tmp = tcg_temp_new_i64();
5721 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5722 dead_tmp(tmpl);
5723 dead_tmp(tmph);
5724 tcg_gen_add_i64(val, val, tmp);
5725 }
5726
5727 /* Set N and Z flags from a 64-bit value. */
gen_logicq_cc(TCGv_i64 val)5728 static void gen_logicq_cc(TCGv_i64 val)
5729 {
5730 TCGv tmp = new_tmp();
5731 gen_helper_logicq_cc(tmp, val);
5732 gen_logic_CC(tmp);
5733 dead_tmp(tmp);
5734 }
5735
5736
5737 #ifdef CONFIG_TRACE
5738
5739 #define gen_traceInsn() gen_helper_traceInsn()
5740
5741 static void
gen_traceTicks(int count)5742 gen_traceTicks( int count )
5743 {
5744 TCGv tmp = tcg_temp_new_i32();
5745 tcg_gen_movi_i32(tmp, count);
5746 gen_helper_traceTicks(tmp);
5747 tcg_temp_free_i32(tmp);
5748 }
5749
5750 static void
gen_traceBB(uint64_t bbNum,target_phys_addr_t tb)5751 gen_traceBB( uint64_t bbNum, target_phys_addr_t tb )
5752 {
5753 #if HOST_LONG_BITS == 32
5754 TCGv_i64 tmpNum = tcg_temp_new_i64();
5755 TCGv_i32 tmpTb = tcg_temp_new_i32();
5756
5757 tcg_gen_movi_i64(tmpNum, (int64_t)bbNum);
5758 tcg_gen_movi_i32(tmpTb, (int32_t)tb);
5759 gen_helper_traceBB32(tmpNum, tmpTb);
5760 tcg_temp_free_i32(tmpTb);
5761 tcg_temp_free_i64(tmpNum);
5762 #elif HOST_LONG_BITS == 64
5763 TCGv_i64 tmpNum = tcg_temp_new_i64();
5764 TCGv_i64 tmpTb = tcg_temp_new_i32();
5765
5766 tcg_gen_movi_i64(tmpNum, (int64_t)bbNum);
5767 tcg_gen_movi_i64(tmpTb, (int64_t)tb);
5768 gen_helper_traceBB32(tmpNum, tmpTb);
5769 tcg_temp_free_i64(tmpTb);
5770 tcg_temp_free_i64(tmpNum);
5771 #endif
5772 }
5773 #endif /* CONFIG_TRACE */
5774
disas_arm_insn(CPUState * env,DisasContext * s)5775 static void disas_arm_insn(CPUState * env, DisasContext *s)
5776 {
5777 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5778 #ifdef CONFIG_TRACE
5779 int ticks;
5780 #endif
5781 TCGv tmp;
5782 TCGv tmp2;
5783 TCGv tmp3;
5784 TCGv addr;
5785 TCGv_i64 tmp64;
5786
5787 insn = ldl_code(s->pc);
5788 #ifdef CONFIG_TRACE
5789 if (tracing) {
5790 trace_add_insn(insn, 0);
5791 ticks = get_insn_ticks_arm(insn);
5792 gen_traceInsn();
5793 }
5794 #endif
5795 s->pc += 4;
5796
5797 /* M variants do not implement ARM mode. */
5798 if (IS_M(env))
5799 goto illegal_op;
5800 cond = insn >> 28;
5801 if (cond == 0xf){
5802 #ifdef CONFIG_TRACE
5803 if (tracing) {
5804 gen_traceTicks(ticks);
5805 }
5806 #endif
5807 /* Unconditional instructions. */
5808 if (((insn >> 25) & 7) == 1) {
5809 /* NEON Data processing. */
5810 if (!arm_feature(env, ARM_FEATURE_NEON))
5811 goto illegal_op;
5812
5813 if (disas_neon_data_insn(env, s, insn))
5814 goto illegal_op;
5815 return;
5816 }
5817 if ((insn & 0x0f100000) == 0x04000000) {
5818 /* NEON load/store. */
5819 if (!arm_feature(env, ARM_FEATURE_NEON))
5820 goto illegal_op;
5821
5822 if (disas_neon_ls_insn(env, s, insn))
5823 goto illegal_op;
5824 return;
5825 }
5826 if ((insn & 0x0d70f000) == 0x0550f000)
5827 return; /* PLD */
5828 else if ((insn & 0x0ffffdff) == 0x01010000) {
5829 ARCH(6);
5830 /* setend */
5831 if (insn & (1 << 9)) {
5832 /* BE8 mode not implemented. */
5833 goto illegal_op;
5834 }
5835 return;
5836 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5837 switch ((insn >> 4) & 0xf) {
5838 case 1: /* clrex */
5839 ARCH(6K);
5840 gen_helper_clrex(cpu_env);
5841 return;
5842 case 4: /* dsb */
5843 case 5: /* dmb */
5844 case 6: /* isb */
5845 ARCH(7);
5846 /* We don't emulate caches so these are a no-op. */
5847 return;
5848 default:
5849 goto illegal_op;
5850 }
5851 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5852 /* srs */
5853 uint32_t offset;
5854 if (IS_USER(s))
5855 goto illegal_op;
5856 ARCH(6);
5857 op1 = (insn & 0x1f);
5858 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5859 addr = load_reg(s, 13);
5860 } else {
5861 addr = new_tmp();
5862 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5863 }
5864 i = (insn >> 23) & 3;
5865 switch (i) {
5866 case 0: offset = -4; break; /* DA */
5867 case 1: offset = -8; break; /* DB */
5868 case 2: offset = 0; break; /* IA */
5869 case 3: offset = 4; break; /* IB */
5870 default: abort();
5871 }
5872 if (offset)
5873 tcg_gen_addi_i32(addr, addr, offset);
5874 tmp = load_reg(s, 14);
5875 gen_st32(tmp, addr, 0);
5876 tmp = new_tmp();
5877 gen_helper_cpsr_read(tmp);
5878 tcg_gen_addi_i32(addr, addr, 4);
5879 gen_st32(tmp, addr, 0);
5880 if (insn & (1 << 21)) {
5881 /* Base writeback. */
5882 switch (i) {
5883 case 0: offset = -8; break;
5884 case 1: offset = -4; break;
5885 case 2: offset = 4; break;
5886 case 3: offset = 0; break;
5887 default: abort();
5888 }
5889 if (offset)
5890 tcg_gen_addi_i32(addr, tmp, offset);
5891 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5892 gen_movl_reg_T1(s, 13);
5893 } else {
5894 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5895 }
5896 } else {
5897 dead_tmp(addr);
5898 }
5899 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5900 /* rfe */
5901 uint32_t offset;
5902 if (IS_USER(s))
5903 goto illegal_op;
5904 ARCH(6);
5905 rn = (insn >> 16) & 0xf;
5906 addr = load_reg(s, rn);
5907 i = (insn >> 23) & 3;
5908 switch (i) {
5909 case 0: offset = -4; break; /* DA */
5910 case 1: offset = -8; break; /* DB */
5911 case 2: offset = 0; break; /* IA */
5912 case 3: offset = 4; break; /* IB */
5913 default: abort();
5914 }
5915 if (offset)
5916 tcg_gen_addi_i32(addr, addr, offset);
5917 /* Load PC into tmp and CPSR into tmp2. */
5918 tmp = gen_ld32(addr, 0);
5919 tcg_gen_addi_i32(addr, addr, 4);
5920 tmp2 = gen_ld32(addr, 0);
5921 if (insn & (1 << 21)) {
5922 /* Base writeback. */
5923 switch (i) {
5924 case 0: offset = -8; break;
5925 case 1: offset = -4; break;
5926 case 2: offset = 4; break;
5927 case 3: offset = 0; break;
5928 default: abort();
5929 }
5930 if (offset)
5931 tcg_gen_addi_i32(addr, addr, offset);
5932 store_reg(s, rn, addr);
5933 } else {
5934 dead_tmp(addr);
5935 }
5936 gen_rfe(s, tmp, tmp2);
5937 } else if ((insn & 0x0e000000) == 0x0a000000) {
5938 /* branch link and change to thumb (blx <offset>) */
5939 int32_t offset;
5940
5941 val = (uint32_t)s->pc;
5942 tmp = new_tmp();
5943 tcg_gen_movi_i32(tmp, val);
5944 store_reg(s, 14, tmp);
5945 /* Sign-extend the 24-bit offset */
5946 offset = (((int32_t)insn) << 8) >> 8;
5947 /* offset * 4 + bit24 * 2 + (thumb bit) */
5948 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5949 /* pipeline offset */
5950 val += 4;
5951 gen_bx_im(s, val);
5952 return;
5953 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5954 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5955 /* iWMMXt register transfer. */
5956 if (env->cp15.c15_cpar & (1 << 1))
5957 if (!disas_iwmmxt_insn(env, s, insn))
5958 return;
5959 }
5960 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5961 /* Coprocessor double register transfer. */
5962 } else if ((insn & 0x0f000010) == 0x0e000010) {
5963 /* Additional coprocessor register transfer. */
5964 } else if ((insn & 0x0ff10020) == 0x01000000) {
5965 uint32_t mask;
5966 uint32_t val;
5967 /* cps (privileged) */
5968 if (IS_USER(s))
5969 return;
5970 mask = val = 0;
5971 if (insn & (1 << 19)) {
5972 if (insn & (1 << 8))
5973 mask |= CPSR_A;
5974 if (insn & (1 << 7))
5975 mask |= CPSR_I;
5976 if (insn & (1 << 6))
5977 mask |= CPSR_F;
5978 if (insn & (1 << 18))
5979 val |= mask;
5980 }
5981 if (insn & (1 << 17)) {
5982 mask |= CPSR_M;
5983 val |= (insn & 0x1f);
5984 }
5985 if (mask) {
5986 gen_op_movl_T0_im(val);
5987 gen_set_psr_T0(s, mask, 0);
5988 }
5989 return;
5990 }
5991 goto illegal_op;
5992 }
5993 if (cond != 0xe) {
5994 #ifdef CONFIG_TRACE
5995 if (tracing) {
5996 /* a non-executed conditional instruction takes */
5997 /* only 1 cycle */
5998 gen_traceTicks(1);
5999 ticks -= 1;
6000 }
6001 #endif
6002 /* if not always execute, we generate a conditional jump to
6003 next instruction */
6004 s->condlabel = gen_new_label();
6005 gen_test_cc(cond ^ 1, s->condlabel);
6006 s->condjmp = 1;
6007 }
6008 #ifdef CONFIG_TRACE
6009 if (tracing && ticks > 0) {
6010 gen_traceTicks(ticks);
6011 }
6012 #endif
6013 if ((insn & 0x0f900000) == 0x03000000) {
6014 if ((insn & (1 << 21)) == 0) {
6015 ARCH(6T2);
6016 rd = (insn >> 12) & 0xf;
6017 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6018 if ((insn & (1 << 22)) == 0) {
6019 /* MOVW */
6020 tmp = new_tmp();
6021 tcg_gen_movi_i32(tmp, val);
6022 } else {
6023 /* MOVT */
6024 tmp = load_reg(s, rd);
6025 tcg_gen_ext16u_i32(tmp, tmp);
6026 tcg_gen_ori_i32(tmp, tmp, val << 16);
6027 }
6028 store_reg(s, rd, tmp);
6029 } else {
6030 if (((insn >> 12) & 0xf) != 0xf)
6031 goto illegal_op;
6032 if (((insn >> 16) & 0xf) == 0) {
6033 gen_nop_hint(s, insn & 0xff);
6034 } else {
6035 /* CPSR = immediate */
6036 val = insn & 0xff;
6037 shift = ((insn >> 8) & 0xf) * 2;
6038 if (shift)
6039 val = (val >> shift) | (val << (32 - shift));
6040 gen_op_movl_T0_im(val);
6041 i = ((insn & (1 << 22)) != 0);
6042 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
6043 goto illegal_op;
6044 }
6045 }
6046 } else if ((insn & 0x0f900000) == 0x01000000
6047 && (insn & 0x00000090) != 0x00000090) {
6048 /* miscellaneous instructions */
6049 op1 = (insn >> 21) & 3;
6050 sh = (insn >> 4) & 0xf;
6051 rm = insn & 0xf;
6052 switch (sh) {
6053 case 0x0: /* move program status register */
6054 if (op1 & 1) {
6055 /* PSR = reg */
6056 gen_movl_T0_reg(s, rm);
6057 i = ((op1 & 2) != 0);
6058 if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
6059 goto illegal_op;
6060 } else {
6061 /* reg = PSR */
6062 rd = (insn >> 12) & 0xf;
6063 if (op1 & 2) {
6064 if (IS_USER(s))
6065 goto illegal_op;
6066 tmp = load_cpu_field(spsr);
6067 } else {
6068 tmp = new_tmp();
6069 gen_helper_cpsr_read(tmp);
6070 }
6071 store_reg(s, rd, tmp);
6072 }
6073 break;
6074 case 0x1:
6075 if (op1 == 1) {
6076 /* branch/exchange thumb (bx). */
6077 tmp = load_reg(s, rm);
6078 gen_bx(s, tmp);
6079 } else if (op1 == 3) {
6080 /* clz */
6081 rd = (insn >> 12) & 0xf;
6082 tmp = load_reg(s, rm);
6083 gen_helper_clz(tmp, tmp);
6084 store_reg(s, rd, tmp);
6085 } else {
6086 goto illegal_op;
6087 }
6088 break;
6089 case 0x2:
6090 if (op1 == 1) {
6091 ARCH(5J); /* bxj */
6092 /* Trivial implementation equivalent to bx. */
6093 tmp = load_reg(s, rm);
6094 gen_bx(s, tmp);
6095 } else {
6096 goto illegal_op;
6097 }
6098 break;
6099 case 0x3:
6100 if (op1 != 1)
6101 goto illegal_op;
6102
6103 /* branch link/exchange thumb (blx) */
6104 tmp = load_reg(s, rm);
6105 tmp2 = new_tmp();
6106 tcg_gen_movi_i32(tmp2, s->pc);
6107 store_reg(s, 14, tmp2);
6108 gen_bx(s, tmp);
6109 break;
6110 case 0x5: /* saturating add/subtract */
6111 rd = (insn >> 12) & 0xf;
6112 rn = (insn >> 16) & 0xf;
6113 tmp = load_reg(s, rm);
6114 tmp2 = load_reg(s, rn);
6115 if (op1 & 2)
6116 gen_helper_double_saturate(tmp2, tmp2);
6117 if (op1 & 1)
6118 gen_helper_sub_saturate(tmp, tmp, tmp2);
6119 else
6120 gen_helper_add_saturate(tmp, tmp, tmp2);
6121 dead_tmp(tmp2);
6122 store_reg(s, rd, tmp);
6123 break;
6124 case 7: /* bkpt */
6125 gen_set_condexec(s);
6126 gen_set_pc_im(s->pc - 4);
6127 gen_exception(EXCP_BKPT);
6128 s->is_jmp = DISAS_JUMP;
6129 break;
6130 case 0x8: /* signed multiply */
6131 case 0xa:
6132 case 0xc:
6133 case 0xe:
6134 rs = (insn >> 8) & 0xf;
6135 rn = (insn >> 12) & 0xf;
6136 rd = (insn >> 16) & 0xf;
6137 if (op1 == 1) {
6138 /* (32 * 16) >> 16 */
6139 tmp = load_reg(s, rm);
6140 tmp2 = load_reg(s, rs);
6141 if (sh & 4)
6142 tcg_gen_sari_i32(tmp2, tmp2, 16);
6143 else
6144 gen_sxth(tmp2);
6145 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6146 tcg_gen_shri_i64(tmp64, tmp64, 16);
6147 tmp = new_tmp();
6148 tcg_gen_trunc_i64_i32(tmp, tmp64);
6149 if ((sh & 2) == 0) {
6150 tmp2 = load_reg(s, rn);
6151 gen_helper_add_setq(tmp, tmp, tmp2);
6152 dead_tmp(tmp2);
6153 }
6154 store_reg(s, rd, tmp);
6155 } else {
6156 /* 16 * 16 */
6157 tmp = load_reg(s, rm);
6158 tmp2 = load_reg(s, rs);
6159 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6160 dead_tmp(tmp2);
6161 if (op1 == 2) {
6162 tmp64 = tcg_temp_new_i64();
6163 tcg_gen_ext_i32_i64(tmp64, tmp);
6164 dead_tmp(tmp);
6165 gen_addq(s, tmp64, rn, rd);
6166 gen_storeq_reg(s, rn, rd, tmp64);
6167 } else {
6168 if (op1 == 0) {
6169 tmp2 = load_reg(s, rn);
6170 gen_helper_add_setq(tmp, tmp, tmp2);
6171 dead_tmp(tmp2);
6172 }
6173 store_reg(s, rd, tmp);
6174 }
6175 }
6176 break;
6177 default:
6178 goto illegal_op;
6179 }
6180 } else if (((insn & 0x0e000000) == 0 &&
6181 (insn & 0x00000090) != 0x90) ||
6182 ((insn & 0x0e000000) == (1 << 25))) {
6183 int set_cc, logic_cc, shiftop;
6184
6185 op1 = (insn >> 21) & 0xf;
6186 set_cc = (insn >> 20) & 1;
6187 logic_cc = table_logic_cc[op1] & set_cc;
6188
6189 /* data processing instruction */
6190 if (insn & (1 << 25)) {
6191 /* immediate operand */
6192 val = insn & 0xff;
6193 shift = ((insn >> 8) & 0xf) * 2;
6194 if (shift) {
6195 val = (val >> shift) | (val << (32 - shift));
6196 }
6197 tmp2 = new_tmp();
6198 tcg_gen_movi_i32(tmp2, val);
6199 if (logic_cc && shift) {
6200 gen_set_CF_bit31(tmp2);
6201 }
6202 } else {
6203 /* register */
6204 rm = (insn) & 0xf;
6205 tmp2 = load_reg(s, rm);
6206 shiftop = (insn >> 5) & 3;
6207 if (!(insn & (1 << 4))) {
6208 shift = (insn >> 7) & 0x1f;
6209 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6210 } else {
6211 rs = (insn >> 8) & 0xf;
6212 tmp = load_reg(s, rs);
6213 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6214 }
6215 }
6216 if (op1 != 0x0f && op1 != 0x0d) {
6217 rn = (insn >> 16) & 0xf;
6218 tmp = load_reg(s, rn);
6219 } else {
6220 TCGV_UNUSED(tmp);
6221 }
6222 rd = (insn >> 12) & 0xf;
6223 switch(op1) {
6224 case 0x00:
6225 tcg_gen_and_i32(tmp, tmp, tmp2);
6226 if (logic_cc) {
6227 gen_logic_CC(tmp);
6228 }
6229 store_reg_bx(env, s, rd, tmp);
6230 break;
6231 case 0x01:
6232 tcg_gen_xor_i32(tmp, tmp, tmp2);
6233 if (logic_cc) {
6234 gen_logic_CC(tmp);
6235 }
6236 store_reg_bx(env, s, rd, tmp);
6237 break;
6238 case 0x02:
6239 if (set_cc && rd == 15) {
6240 /* SUBS r15, ... is used for exception return. */
6241 if (IS_USER(s)) {
6242 goto illegal_op;
6243 }
6244 gen_helper_sub_cc(tmp, tmp, tmp2);
6245 gen_exception_return(s, tmp);
6246 } else {
6247 if (set_cc) {
6248 gen_helper_sub_cc(tmp, tmp, tmp2);
6249 } else {
6250 tcg_gen_sub_i32(tmp, tmp, tmp2);
6251 }
6252 store_reg_bx(env, s, rd, tmp);
6253 }
6254 break;
6255 case 0x03:
6256 if (set_cc) {
6257 gen_helper_sub_cc(tmp, tmp2, tmp);
6258 } else {
6259 tcg_gen_sub_i32(tmp, tmp2, tmp);
6260 }
6261 store_reg_bx(env, s, rd, tmp);
6262 break;
6263 case 0x04:
6264 if (set_cc) {
6265 gen_helper_add_cc(tmp, tmp, tmp2);
6266 } else {
6267 tcg_gen_add_i32(tmp, tmp, tmp2);
6268 }
6269 store_reg_bx(env, s, rd, tmp);
6270 break;
6271 case 0x05:
6272 if (set_cc) {
6273 gen_helper_adc_cc(tmp, tmp, tmp2);
6274 } else {
6275 gen_add_carry(tmp, tmp, tmp2);
6276 }
6277 store_reg_bx(env, s, rd, tmp);
6278 break;
6279 case 0x06:
6280 if (set_cc) {
6281 gen_helper_sbc_cc(tmp, tmp, tmp2);
6282 } else {
6283 gen_sub_carry(tmp, tmp, tmp2);
6284 }
6285 store_reg_bx(env, s, rd, tmp);
6286 break;
6287 case 0x07:
6288 if (set_cc) {
6289 gen_helper_sbc_cc(tmp, tmp2, tmp);
6290 } else {
6291 gen_sub_carry(tmp, tmp2, tmp);
6292 }
6293 store_reg_bx(env, s, rd, tmp);
6294 break;
6295 case 0x08:
6296 if (set_cc) {
6297 tcg_gen_and_i32(tmp, tmp, tmp2);
6298 gen_logic_CC(tmp);
6299 }
6300 dead_tmp(tmp);
6301 break;
6302 case 0x09:
6303 if (set_cc) {
6304 tcg_gen_xor_i32(tmp, tmp, tmp2);
6305 gen_logic_CC(tmp);
6306 }
6307 dead_tmp(tmp);
6308 break;
6309 case 0x0a:
6310 if (set_cc) {
6311 gen_helper_sub_cc(tmp, tmp, tmp2);
6312 }
6313 dead_tmp(tmp);
6314 break;
6315 case 0x0b:
6316 if (set_cc) {
6317 gen_helper_add_cc(tmp, tmp, tmp2);
6318 }
6319 dead_tmp(tmp);
6320 break;
6321 case 0x0c:
6322 tcg_gen_or_i32(tmp, tmp, tmp2);
6323 if (logic_cc) {
6324 gen_logic_CC(tmp);
6325 }
6326 store_reg_bx(env, s, rd, tmp);
6327 break;
6328 case 0x0d:
6329 if (logic_cc && rd == 15) {
6330 /* MOVS r15, ... is used for exception return. */
6331 if (IS_USER(s)) {
6332 goto illegal_op;
6333 }
6334 gen_exception_return(s, tmp2);
6335 } else {
6336 if (logic_cc) {
6337 gen_logic_CC(tmp2);
6338 }
6339 store_reg_bx(env, s, rd, tmp2);
6340 }
6341 break;
6342 case 0x0e:
6343 tcg_gen_bic_i32(tmp, tmp, tmp2);
6344 if (logic_cc) {
6345 gen_logic_CC(tmp);
6346 }
6347 store_reg_bx(env, s, rd, tmp);
6348 break;
6349 default:
6350 case 0x0f:
6351 tcg_gen_not_i32(tmp2, tmp2);
6352 if (logic_cc) {
6353 gen_logic_CC(tmp2);
6354 }
6355 store_reg_bx(env, s, rd, tmp2);
6356 break;
6357 }
6358 if (op1 != 0x0f && op1 != 0x0d) {
6359 dead_tmp(tmp2);
6360 }
6361 } else {
6362 /* other instructions */
6363 op1 = (insn >> 24) & 0xf;
6364 switch(op1) {
6365 case 0x0:
6366 case 0x1:
6367 /* multiplies, extra load/stores */
6368 sh = (insn >> 5) & 3;
6369 if (sh == 0) {
6370 if (op1 == 0x0) {
6371 rd = (insn >> 16) & 0xf;
6372 rn = (insn >> 12) & 0xf;
6373 rs = (insn >> 8) & 0xf;
6374 rm = (insn) & 0xf;
6375 op1 = (insn >> 20) & 0xf;
6376 switch (op1) {
6377 case 0: case 1: case 2: case 3: case 6:
6378 /* 32 bit mul */
6379 tmp = load_reg(s, rs);
6380 tmp2 = load_reg(s, rm);
6381 tcg_gen_mul_i32(tmp, tmp, tmp2);
6382 dead_tmp(tmp2);
6383 if (insn & (1 << 22)) {
6384 /* Subtract (mls) */
6385 ARCH(6T2);
6386 tmp2 = load_reg(s, rn);
6387 tcg_gen_sub_i32(tmp, tmp2, tmp);
6388 dead_tmp(tmp2);
6389 } else if (insn & (1 << 21)) {
6390 /* Add */
6391 tmp2 = load_reg(s, rn);
6392 tcg_gen_add_i32(tmp, tmp, tmp2);
6393 dead_tmp(tmp2);
6394 }
6395 if (insn & (1 << 20))
6396 gen_logic_CC(tmp);
6397 store_reg(s, rd, tmp);
6398 break;
6399 default:
6400 /* 64 bit mul */
6401 tmp = load_reg(s, rs);
6402 tmp2 = load_reg(s, rm);
6403 if (insn & (1 << 22))
6404 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6405 else
6406 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6407 if (insn & (1 << 21)) /* mult accumulate */
6408 gen_addq(s, tmp64, rn, rd);
6409 if (!(insn & (1 << 23))) { /* double accumulate */
6410 ARCH(6);
6411 gen_addq_lo(s, tmp64, rn);
6412 gen_addq_lo(s, tmp64, rd);
6413 }
6414 if (insn & (1 << 20))
6415 gen_logicq_cc(tmp64);
6416 gen_storeq_reg(s, rn, rd, tmp64);
6417 break;
6418 }
6419 } else {
6420 rn = (insn >> 16) & 0xf;
6421 rd = (insn >> 12) & 0xf;
6422 if (insn & (1 << 23)) {
6423 /* load/store exclusive */
6424 op1 = (insn >> 21) & 0x3;
6425 if (op1)
6426 ARCH(6K);
6427 else
6428 ARCH(6);
6429 gen_movl_T1_reg(s, rn);
6430 addr = cpu_T[1];
6431 if (insn & (1 << 20)) {
6432 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6433 switch (op1) {
6434 case 0: /* ldrex */
6435 tmp = gen_ld32(addr, IS_USER(s));
6436 break;
6437 case 1: /* ldrexd */
6438 tmp = gen_ld32(addr, IS_USER(s));
6439 store_reg(s, rd, tmp);
6440 tcg_gen_addi_i32(addr, addr, 4);
6441 tmp = gen_ld32(addr, IS_USER(s));
6442 rd++;
6443 break;
6444 case 2: /* ldrexb */
6445 tmp = gen_ld8u(addr, IS_USER(s));
6446 break;
6447 case 3: /* ldrexh */
6448 tmp = gen_ld16u(addr, IS_USER(s));
6449 break;
6450 default:
6451 abort();
6452 }
6453 store_reg(s, rd, tmp);
6454 } else {
6455 int label = gen_new_label();
6456 rm = insn & 0xf;
6457 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6458 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6459 0, label);
6460 tmp = load_reg(s,rm);
6461 switch (op1) {
6462 case 0: /* strex */
6463 gen_st32(tmp, addr, IS_USER(s));
6464 break;
6465 case 1: /* strexd */
6466 gen_st32(tmp, addr, IS_USER(s));
6467 tcg_gen_addi_i32(addr, addr, 4);
6468 tmp = load_reg(s, rm + 1);
6469 gen_st32(tmp, addr, IS_USER(s));
6470 break;
6471 case 2: /* strexb */
6472 gen_st8(tmp, addr, IS_USER(s));
6473 break;
6474 case 3: /* strexh */
6475 gen_st16(tmp, addr, IS_USER(s));
6476 break;
6477 default:
6478 abort();
6479 }
6480 gen_set_label(label);
6481 gen_movl_reg_T0(s, rd);
6482 }
6483 } else {
6484 /* SWP instruction */
6485 rm = (insn) & 0xf;
6486
6487 /* ??? This is not really atomic. However we know
6488 we never have multiple CPUs running in parallel,
6489 so it is good enough. */
6490 addr = load_reg(s, rn);
6491 tmp = load_reg(s, rm);
6492 if (insn & (1 << 22)) {
6493 tmp2 = gen_ld8u(addr, IS_USER(s));
6494 gen_st8(tmp, addr, IS_USER(s));
6495 } else {
6496 tmp2 = gen_ld32(addr, IS_USER(s));
6497 gen_st32(tmp, addr, IS_USER(s));
6498 }
6499 dead_tmp(addr);
6500 store_reg(s, rd, tmp2);
6501 }
6502 }
6503 } else {
6504 int address_offset;
6505 int load;
6506 /* Misc load/store */
6507 rn = (insn >> 16) & 0xf;
6508 rd = (insn >> 12) & 0xf;
6509 addr = load_reg(s, rn);
6510 if (insn & (1 << 24))
6511 gen_add_datah_offset(s, insn, 0, addr);
6512 address_offset = 0;
6513 if (insn & (1 << 20)) {
6514 /* load */
6515 switch(sh) {
6516 case 1:
6517 tmp = gen_ld16u(addr, IS_USER(s));
6518 break;
6519 case 2:
6520 tmp = gen_ld8s(addr, IS_USER(s));
6521 break;
6522 default:
6523 case 3:
6524 tmp = gen_ld16s(addr, IS_USER(s));
6525 break;
6526 }
6527 load = 1;
6528 } else if (sh & 2) {
6529 /* doubleword */
6530 if (sh & 1) {
6531 /* store */
6532 tmp = load_reg(s, rd);
6533 gen_st32(tmp, addr, IS_USER(s));
6534 tcg_gen_addi_i32(addr, addr, 4);
6535 tmp = load_reg(s, rd + 1);
6536 gen_st32(tmp, addr, IS_USER(s));
6537 load = 0;
6538 } else {
6539 /* load */
6540 tmp = gen_ld32(addr, IS_USER(s));
6541 store_reg(s, rd, tmp);
6542 tcg_gen_addi_i32(addr, addr, 4);
6543 tmp = gen_ld32(addr, IS_USER(s));
6544 rd++;
6545 load = 1;
6546 }
6547 address_offset = -4;
6548 } else {
6549 /* store */
6550 tmp = load_reg(s, rd);
6551 gen_st16(tmp, addr, IS_USER(s));
6552 load = 0;
6553 }
6554 /* Perform base writeback before the loaded value to
6555 ensure correct behavior with overlapping index registers.
6556 ldrd with base writeback is is undefined if the
6557 destination and index registers overlap. */
6558 if (!(insn & (1 << 24))) {
6559 gen_add_datah_offset(s, insn, address_offset, addr);
6560 store_reg(s, rn, addr);
6561 } else if (insn & (1 << 21)) {
6562 if (address_offset)
6563 tcg_gen_addi_i32(addr, addr, address_offset);
6564 store_reg(s, rn, addr);
6565 } else {
6566 dead_tmp(addr);
6567 }
6568 if (load) {
6569 /* Complete the load. */
6570 store_reg(s, rd, tmp);
6571 }
6572 }
6573 break;
6574 case 0x4:
6575 case 0x5:
6576 goto do_ldst;
6577 case 0x6:
6578 case 0x7:
6579 if (insn & (1 << 4)) {
6580 ARCH(6);
6581 /* Armv6 Media instructions. */
6582 rm = insn & 0xf;
6583 rn = (insn >> 16) & 0xf;
6584 rd = (insn >> 12) & 0xf;
6585 rs = (insn >> 8) & 0xf;
6586 switch ((insn >> 23) & 3) {
6587 case 0: /* Parallel add/subtract. */
6588 op1 = (insn >> 20) & 7;
6589 tmp = load_reg(s, rn);
6590 tmp2 = load_reg(s, rm);
6591 sh = (insn >> 5) & 7;
6592 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6593 goto illegal_op;
6594 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6595 dead_tmp(tmp2);
6596 store_reg(s, rd, tmp);
6597 break;
6598 case 1:
6599 if ((insn & 0x00700020) == 0) {
6600 /* Halfword pack. */
6601 tmp = load_reg(s, rn);
6602 tmp2 = load_reg(s, rm);
6603 shift = (insn >> 7) & 0x1f;
6604 if (insn & (1 << 6)) {
6605 /* pkhtb */
6606 if (shift == 0)
6607 shift = 31;
6608 tcg_gen_sari_i32(tmp2, tmp2, shift);
6609 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6610 tcg_gen_ext16u_i32(tmp2, tmp2);
6611 } else {
6612 /* pkhbt */
6613 if (shift)
6614 tcg_gen_shli_i32(tmp2, tmp2, shift);
6615 tcg_gen_ext16u_i32(tmp, tmp);
6616 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6617 }
6618 tcg_gen_or_i32(tmp, tmp, tmp2);
6619 dead_tmp(tmp2);
6620 store_reg(s, rd, tmp);
6621 } else if ((insn & 0x00200020) == 0x00200000) {
6622 /* [us]sat */
6623 tmp = load_reg(s, rm);
6624 shift = (insn >> 7) & 0x1f;
6625 if (insn & (1 << 6)) {
6626 if (shift == 0)
6627 shift = 31;
6628 tcg_gen_sari_i32(tmp, tmp, shift);
6629 } else {
6630 tcg_gen_shli_i32(tmp, tmp, shift);
6631 }
6632 sh = (insn >> 16) & 0x1f;
6633 if (sh != 0) {
6634 if (insn & (1 << 22))
6635 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6636 else
6637 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6638 }
6639 store_reg(s, rd, tmp);
6640 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6641 /* [us]sat16 */
6642 tmp = load_reg(s, rm);
6643 sh = (insn >> 16) & 0x1f;
6644 if (sh != 0) {
6645 if (insn & (1 << 22))
6646 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6647 else
6648 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6649 }
6650 store_reg(s, rd, tmp);
6651 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6652 /* Select bytes. */
6653 tmp = load_reg(s, rn);
6654 tmp2 = load_reg(s, rm);
6655 tmp3 = new_tmp();
6656 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6657 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6658 dead_tmp(tmp3);
6659 dead_tmp(tmp2);
6660 store_reg(s, rd, tmp);
6661 } else if ((insn & 0x000003e0) == 0x00000060) {
6662 tmp = load_reg(s, rm);
6663 shift = (insn >> 10) & 3;
6664 /* ??? In many cases it's not neccessary to do a
6665 rotate, a shift is sufficient. */
6666 if (shift != 0)
6667 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6668 op1 = (insn >> 20) & 7;
6669 switch (op1) {
6670 case 0: gen_sxtb16(tmp); break;
6671 case 2: gen_sxtb(tmp); break;
6672 case 3: gen_sxth(tmp); break;
6673 case 4: gen_uxtb16(tmp); break;
6674 case 6: gen_uxtb(tmp); break;
6675 case 7: gen_uxth(tmp); break;
6676 default: goto illegal_op;
6677 }
6678 if (rn != 15) {
6679 tmp2 = load_reg(s, rn);
6680 if ((op1 & 3) == 0) {
6681 gen_add16(tmp, tmp2);
6682 } else {
6683 tcg_gen_add_i32(tmp, tmp, tmp2);
6684 dead_tmp(tmp2);
6685 }
6686 }
6687 store_reg(s, rd, tmp);
6688 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6689 /* rev */
6690 tmp = load_reg(s, rm);
6691 if (insn & (1 << 22)) {
6692 if (insn & (1 << 7)) {
6693 gen_revsh(tmp);
6694 } else {
6695 ARCH(6T2);
6696 gen_helper_rbit(tmp, tmp);
6697 }
6698 } else {
6699 if (insn & (1 << 7))
6700 gen_rev16(tmp);
6701 else
6702 tcg_gen_bswap32_i32(tmp, tmp);
6703 }
6704 store_reg(s, rd, tmp);
6705 } else {
6706 goto illegal_op;
6707 }
6708 break;
6709 case 2: /* Multiplies (Type 3). */
6710 tmp = load_reg(s, rm);
6711 tmp2 = load_reg(s, rs);
6712 if (insn & (1 << 20)) {
6713 /* Signed multiply most significant [accumulate]. */
6714 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6715 if (insn & (1 << 5))
6716 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6717 tcg_gen_shri_i64(tmp64, tmp64, 32);
6718 tmp = new_tmp();
6719 tcg_gen_trunc_i64_i32(tmp, tmp64);
6720 if (rd != 15) {
6721 tmp2 = load_reg(s, rd);
6722 if (insn & (1 << 6)) {
6723 tcg_gen_sub_i32(tmp, tmp, tmp2);
6724 } else {
6725 tcg_gen_add_i32(tmp, tmp, tmp2);
6726 }
6727 dead_tmp(tmp2);
6728 }
6729 store_reg(s, rn, tmp);
6730 } else {
6731 if (insn & (1 << 5))
6732 gen_swap_half(tmp2);
6733 gen_smul_dual(tmp, tmp2);
6734 /* This addition cannot overflow. */
6735 if (insn & (1 << 6)) {
6736 tcg_gen_sub_i32(tmp, tmp, tmp2);
6737 } else {
6738 tcg_gen_add_i32(tmp, tmp, tmp2);
6739 }
6740 dead_tmp(tmp2);
6741 if (insn & (1 << 22)) {
6742 /* smlald, smlsld */
6743 tmp64 = tcg_temp_new_i64();
6744 tcg_gen_ext_i32_i64(tmp64, tmp);
6745 dead_tmp(tmp);
6746 gen_addq(s, tmp64, rd, rn);
6747 gen_storeq_reg(s, rd, rn, tmp64);
6748 } else {
6749 /* smuad, smusd, smlad, smlsd */
6750 if (rd != 15)
6751 {
6752 tmp2 = load_reg(s, rd);
6753 gen_helper_add_setq(tmp, tmp, tmp2);
6754 dead_tmp(tmp2);
6755 }
6756 store_reg(s, rn, tmp);
6757 }
6758 }
6759 break;
6760 case 3:
6761 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6762 switch (op1) {
6763 case 0: /* Unsigned sum of absolute differences. */
6764 ARCH(6);
6765 tmp = load_reg(s, rm);
6766 tmp2 = load_reg(s, rs);
6767 gen_helper_usad8(tmp, tmp, tmp2);
6768 dead_tmp(tmp2);
6769 if (rd != 15) {
6770 tmp2 = load_reg(s, rd);
6771 tcg_gen_add_i32(tmp, tmp, tmp2);
6772 dead_tmp(tmp2);
6773 }
6774 store_reg(s, rn, tmp);
6775 break;
6776 case 0x20: case 0x24: case 0x28: case 0x2c:
6777 /* Bitfield insert/clear. */
6778 ARCH(6T2);
6779 shift = (insn >> 7) & 0x1f;
6780 i = (insn >> 16) & 0x1f;
6781 i = i + 1 - shift;
6782 if (rm == 15) {
6783 tmp = new_tmp();
6784 tcg_gen_movi_i32(tmp, 0);
6785 } else {
6786 tmp = load_reg(s, rm);
6787 }
6788 if (i != 32) {
6789 tmp2 = load_reg(s, rd);
6790 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6791 dead_tmp(tmp2);
6792 }
6793 store_reg(s, rd, tmp);
6794 break;
6795 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6796 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6797 ARCH(6T2);
6798 tmp = load_reg(s, rm);
6799 shift = (insn >> 7) & 0x1f;
6800 i = ((insn >> 16) & 0x1f) + 1;
6801 if (shift + i > 32)
6802 goto illegal_op;
6803 if (i < 32) {
6804 if (op1 & 0x20) {
6805 gen_ubfx(tmp, shift, (1u << i) - 1);
6806 } else {
6807 gen_sbfx(tmp, shift, i);
6808 }
6809 }
6810 store_reg(s, rd, tmp);
6811 break;
6812 default:
6813 goto illegal_op;
6814 }
6815 break;
6816 }
6817 break;
6818 }
6819 do_ldst:
6820 /* Check for undefined extension instructions
6821 * per the ARM Bible IE:
6822 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6823 */
6824 sh = (0xf << 20) | (0xf << 4);
6825 if (op1 == 0x7 && ((insn & sh) == sh))
6826 {
6827 goto illegal_op;
6828 }
6829 /* load/store byte/word */
6830 rn = (insn >> 16) & 0xf;
6831 rd = (insn >> 12) & 0xf;
6832 tmp2 = load_reg(s, rn);
6833 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6834 if (insn & (1 << 24))
6835 gen_add_data_offset(s, insn, tmp2);
6836 if (insn & (1 << 20)) {
6837 /* load */
6838 if (insn & (1 << 22)) {
6839 tmp = gen_ld8u(tmp2, i);
6840 } else {
6841 tmp = gen_ld32(tmp2, i);
6842 }
6843 } else {
6844 /* store */
6845 tmp = load_reg(s, rd);
6846 if (insn & (1 << 22))
6847 gen_st8(tmp, tmp2, i);
6848 else
6849 gen_st32(tmp, tmp2, i);
6850 }
6851 if (!(insn & (1 << 24))) {
6852 gen_add_data_offset(s, insn, tmp2);
6853 store_reg(s, rn, tmp2);
6854 } else if (insn & (1 << 21)) {
6855 store_reg(s, rn, tmp2);
6856 } else {
6857 dead_tmp(tmp2);
6858 }
6859 if (insn & (1 << 20)) {
6860 /* Complete the load. */
6861 if (rd == 15)
6862 gen_bx(s, tmp);
6863 else
6864 store_reg(s, rd, tmp);
6865 }
6866 break;
6867 case 0x08:
6868 case 0x09:
6869 {
6870 int j, n, user, loaded_base;
6871 TCGv loaded_var;
6872 /* load/store multiple words */
6873 /* XXX: store correct base if write back */
6874 user = 0;
6875 if (insn & (1 << 22)) {
6876 if (IS_USER(s))
6877 goto illegal_op; /* only usable in supervisor mode */
6878
6879 if ((insn & (1 << 15)) == 0)
6880 user = 1;
6881 }
6882 rn = (insn >> 16) & 0xf;
6883 addr = load_reg(s, rn);
6884
6885 /* compute total size */
6886 loaded_base = 0;
6887 TCGV_UNUSED(loaded_var);
6888 n = 0;
6889 for(i=0;i<16;i++) {
6890 if (insn & (1 << i))
6891 n++;
6892 }
6893 /* XXX: test invalid n == 0 case ? */
6894 if (insn & (1 << 23)) {
6895 if (insn & (1 << 24)) {
6896 /* pre increment */
6897 tcg_gen_addi_i32(addr, addr, 4);
6898 } else {
6899 /* post increment */
6900 }
6901 } else {
6902 if (insn & (1 << 24)) {
6903 /* pre decrement */
6904 tcg_gen_addi_i32(addr, addr, -(n * 4));
6905 } else {
6906 /* post decrement */
6907 if (n != 1)
6908 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6909 }
6910 }
6911 j = 0;
6912 for(i=0;i<16;i++) {
6913 if (insn & (1 << i)) {
6914 if (insn & (1 << 20)) {
6915 /* load */
6916 tmp = gen_ld32(addr, IS_USER(s));
6917 if (i == 15) {
6918 gen_bx(s, tmp);
6919 } else if (user) {
6920 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6921 dead_tmp(tmp);
6922 } else if (i == rn) {
6923 loaded_var = tmp;
6924 loaded_base = 1;
6925 } else {
6926 store_reg(s, i, tmp);
6927 }
6928 } else {
6929 /* store */
6930 if (i == 15) {
6931 /* special case: r15 = PC + 8 */
6932 val = (long)s->pc + 4;
6933 tmp = new_tmp();
6934 tcg_gen_movi_i32(tmp, val);
6935 } else if (user) {
6936 tmp = new_tmp();
6937 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6938 } else {
6939 tmp = load_reg(s, i);
6940 }
6941 gen_st32(tmp, addr, IS_USER(s));
6942 }
6943 j++;
6944 /* no need to add after the last transfer */
6945 if (j != n)
6946 tcg_gen_addi_i32(addr, addr, 4);
6947 }
6948 }
6949 if (insn & (1 << 21)) {
6950 /* write back */
6951 if (insn & (1 << 23)) {
6952 if (insn & (1 << 24)) {
6953 /* pre increment */
6954 } else {
6955 /* post increment */
6956 tcg_gen_addi_i32(addr, addr, 4);
6957 }
6958 } else {
6959 if (insn & (1 << 24)) {
6960 /* pre decrement */
6961 if (n != 1)
6962 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6963 } else {
6964 /* post decrement */
6965 tcg_gen_addi_i32(addr, addr, -(n * 4));
6966 }
6967 }
6968 store_reg(s, rn, addr);
6969 } else {
6970 dead_tmp(addr);
6971 }
6972 if (loaded_base) {
6973 store_reg(s, rn, loaded_var);
6974 }
6975 if ((insn & (1 << 22)) && !user) {
6976 /* Restore CPSR from SPSR. */
6977 tmp = load_cpu_field(spsr);
6978 gen_set_cpsr(tmp, 0xffffffff);
6979 dead_tmp(tmp);
6980 s->is_jmp = DISAS_UPDATE;
6981 }
6982 }
6983 break;
6984 case 0xa:
6985 case 0xb:
6986 {
6987 int32_t offset;
6988
6989 /* branch (and link) */
6990 val = (int32_t)s->pc;
6991 if (insn & (1 << 24)) {
6992 tmp = new_tmp();
6993 tcg_gen_movi_i32(tmp, val);
6994 store_reg(s, 14, tmp);
6995 }
6996 offset = (((int32_t)insn << 8) >> 8);
6997 val += (offset << 2) + 4;
6998 gen_jmp(s, val);
6999 }
7000 break;
7001 case 0xc:
7002 case 0xd:
7003 case 0xe:
7004 /* Coprocessor. */
7005 if (disas_coproc_insn(env, s, insn))
7006 goto illegal_op;
7007 break;
7008 case 0xf:
7009 /* swi */
7010 gen_set_pc_im(s->pc);
7011 s->is_jmp = DISAS_SWI;
7012 break;
7013 default:
7014 illegal_op:
7015 gen_set_condexec(s);
7016 gen_set_pc_im(s->pc - 4);
7017 gen_exception(EXCP_UDEF);
7018 s->is_jmp = DISAS_JUMP;
7019 break;
7020 }
7021 }
7022 }
7023
7024 /* Return true if this is a Thumb-2 logical op. */
7025 static int
thumb2_logic_op(int op)7026 thumb2_logic_op(int op)
7027 {
7028 return (op < 8);
7029 }
7030
7031 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7032 then set condition code flags based on the result of the operation.
7033 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7034 to the high bit of T1.
7035 Returns zero if the opcode is valid. */
7036
7037 static int
gen_thumb2_data_op(DisasContext * s,int op,int conds,uint32_t shifter_out)7038 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
7039 {
7040 int logic_cc;
7041
7042 logic_cc = 0;
7043 switch (op) {
7044 case 0: /* and */
7045 gen_op_andl_T0_T1();
7046 logic_cc = conds;
7047 break;
7048 case 1: /* bic */
7049 gen_op_bicl_T0_T1();
7050 logic_cc = conds;
7051 break;
7052 case 2: /* orr */
7053 gen_op_orl_T0_T1();
7054 logic_cc = conds;
7055 break;
7056 case 3: /* orn */
7057 gen_op_notl_T1();
7058 gen_op_orl_T0_T1();
7059 logic_cc = conds;
7060 break;
7061 case 4: /* eor */
7062 gen_op_xorl_T0_T1();
7063 logic_cc = conds;
7064 break;
7065 case 8: /* add */
7066 if (conds)
7067 gen_op_addl_T0_T1_cc();
7068 else
7069 gen_op_addl_T0_T1();
7070 break;
7071 case 10: /* adc */
7072 if (conds)
7073 gen_op_adcl_T0_T1_cc();
7074 else
7075 gen_adc_T0_T1();
7076 break;
7077 case 11: /* sbc */
7078 if (conds)
7079 gen_op_sbcl_T0_T1_cc();
7080 else
7081 gen_sbc_T0_T1();
7082 break;
7083 case 13: /* sub */
7084 if (conds)
7085 gen_op_subl_T0_T1_cc();
7086 else
7087 gen_op_subl_T0_T1();
7088 break;
7089 case 14: /* rsb */
7090 if (conds)
7091 gen_op_rsbl_T0_T1_cc();
7092 else
7093 gen_op_rsbl_T0_T1();
7094 break;
7095 default: /* 5, 6, 7, 9, 12, 15. */
7096 return 1;
7097 }
7098 if (logic_cc) {
7099 gen_op_logic_T0_cc();
7100 if (shifter_out)
7101 gen_set_CF_bit31(cpu_T[1]);
7102 }
7103 return 0;
7104 }
7105
7106 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7107 is not legal. */
disas_thumb2_insn(CPUState * env,DisasContext * s,uint16_t insn_hw1)7108 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7109 {
7110 uint32_t insn, imm, shift, offset;
7111 uint32_t rd, rn, rm, rs;
7112 TCGv tmp;
7113 TCGv tmp2;
7114 TCGv tmp3;
7115 TCGv addr;
7116 TCGv_i64 tmp64;
7117 int op;
7118 int shiftop;
7119 int conds;
7120 int logic_cc;
7121
7122 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7123 || arm_feature (env, ARM_FEATURE_M))) {
7124 /* Thumb-1 cores may need to treat bl and blx as a pair of
7125 16-bit instructions to get correct prefetch abort behavior. */
7126 insn = insn_hw1;
7127 if ((insn & (1 << 12)) == 0) {
7128 /* Second half of blx. */
7129 offset = ((insn & 0x7ff) << 1);
7130 tmp = load_reg(s, 14);
7131 tcg_gen_addi_i32(tmp, tmp, offset);
7132 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7133
7134 tmp2 = new_tmp();
7135 tcg_gen_movi_i32(tmp2, s->pc | 1);
7136 store_reg(s, 14, tmp2);
7137 gen_bx(s, tmp);
7138 return 0;
7139 }
7140 if (insn & (1 << 11)) {
7141 /* Second half of bl. */
7142 offset = ((insn & 0x7ff) << 1) | 1;
7143 tmp = load_reg(s, 14);
7144 tcg_gen_addi_i32(tmp, tmp, offset);
7145
7146 tmp2 = new_tmp();
7147 tcg_gen_movi_i32(tmp2, s->pc | 1);
7148 store_reg(s, 14, tmp2);
7149 gen_bx(s, tmp);
7150 return 0;
7151 }
7152 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7153 /* Instruction spans a page boundary. Implement it as two
7154 16-bit instructions in case the second half causes an
7155 prefetch abort. */
7156 offset = ((int32_t)insn << 21) >> 9;
7157 gen_op_movl_T0_im(s->pc + 2 + offset);
7158 gen_movl_reg_T0(s, 14);
7159 return 0;
7160 }
7161 /* Fall through to 32-bit decode. */
7162 }
7163
7164 insn = lduw_code(s->pc);
7165 #ifdef CONFIG_TRACE
7166 if (tracing) {
7167 int ticks = get_insn_ticks_thumb(insn);
7168 trace_add_insn( insn_wrap_thumb(insn), 1 );
7169 gen_traceInsn();
7170 gen_traceTicks(ticks);
7171 }
7172 #endif
7173 s->pc += 2;
7174 insn |= (uint32_t)insn_hw1 << 16;
7175
7176 if ((insn & 0xf800e800) != 0xf000e800) {
7177 ARCH(6T2);
7178 }
7179
7180 rn = (insn >> 16) & 0xf;
7181 rs = (insn >> 12) & 0xf;
7182 rd = (insn >> 8) & 0xf;
7183 rm = insn & 0xf;
7184 switch ((insn >> 25) & 0xf) {
7185 case 0: case 1: case 2: case 3:
7186 /* 16-bit instructions. Should never happen. */
7187 abort();
7188 case 4:
7189 if (insn & (1 << 22)) {
7190 /* Other load/store, table branch. */
7191 if (insn & 0x01200000) {
7192 /* Load/store doubleword. */
7193 if (rn == 15) {
7194 addr = new_tmp();
7195 tcg_gen_movi_i32(addr, s->pc & ~3);
7196 } else {
7197 addr = load_reg(s, rn);
7198 }
7199 offset = (insn & 0xff) * 4;
7200 if ((insn & (1 << 23)) == 0)
7201 offset = -offset;
7202 if (insn & (1 << 24)) {
7203 tcg_gen_addi_i32(addr, addr, offset);
7204 offset = 0;
7205 }
7206 if (insn & (1 << 20)) {
7207 /* ldrd */
7208 tmp = gen_ld32(addr, IS_USER(s));
7209 store_reg(s, rs, tmp);
7210 tcg_gen_addi_i32(addr, addr, 4);
7211 tmp = gen_ld32(addr, IS_USER(s));
7212 store_reg(s, rd, tmp);
7213 } else {
7214 /* strd */
7215 tmp = load_reg(s, rs);
7216 gen_st32(tmp, addr, IS_USER(s));
7217 tcg_gen_addi_i32(addr, addr, 4);
7218 tmp = load_reg(s, rd);
7219 gen_st32(tmp, addr, IS_USER(s));
7220 }
7221 if (insn & (1 << 21)) {
7222 /* Base writeback. */
7223 if (rn == 15)
7224 goto illegal_op;
7225 tcg_gen_addi_i32(addr, addr, offset - 4);
7226 store_reg(s, rn, addr);
7227 } else {
7228 dead_tmp(addr);
7229 }
7230 } else if ((insn & (1 << 23)) == 0) {
7231 /* Load/store exclusive word. */
7232 gen_movl_T1_reg(s, rn);
7233 addr = cpu_T[1];
7234 if (insn & (1 << 20)) {
7235 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
7236 tmp = gen_ld32(addr, IS_USER(s));
7237 store_reg(s, rd, tmp);
7238 } else {
7239 int label = gen_new_label();
7240 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7241 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7242 0, label);
7243 tmp = load_reg(s, rs);
7244 gen_st32(tmp, cpu_T[1], IS_USER(s));
7245 gen_set_label(label);
7246 gen_movl_reg_T0(s, rd);
7247 }
7248 } else if ((insn & (1 << 6)) == 0) {
7249 /* Table Branch. */
7250 if (rn == 15) {
7251 addr = new_tmp();
7252 tcg_gen_movi_i32(addr, s->pc);
7253 } else {
7254 addr = load_reg(s, rn);
7255 }
7256 tmp = load_reg(s, rm);
7257 tcg_gen_add_i32(addr, addr, tmp);
7258 if (insn & (1 << 4)) {
7259 /* tbh */
7260 tcg_gen_add_i32(addr, addr, tmp);
7261 dead_tmp(tmp);
7262 tmp = gen_ld16u(addr, IS_USER(s));
7263 } else { /* tbb */
7264 dead_tmp(tmp);
7265 tmp = gen_ld8u(addr, IS_USER(s));
7266 }
7267 dead_tmp(addr);
7268 tcg_gen_shli_i32(tmp, tmp, 1);
7269 tcg_gen_addi_i32(tmp, tmp, s->pc);
7270 store_reg(s, 15, tmp);
7271 } else {
7272 /* Load/store exclusive byte/halfword/doubleword. */
7273 /* ??? These are not really atomic. However we know
7274 we never have multiple CPUs running in parallel,
7275 so it is good enough. */
7276 op = (insn >> 4) & 0x3;
7277 /* Must use a global reg for the address because we have
7278 a conditional branch in the store instruction. */
7279 gen_movl_T1_reg(s, rn);
7280 addr = cpu_T[1];
7281 if (insn & (1 << 20)) {
7282 gen_helper_mark_exclusive(cpu_env, addr);
7283 switch (op) {
7284 case 0:
7285 tmp = gen_ld8u(addr, IS_USER(s));
7286 break;
7287 case 1:
7288 tmp = gen_ld16u(addr, IS_USER(s));
7289 break;
7290 case 3:
7291 tmp = gen_ld32(addr, IS_USER(s));
7292 tcg_gen_addi_i32(addr, addr, 4);
7293 tmp2 = gen_ld32(addr, IS_USER(s));
7294 store_reg(s, rd, tmp2);
7295 break;
7296 default:
7297 goto illegal_op;
7298 }
7299 store_reg(s, rs, tmp);
7300 } else {
7301 int label = gen_new_label();
7302 /* Must use a global that is not killed by the branch. */
7303 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7304 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
7305 tmp = load_reg(s, rs);
7306 switch (op) {
7307 case 0:
7308 gen_st8(tmp, addr, IS_USER(s));
7309 break;
7310 case 1:
7311 gen_st16(tmp, addr, IS_USER(s));
7312 break;
7313 case 3:
7314 gen_st32(tmp, addr, IS_USER(s));
7315 tcg_gen_addi_i32(addr, addr, 4);
7316 tmp = load_reg(s, rd);
7317 gen_st32(tmp, addr, IS_USER(s));
7318 break;
7319 default:
7320 goto illegal_op;
7321 }
7322 gen_set_label(label);
7323 gen_movl_reg_T0(s, rm);
7324 }
7325 }
7326 } else {
7327 /* Load/store multiple, RFE, SRS. */
7328 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7329 /* Not available in user mode. */
7330 if (IS_USER(s))
7331 goto illegal_op;
7332 if (insn & (1 << 20)) {
7333 /* rfe */
7334 addr = load_reg(s, rn);
7335 if ((insn & (1 << 24)) == 0)
7336 tcg_gen_addi_i32(addr, addr, -8);
7337 /* Load PC into tmp and CPSR into tmp2. */
7338 tmp = gen_ld32(addr, 0);
7339 tcg_gen_addi_i32(addr, addr, 4);
7340 tmp2 = gen_ld32(addr, 0);
7341 if (insn & (1 << 21)) {
7342 /* Base writeback. */
7343 if (insn & (1 << 24)) {
7344 tcg_gen_addi_i32(addr, addr, 4);
7345 } else {
7346 tcg_gen_addi_i32(addr, addr, -4);
7347 }
7348 store_reg(s, rn, addr);
7349 } else {
7350 dead_tmp(addr);
7351 }
7352 gen_rfe(s, tmp, tmp2);
7353 } else {
7354 /* srs */
7355 op = (insn & 0x1f);
7356 if (op == (env->uncached_cpsr & CPSR_M)) {
7357 addr = load_reg(s, 13);
7358 } else {
7359 addr = new_tmp();
7360 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7361 }
7362 if ((insn & (1 << 24)) == 0) {
7363 tcg_gen_addi_i32(addr, addr, -8);
7364 }
7365 tmp = load_reg(s, 14);
7366 gen_st32(tmp, addr, 0);
7367 tcg_gen_addi_i32(addr, addr, 4);
7368 tmp = new_tmp();
7369 gen_helper_cpsr_read(tmp);
7370 gen_st32(tmp, addr, 0);
7371 if (insn & (1 << 21)) {
7372 if ((insn & (1 << 24)) == 0) {
7373 tcg_gen_addi_i32(addr, addr, -4);
7374 } else {
7375 tcg_gen_addi_i32(addr, addr, 4);
7376 }
7377 if (op == (env->uncached_cpsr & CPSR_M)) {
7378 store_reg(s, 13, addr);
7379 } else {
7380 gen_helper_set_r13_banked(cpu_env,
7381 tcg_const_i32(op), addr);
7382 }
7383 } else {
7384 dead_tmp(addr);
7385 }
7386 }
7387 } else {
7388 int i;
7389 /* Load/store multiple. */
7390 addr = load_reg(s, rn);
7391 offset = 0;
7392 for (i = 0; i < 16; i++) {
7393 if (insn & (1 << i))
7394 offset += 4;
7395 }
7396 if (insn & (1 << 24)) {
7397 tcg_gen_addi_i32(addr, addr, -offset);
7398 }
7399
7400 for (i = 0; i < 16; i++) {
7401 if ((insn & (1 << i)) == 0)
7402 continue;
7403 if (insn & (1 << 20)) {
7404 /* Load. */
7405 tmp = gen_ld32(addr, IS_USER(s));
7406 if (i == 15) {
7407 gen_bx(s, tmp);
7408 } else {
7409 store_reg(s, i, tmp);
7410 }
7411 } else {
7412 /* Store. */
7413 tmp = load_reg(s, i);
7414 gen_st32(tmp, addr, IS_USER(s));
7415 }
7416 tcg_gen_addi_i32(addr, addr, 4);
7417 }
7418 if (insn & (1 << 21)) {
7419 /* Base register writeback. */
7420 if (insn & (1 << 24)) {
7421 tcg_gen_addi_i32(addr, addr, -offset);
7422 }
7423 /* Fault if writeback register is in register list. */
7424 if (insn & (1 << rn))
7425 goto illegal_op;
7426 store_reg(s, rn, addr);
7427 } else {
7428 dead_tmp(addr);
7429 }
7430 }
7431 }
7432 break;
7433 case 5: /* Data processing register constant shift. */
7434 if (rn == 15)
7435 gen_op_movl_T0_im(0);
7436 else
7437 gen_movl_T0_reg(s, rn);
7438 gen_movl_T1_reg(s, rm);
7439 op = (insn >> 21) & 0xf;
7440 shiftop = (insn >> 4) & 3;
7441 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7442 conds = (insn & (1 << 20)) != 0;
7443 logic_cc = (conds && thumb2_logic_op(op));
7444 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7445 if (gen_thumb2_data_op(s, op, conds, 0))
7446 goto illegal_op;
7447 if (rd != 15)
7448 gen_movl_reg_T0(s, rd);
7449 break;
7450 case 13: /* Misc data processing. */
7451 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7452 if (op < 4 && (insn & 0xf000) != 0xf000)
7453 goto illegal_op;
7454 switch (op) {
7455 case 0: /* Register controlled shift. */
7456 tmp = load_reg(s, rn);
7457 tmp2 = load_reg(s, rm);
7458 if ((insn & 0x70) != 0)
7459 goto illegal_op;
7460 op = (insn >> 21) & 3;
7461 logic_cc = (insn & (1 << 20)) != 0;
7462 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7463 if (logic_cc)
7464 gen_logic_CC(tmp);
7465 store_reg_bx(env, s, rd, tmp);
7466 break;
7467 case 1: /* Sign/zero extend. */
7468 tmp = load_reg(s, rm);
7469 shift = (insn >> 4) & 3;
7470 /* ??? In many cases it's not neccessary to do a
7471 rotate, a shift is sufficient. */
7472 if (shift != 0)
7473 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7474 op = (insn >> 20) & 7;
7475 switch (op) {
7476 case 0: gen_sxth(tmp); break;
7477 case 1: gen_uxth(tmp); break;
7478 case 2: gen_sxtb16(tmp); break;
7479 case 3: gen_uxtb16(tmp); break;
7480 case 4: gen_sxtb(tmp); break;
7481 case 5: gen_uxtb(tmp); break;
7482 default: goto illegal_op;
7483 }
7484 if (rn != 15) {
7485 tmp2 = load_reg(s, rn);
7486 if ((op >> 1) == 1) {
7487 gen_add16(tmp, tmp2);
7488 } else {
7489 tcg_gen_add_i32(tmp, tmp, tmp2);
7490 dead_tmp(tmp2);
7491 }
7492 }
7493 store_reg(s, rd, tmp);
7494 break;
7495 case 2: /* SIMD add/subtract. */
7496 op = (insn >> 20) & 7;
7497 shift = (insn >> 4) & 7;
7498 if ((op & 3) == 3 || (shift & 3) == 3)
7499 goto illegal_op;
7500 tmp = load_reg(s, rn);
7501 tmp2 = load_reg(s, rm);
7502 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7503 dead_tmp(tmp2);
7504 store_reg(s, rd, tmp);
7505 break;
7506 case 3: /* Other data processing. */
7507 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7508 if (op < 4) {
7509 /* Saturating add/subtract. */
7510 tmp = load_reg(s, rn);
7511 tmp2 = load_reg(s, rm);
7512 if (op & 2)
7513 gen_helper_double_saturate(tmp, tmp);
7514 if (op & 1)
7515 gen_helper_sub_saturate(tmp, tmp2, tmp);
7516 else
7517 gen_helper_add_saturate(tmp, tmp, tmp2);
7518 dead_tmp(tmp2);
7519 } else {
7520 tmp = load_reg(s, rn);
7521 switch (op) {
7522 case 0x0a: /* rbit */
7523 gen_helper_rbit(tmp, tmp);
7524 break;
7525 case 0x08: /* rev */
7526 tcg_gen_bswap32_i32(tmp, tmp);
7527 break;
7528 case 0x09: /* rev16 */
7529 gen_rev16(tmp);
7530 break;
7531 case 0x0b: /* revsh */
7532 gen_revsh(tmp);
7533 break;
7534 case 0x10: /* sel */
7535 tmp2 = load_reg(s, rm);
7536 tmp3 = new_tmp();
7537 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7538 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7539 dead_tmp(tmp3);
7540 dead_tmp(tmp2);
7541 break;
7542 case 0x18: /* clz */
7543 gen_helper_clz(tmp, tmp);
7544 break;
7545 default:
7546 goto illegal_op;
7547 }
7548 }
7549 store_reg(s, rd, tmp);
7550 break;
7551 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7552 op = (insn >> 4) & 0xf;
7553 tmp = load_reg(s, rn);
7554 tmp2 = load_reg(s, rm);
7555 switch ((insn >> 20) & 7) {
7556 case 0: /* 32 x 32 -> 32 */
7557 tcg_gen_mul_i32(tmp, tmp, tmp2);
7558 dead_tmp(tmp2);
7559 if (rs != 15) {
7560 tmp2 = load_reg(s, rs);
7561 if (op)
7562 tcg_gen_sub_i32(tmp, tmp2, tmp);
7563 else
7564 tcg_gen_add_i32(tmp, tmp, tmp2);
7565 dead_tmp(tmp2);
7566 }
7567 break;
7568 case 1: /* 16 x 16 -> 32 */
7569 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7570 dead_tmp(tmp2);
7571 if (rs != 15) {
7572 tmp2 = load_reg(s, rs);
7573 gen_helper_add_setq(tmp, tmp, tmp2);
7574 dead_tmp(tmp2);
7575 }
7576 break;
7577 case 2: /* Dual multiply add. */
7578 case 4: /* Dual multiply subtract. */
7579 if (op)
7580 gen_swap_half(tmp2);
7581 gen_smul_dual(tmp, tmp2);
7582 /* This addition cannot overflow. */
7583 if (insn & (1 << 22)) {
7584 tcg_gen_sub_i32(tmp, tmp, tmp2);
7585 } else {
7586 tcg_gen_add_i32(tmp, tmp, tmp2);
7587 }
7588 dead_tmp(tmp2);
7589 if (rs != 15)
7590 {
7591 tmp2 = load_reg(s, rs);
7592 gen_helper_add_setq(tmp, tmp, tmp2);
7593 dead_tmp(tmp2);
7594 }
7595 break;
7596 case 3: /* 32 * 16 -> 32msb */
7597 if (op)
7598 tcg_gen_sari_i32(tmp2, tmp2, 16);
7599 else
7600 gen_sxth(tmp2);
7601 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7602 tcg_gen_shri_i64(tmp64, tmp64, 16);
7603 tmp = new_tmp();
7604 tcg_gen_trunc_i64_i32(tmp, tmp64);
7605 if (rs != 15)
7606 {
7607 tmp2 = load_reg(s, rs);
7608 gen_helper_add_setq(tmp, tmp, tmp2);
7609 dead_tmp(tmp2);
7610 }
7611 break;
7612 case 5: case 6: /* 32 * 32 -> 32msb */
7613 gen_imull(tmp, tmp2);
7614 if (insn & (1 << 5)) {
7615 gen_roundqd(tmp, tmp2);
7616 dead_tmp(tmp2);
7617 } else {
7618 dead_tmp(tmp);
7619 tmp = tmp2;
7620 }
7621 if (rs != 15) {
7622 tmp2 = load_reg(s, rs);
7623 if (insn & (1 << 21)) {
7624 tcg_gen_add_i32(tmp, tmp, tmp2);
7625 } else {
7626 tcg_gen_sub_i32(tmp, tmp2, tmp);
7627 }
7628 dead_tmp(tmp2);
7629 }
7630 break;
7631 case 7: /* Unsigned sum of absolute differences. */
7632 gen_helper_usad8(tmp, tmp, tmp2);
7633 dead_tmp(tmp2);
7634 if (rs != 15) {
7635 tmp2 = load_reg(s, rs);
7636 tcg_gen_add_i32(tmp, tmp, tmp2);
7637 dead_tmp(tmp2);
7638 }
7639 break;
7640 }
7641 store_reg(s, rd, tmp);
7642 break;
7643 case 6: case 7: /* 64-bit multiply, Divide. */
7644 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7645 tmp = load_reg(s, rn);
7646 tmp2 = load_reg(s, rm);
7647 if ((op & 0x50) == 0x10) {
7648 /* sdiv, udiv */
7649 if (!arm_feature(env, ARM_FEATURE_DIV))
7650 goto illegal_op;
7651 if (op & 0x20)
7652 gen_helper_udiv(tmp, tmp, tmp2);
7653 else
7654 gen_helper_sdiv(tmp, tmp, tmp2);
7655 dead_tmp(tmp2);
7656 store_reg(s, rd, tmp);
7657 } else if ((op & 0xe) == 0xc) {
7658 /* Dual multiply accumulate long. */
7659 if (op & 1)
7660 gen_swap_half(tmp2);
7661 gen_smul_dual(tmp, tmp2);
7662 if (op & 0x10) {
7663 tcg_gen_sub_i32(tmp, tmp, tmp2);
7664 } else {
7665 tcg_gen_add_i32(tmp, tmp, tmp2);
7666 }
7667 dead_tmp(tmp2);
7668 /* BUGFIX */
7669 tmp64 = tcg_temp_new_i64();
7670 tcg_gen_ext_i32_i64(tmp64, tmp);
7671 dead_tmp(tmp);
7672 gen_addq(s, tmp64, rs, rd);
7673 gen_storeq_reg(s, rs, rd, tmp64);
7674 } else {
7675 if (op & 0x20) {
7676 /* Unsigned 64-bit multiply */
7677 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7678 } else {
7679 if (op & 8) {
7680 /* smlalxy */
7681 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7682 dead_tmp(tmp2);
7683 tmp64 = tcg_temp_new_i64();
7684 tcg_gen_ext_i32_i64(tmp64, tmp);
7685 dead_tmp(tmp);
7686 } else {
7687 /* Signed 64-bit multiply */
7688 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7689 }
7690 }
7691 if (op & 4) {
7692 /* umaal */
7693 gen_addq_lo(s, tmp64, rs);
7694 gen_addq_lo(s, tmp64, rd);
7695 } else if (op & 0x40) {
7696 /* 64-bit accumulate. */
7697 gen_addq(s, tmp64, rs, rd);
7698 }
7699 gen_storeq_reg(s, rs, rd, tmp64);
7700 }
7701 break;
7702 }
7703 break;
7704 case 6: case 7: case 14: case 15:
7705 /* Coprocessor. */
7706 if (((insn >> 24) & 3) == 3) {
7707 /* Translate into the equivalent ARM encoding. */
7708 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7709 if (disas_neon_data_insn(env, s, insn))
7710 goto illegal_op;
7711 } else {
7712 if (insn & (1 << 28))
7713 goto illegal_op;
7714 if (disas_coproc_insn (env, s, insn))
7715 goto illegal_op;
7716 }
7717 break;
7718 case 8: case 9: case 10: case 11:
7719 if (insn & (1 << 15)) {
7720 /* Branches, misc control. */
7721 if (insn & 0x5000) {
7722 /* Unconditional branch. */
7723 /* signextend(hw1[10:0]) -> offset[:12]. */
7724 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7725 /* hw1[10:0] -> offset[11:1]. */
7726 offset |= (insn & 0x7ff) << 1;
7727 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7728 offset[24:22] already have the same value because of the
7729 sign extension above. */
7730 offset ^= ((~insn) & (1 << 13)) << 10;
7731 offset ^= ((~insn) & (1 << 11)) << 11;
7732
7733 if (insn & (1 << 14)) {
7734 /* Branch and link. */
7735 gen_op_movl_T1_im(s->pc | 1);
7736 gen_movl_reg_T1(s, 14);
7737 }
7738
7739 offset += s->pc;
7740 if (insn & (1 << 12)) {
7741 /* b/bl */
7742 gen_jmp(s, offset);
7743 } else {
7744 /* blx */
7745 offset &= ~(uint32_t)2;
7746 gen_bx_im(s, offset);
7747 }
7748 } else if (((insn >> 23) & 7) == 7) {
7749 /* Misc control */
7750 if (insn & (1 << 13))
7751 goto illegal_op;
7752
7753 if (insn & (1 << 26)) {
7754 /* Secure monitor call (v6Z) */
7755 goto illegal_op; /* not implemented. */
7756 } else {
7757 op = (insn >> 20) & 7;
7758 switch (op) {
7759 case 0: /* msr cpsr. */
7760 if (IS_M(env)) {
7761 tmp = load_reg(s, rn);
7762 addr = tcg_const_i32(insn & 0xff);
7763 gen_helper_v7m_msr(cpu_env, addr, tmp);
7764 gen_lookup_tb(s);
7765 break;
7766 }
7767 /* fall through */
7768 case 1: /* msr spsr. */
7769 if (IS_M(env))
7770 goto illegal_op;
7771 gen_movl_T0_reg(s, rn);
7772 if (gen_set_psr_T0(s,
7773 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7774 op == 1))
7775 goto illegal_op;
7776 break;
7777 case 2: /* cps, nop-hint. */
7778 if (((insn >> 8) & 7) == 0) {
7779 gen_nop_hint(s, insn & 0xff);
7780 }
7781 /* Implemented as NOP in user mode. */
7782 if (IS_USER(s))
7783 break;
7784 offset = 0;
7785 imm = 0;
7786 if (insn & (1 << 10)) {
7787 if (insn & (1 << 7))
7788 offset |= CPSR_A;
7789 if (insn & (1 << 6))
7790 offset |= CPSR_I;
7791 if (insn & (1 << 5))
7792 offset |= CPSR_F;
7793 if (insn & (1 << 9))
7794 imm = CPSR_A | CPSR_I | CPSR_F;
7795 }
7796 if (insn & (1 << 8)) {
7797 offset |= 0x1f;
7798 imm |= (insn & 0x1f);
7799 }
7800 if (offset) {
7801 gen_op_movl_T0_im(imm);
7802 gen_set_psr_T0(s, offset, 0);
7803 }
7804 break;
7805 case 3: /* Special control operations. */
7806 op = (insn >> 4) & 0xf;
7807 switch (op) {
7808 case 2: /* clrex */
7809 gen_helper_clrex(cpu_env);
7810 break;
7811 case 4: /* dsb */
7812 case 5: /* dmb */
7813 case 6: /* isb */
7814 /* These execute as NOPs. */
7815 ARCH(7);
7816 break;
7817 default:
7818 goto illegal_op;
7819 }
7820 break;
7821 case 4: /* bxj */
7822 /* Trivial implementation equivalent to bx. */
7823 tmp = load_reg(s, rn);
7824 gen_bx(s, tmp);
7825 break;
7826 case 5: /* Exception return. */
7827 /* Unpredictable in user mode. */
7828 goto illegal_op;
7829 case 6: /* mrs cpsr. */
7830 tmp = new_tmp();
7831 if (IS_M(env)) {
7832 addr = tcg_const_i32(insn & 0xff);
7833 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7834 } else {
7835 gen_helper_cpsr_read(tmp);
7836 }
7837 store_reg(s, rd, tmp);
7838 break;
7839 case 7: /* mrs spsr. */
7840 /* Not accessible in user mode. */
7841 if (IS_USER(s) || IS_M(env))
7842 goto illegal_op;
7843 tmp = load_cpu_field(spsr);
7844 store_reg(s, rd, tmp);
7845 break;
7846 }
7847 }
7848 } else {
7849 /* Conditional branch. */
7850 op = (insn >> 22) & 0xf;
7851 /* Generate a conditional jump to next instruction. */
7852 s->condlabel = gen_new_label();
7853 gen_test_cc(op ^ 1, s->condlabel);
7854 s->condjmp = 1;
7855
7856 /* offset[11:1] = insn[10:0] */
7857 offset = (insn & 0x7ff) << 1;
7858 /* offset[17:12] = insn[21:16]. */
7859 offset |= (insn & 0x003f0000) >> 4;
7860 /* offset[31:20] = insn[26]. */
7861 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7862 /* offset[18] = insn[13]. */
7863 offset |= (insn & (1 << 13)) << 5;
7864 /* offset[19] = insn[11]. */
7865 offset |= (insn & (1 << 11)) << 8;
7866
7867 /* jump to the offset */
7868 gen_jmp(s, s->pc + offset);
7869 }
7870 } else {
7871 /* Data processing immediate. */
7872 if (insn & (1 << 25)) {
7873 if (insn & (1 << 24)) {
7874 if (insn & (1 << 20))
7875 goto illegal_op;
7876 /* Bitfield/Saturate. */
7877 op = (insn >> 21) & 7;
7878 imm = insn & 0x1f;
7879 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7880 if (rn == 15) {
7881 tmp = new_tmp();
7882 tcg_gen_movi_i32(tmp, 0);
7883 } else {
7884 tmp = load_reg(s, rn);
7885 }
7886 switch (op) {
7887 case 2: /* Signed bitfield extract. */
7888 imm++;
7889 if (shift + imm > 32)
7890 goto illegal_op;
7891 if (imm < 32)
7892 gen_sbfx(tmp, shift, imm);
7893 break;
7894 case 6: /* Unsigned bitfield extract. */
7895 imm++;
7896 if (shift + imm > 32)
7897 goto illegal_op;
7898 if (imm < 32)
7899 gen_ubfx(tmp, shift, (1u << imm) - 1);
7900 break;
7901 case 3: /* Bitfield insert/clear. */
7902 if (imm < shift)
7903 goto illegal_op;
7904 imm = imm + 1 - shift;
7905 if (imm != 32) {
7906 tmp2 = load_reg(s, rd);
7907 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7908 dead_tmp(tmp2);
7909 }
7910 break;
7911 case 7:
7912 goto illegal_op;
7913 default: /* Saturate. */
7914 if (shift) {
7915 if (op & 1)
7916 tcg_gen_sari_i32(tmp, tmp, shift);
7917 else
7918 tcg_gen_shli_i32(tmp, tmp, shift);
7919 }
7920 tmp2 = tcg_const_i32(imm);
7921 if (op & 4) {
7922 /* Unsigned. */
7923 if ((op & 1) && shift == 0)
7924 gen_helper_usat16(tmp, tmp, tmp2);
7925 else
7926 gen_helper_usat(tmp, tmp, tmp2);
7927 } else {
7928 /* Signed. */
7929 if ((op & 1) && shift == 0)
7930 gen_helper_ssat16(tmp, tmp, tmp2);
7931 else
7932 gen_helper_ssat(tmp, tmp, tmp2);
7933 }
7934 break;
7935 }
7936 store_reg(s, rd, tmp);
7937 } else {
7938 imm = ((insn & 0x04000000) >> 15)
7939 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7940 if (insn & (1 << 22)) {
7941 /* 16-bit immediate. */
7942 imm |= (insn >> 4) & 0xf000;
7943 if (insn & (1 << 23)) {
7944 /* movt */
7945 tmp = load_reg(s, rd);
7946 tcg_gen_ext16u_i32(tmp, tmp);
7947 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7948 } else {
7949 /* movw */
7950 tmp = new_tmp();
7951 tcg_gen_movi_i32(tmp, imm);
7952 }
7953 } else {
7954 /* Add/sub 12-bit immediate. */
7955 if (rn == 15) {
7956 offset = s->pc & ~(uint32_t)3;
7957 if (insn & (1 << 23))
7958 offset -= imm;
7959 else
7960 offset += imm;
7961 tmp = new_tmp();
7962 tcg_gen_movi_i32(tmp, offset);
7963 } else {
7964 tmp = load_reg(s, rn);
7965 if (insn & (1 << 23))
7966 tcg_gen_subi_i32(tmp, tmp, imm);
7967 else
7968 tcg_gen_addi_i32(tmp, tmp, imm);
7969 }
7970 }
7971 store_reg(s, rd, tmp);
7972 }
7973 } else {
7974 int shifter_out = 0;
7975 /* modified 12-bit immediate. */
7976 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7977 imm = (insn & 0xff);
7978 switch (shift) {
7979 case 0: /* XY */
7980 /* Nothing to do. */
7981 break;
7982 case 1: /* 00XY00XY */
7983 imm |= imm << 16;
7984 break;
7985 case 2: /* XY00XY00 */
7986 imm |= imm << 16;
7987 imm <<= 8;
7988 break;
7989 case 3: /* XYXYXYXY */
7990 imm |= imm << 16;
7991 imm |= imm << 8;
7992 break;
7993 default: /* Rotated constant. */
7994 shift = (shift << 1) | (imm >> 7);
7995 imm |= 0x80;
7996 imm = imm << (32 - shift);
7997 shifter_out = 1;
7998 break;
7999 }
8000 gen_op_movl_T1_im(imm);
8001 rn = (insn >> 16) & 0xf;
8002 if (rn == 15)
8003 gen_op_movl_T0_im(0);
8004 else
8005 gen_movl_T0_reg(s, rn);
8006 op = (insn >> 21) & 0xf;
8007 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8008 shifter_out))
8009 goto illegal_op;
8010 rd = (insn >> 8) & 0xf;
8011 if (rd != 15) {
8012 gen_movl_reg_T0(s, rd);
8013 }
8014 }
8015 }
8016 break;
8017 case 12: /* Load/store single data item. */
8018 {
8019 int postinc = 0;
8020 int writeback = 0;
8021 int user;
8022 if ((insn & 0x01100000) == 0x01000000) {
8023 if (disas_neon_ls_insn(env, s, insn))
8024 goto illegal_op;
8025 break;
8026 }
8027 user = IS_USER(s);
8028 if (rn == 15) {
8029 addr = new_tmp();
8030 /* PC relative. */
8031 /* s->pc has already been incremented by 4. */
8032 imm = s->pc & 0xfffffffc;
8033 if (insn & (1 << 23))
8034 imm += insn & 0xfff;
8035 else
8036 imm -= insn & 0xfff;
8037 tcg_gen_movi_i32(addr, imm);
8038 } else {
8039 addr = load_reg(s, rn);
8040 if (insn & (1 << 23)) {
8041 /* Positive offset. */
8042 imm = insn & 0xfff;
8043 tcg_gen_addi_i32(addr, addr, imm);
8044 } else {
8045 op = (insn >> 8) & 7;
8046 imm = insn & 0xff;
8047 switch (op) {
8048 case 0: case 8: /* Shifted Register. */
8049 shift = (insn >> 4) & 0xf;
8050 if (shift > 3)
8051 goto illegal_op;
8052 tmp = load_reg(s, rm);
8053 if (shift)
8054 tcg_gen_shli_i32(tmp, tmp, shift);
8055 tcg_gen_add_i32(addr, addr, tmp);
8056 dead_tmp(tmp);
8057 break;
8058 case 4: /* Negative offset. */
8059 tcg_gen_addi_i32(addr, addr, -imm);
8060 break;
8061 case 6: /* User privilege. */
8062 tcg_gen_addi_i32(addr, addr, imm);
8063 user = 1;
8064 break;
8065 case 1: /* Post-decrement. */
8066 imm = -imm;
8067 /* Fall through. */
8068 case 3: /* Post-increment. */
8069 postinc = 1;
8070 writeback = 1;
8071 break;
8072 case 5: /* Pre-decrement. */
8073 imm = -imm;
8074 /* Fall through. */
8075 case 7: /* Pre-increment. */
8076 tcg_gen_addi_i32(addr, addr, imm);
8077 writeback = 1;
8078 break;
8079 default:
8080 goto illegal_op;
8081 }
8082 }
8083 }
8084 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8085 if (insn & (1 << 20)) {
8086 /* Load. */
8087 if (rs == 15 && op != 2) {
8088 if (op & 2)
8089 goto illegal_op;
8090 /* Memory hint. Implemented as NOP. */
8091 } else {
8092 switch (op) {
8093 case 0: tmp = gen_ld8u(addr, user); break;
8094 case 4: tmp = gen_ld8s(addr, user); break;
8095 case 1: tmp = gen_ld16u(addr, user); break;
8096 case 5: tmp = gen_ld16s(addr, user); break;
8097 case 2: tmp = gen_ld32(addr, user); break;
8098 default: goto illegal_op;
8099 }
8100 if (rs == 15) {
8101 gen_bx(s, tmp);
8102 } else {
8103 store_reg(s, rs, tmp);
8104 }
8105 }
8106 } else {
8107 /* Store. */
8108 if (rs == 15)
8109 goto illegal_op;
8110 tmp = load_reg(s, rs);
8111 switch (op) {
8112 case 0: gen_st8(tmp, addr, user); break;
8113 case 1: gen_st16(tmp, addr, user); break;
8114 case 2: gen_st32(tmp, addr, user); break;
8115 default: goto illegal_op;
8116 }
8117 }
8118 if (postinc)
8119 tcg_gen_addi_i32(addr, addr, imm);
8120 if (writeback) {
8121 store_reg(s, rn, addr);
8122 } else {
8123 dead_tmp(addr);
8124 }
8125 }
8126 break;
8127 default:
8128 goto illegal_op;
8129 }
8130 return 0;
8131 illegal_op:
8132 return 1;
8133 }
8134
disas_thumb_insn(CPUState * env,DisasContext * s)8135 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8136 {
8137 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8138 int32_t offset;
8139 int i;
8140 TCGv tmp;
8141 TCGv tmp2;
8142 TCGv addr;
8143
8144 if (s->condexec_mask) {
8145 cond = s->condexec_cond;
8146 s->condlabel = gen_new_label();
8147 gen_test_cc(cond ^ 1, s->condlabel);
8148 s->condjmp = 1;
8149 }
8150
8151 insn = lduw_code(s->pc);
8152 #ifdef CONFIG_TRACE
8153 if (tracing) {
8154 int ticks = get_insn_ticks_thumb(insn);
8155 trace_add_insn( insn_wrap_thumb(insn), 1 );
8156 gen_traceInsn();
8157 gen_traceTicks(ticks);
8158 }
8159 #endif
8160 s->pc += 2;
8161
8162 switch (insn >> 12) {
8163 case 0: case 1:
8164 rd = insn & 7;
8165 op = (insn >> 11) & 3;
8166 if (op == 3) {
8167 /* add/subtract */
8168 rn = (insn >> 3) & 7;
8169 gen_movl_T0_reg(s, rn);
8170 if (insn & (1 << 10)) {
8171 /* immediate */
8172 gen_op_movl_T1_im((insn >> 6) & 7);
8173 } else {
8174 /* reg */
8175 rm = (insn >> 6) & 7;
8176 gen_movl_T1_reg(s, rm);
8177 }
8178 if (insn & (1 << 9)) {
8179 if (s->condexec_mask)
8180 gen_op_subl_T0_T1();
8181 else
8182 gen_op_subl_T0_T1_cc();
8183 } else {
8184 if (s->condexec_mask)
8185 gen_op_addl_T0_T1();
8186 else
8187 gen_op_addl_T0_T1_cc();
8188 }
8189 gen_movl_reg_T0(s, rd);
8190 } else {
8191 /* shift immediate */
8192 rm = (insn >> 3) & 7;
8193 shift = (insn >> 6) & 0x1f;
8194 tmp = load_reg(s, rm);
8195 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8196 if (!s->condexec_mask)
8197 gen_logic_CC(tmp);
8198 store_reg(s, rd, tmp);
8199 }
8200 break;
8201 case 2: case 3:
8202 /* arithmetic large immediate */
8203 op = (insn >> 11) & 3;
8204 rd = (insn >> 8) & 0x7;
8205 if (op == 0) {
8206 gen_op_movl_T0_im(insn & 0xff);
8207 } else {
8208 gen_movl_T0_reg(s, rd);
8209 gen_op_movl_T1_im(insn & 0xff);
8210 }
8211 switch (op) {
8212 case 0: /* mov */
8213 if (!s->condexec_mask)
8214 gen_op_logic_T0_cc();
8215 break;
8216 case 1: /* cmp */
8217 gen_op_subl_T0_T1_cc();
8218 break;
8219 case 2: /* add */
8220 if (s->condexec_mask)
8221 gen_op_addl_T0_T1();
8222 else
8223 gen_op_addl_T0_T1_cc();
8224 break;
8225 case 3: /* sub */
8226 if (s->condexec_mask)
8227 gen_op_subl_T0_T1();
8228 else
8229 gen_op_subl_T0_T1_cc();
8230 break;
8231 }
8232 if (op != 1)
8233 gen_movl_reg_T0(s, rd);
8234 break;
8235 case 4:
8236 if (insn & (1 << 11)) {
8237 rd = (insn >> 8) & 7;
8238 /* load pc-relative. Bit 1 of PC is ignored. */
8239 val = s->pc + 2 + ((insn & 0xff) * 4);
8240 val &= ~(uint32_t)2;
8241 addr = new_tmp();
8242 tcg_gen_movi_i32(addr, val);
8243 tmp = gen_ld32(addr, IS_USER(s));
8244 dead_tmp(addr);
8245 store_reg(s, rd, tmp);
8246 break;
8247 }
8248 if (insn & (1 << 10)) {
8249 /* data processing extended or blx */
8250 rd = (insn & 7) | ((insn >> 4) & 8);
8251 rm = (insn >> 3) & 0xf;
8252 op = (insn >> 8) & 3;
8253 switch (op) {
8254 case 0: /* add */
8255 gen_movl_T0_reg(s, rd);
8256 gen_movl_T1_reg(s, rm);
8257 gen_op_addl_T0_T1();
8258 gen_movl_reg_T0(s, rd);
8259 break;
8260 case 1: /* cmp */
8261 gen_movl_T0_reg(s, rd);
8262 gen_movl_T1_reg(s, rm);
8263 gen_op_subl_T0_T1_cc();
8264 break;
8265 case 2: /* mov/cpy */
8266 gen_movl_T0_reg(s, rm);
8267 gen_movl_reg_T0(s, rd);
8268 break;
8269 case 3:/* branch [and link] exchange thumb register */
8270 tmp = load_reg(s, rm);
8271 if (insn & (1 << 7)) {
8272 val = (uint32_t)s->pc | 1;
8273 tmp2 = new_tmp();
8274 tcg_gen_movi_i32(tmp2, val);
8275 store_reg(s, 14, tmp2);
8276 }
8277 gen_bx(s, tmp);
8278 break;
8279 }
8280 break;
8281 }
8282
8283 /* data processing register */
8284 rd = insn & 7;
8285 rm = (insn >> 3) & 7;
8286 op = (insn >> 6) & 0xf;
8287 if (op == 2 || op == 3 || op == 4 || op == 7) {
8288 /* the shift/rotate ops want the operands backwards */
8289 val = rm;
8290 rm = rd;
8291 rd = val;
8292 val = 1;
8293 } else {
8294 val = 0;
8295 }
8296
8297 if (op == 9) /* neg */
8298 gen_op_movl_T0_im(0);
8299 else if (op != 0xf) /* mvn doesn't read its first operand */
8300 gen_movl_T0_reg(s, rd);
8301
8302 gen_movl_T1_reg(s, rm);
8303 switch (op) {
8304 case 0x0: /* and */
8305 gen_op_andl_T0_T1();
8306 if (!s->condexec_mask)
8307 gen_op_logic_T0_cc();
8308 break;
8309 case 0x1: /* eor */
8310 gen_op_xorl_T0_T1();
8311 if (!s->condexec_mask)
8312 gen_op_logic_T0_cc();
8313 break;
8314 case 0x2: /* lsl */
8315 if (s->condexec_mask) {
8316 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8317 } else {
8318 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8319 gen_op_logic_T1_cc();
8320 }
8321 break;
8322 case 0x3: /* lsr */
8323 if (s->condexec_mask) {
8324 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8325 } else {
8326 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8327 gen_op_logic_T1_cc();
8328 }
8329 break;
8330 case 0x4: /* asr */
8331 if (s->condexec_mask) {
8332 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8333 } else {
8334 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8335 gen_op_logic_T1_cc();
8336 }
8337 break;
8338 case 0x5: /* adc */
8339 if (s->condexec_mask)
8340 gen_adc_T0_T1();
8341 else
8342 gen_op_adcl_T0_T1_cc();
8343 break;
8344 case 0x6: /* sbc */
8345 if (s->condexec_mask)
8346 gen_sbc_T0_T1();
8347 else
8348 gen_op_sbcl_T0_T1_cc();
8349 break;
8350 case 0x7: /* ror */
8351 if (s->condexec_mask) {
8352 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8353 } else {
8354 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8355 gen_op_logic_T1_cc();
8356 }
8357 break;
8358 case 0x8: /* tst */
8359 gen_op_andl_T0_T1();
8360 gen_op_logic_T0_cc();
8361 rd = 16;
8362 break;
8363 case 0x9: /* neg */
8364 if (s->condexec_mask)
8365 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
8366 else
8367 gen_op_subl_T0_T1_cc();
8368 break;
8369 case 0xa: /* cmp */
8370 gen_op_subl_T0_T1_cc();
8371 rd = 16;
8372 break;
8373 case 0xb: /* cmn */
8374 gen_op_addl_T0_T1_cc();
8375 rd = 16;
8376 break;
8377 case 0xc: /* orr */
8378 gen_op_orl_T0_T1();
8379 if (!s->condexec_mask)
8380 gen_op_logic_T0_cc();
8381 break;
8382 case 0xd: /* mul */
8383 gen_op_mull_T0_T1();
8384 if (!s->condexec_mask)
8385 gen_op_logic_T0_cc();
8386 break;
8387 case 0xe: /* bic */
8388 gen_op_bicl_T0_T1();
8389 if (!s->condexec_mask)
8390 gen_op_logic_T0_cc();
8391 break;
8392 case 0xf: /* mvn */
8393 gen_op_notl_T1();
8394 if (!s->condexec_mask)
8395 gen_op_logic_T1_cc();
8396 val = 1;
8397 rm = rd;
8398 break;
8399 }
8400 if (rd != 16) {
8401 if (val)
8402 gen_movl_reg_T1(s, rm);
8403 else
8404 gen_movl_reg_T0(s, rd);
8405 }
8406 break;
8407
8408 case 5:
8409 /* load/store register offset. */
8410 rd = insn & 7;
8411 rn = (insn >> 3) & 7;
8412 rm = (insn >> 6) & 7;
8413 op = (insn >> 9) & 7;
8414 addr = load_reg(s, rn);
8415 tmp = load_reg(s, rm);
8416 tcg_gen_add_i32(addr, addr, tmp);
8417 dead_tmp(tmp);
8418
8419 if (op < 3) /* store */
8420 tmp = load_reg(s, rd);
8421
8422 switch (op) {
8423 case 0: /* str */
8424 gen_st32(tmp, addr, IS_USER(s));
8425 break;
8426 case 1: /* strh */
8427 gen_st16(tmp, addr, IS_USER(s));
8428 break;
8429 case 2: /* strb */
8430 gen_st8(tmp, addr, IS_USER(s));
8431 break;
8432 case 3: /* ldrsb */
8433 tmp = gen_ld8s(addr, IS_USER(s));
8434 break;
8435 case 4: /* ldr */
8436 tmp = gen_ld32(addr, IS_USER(s));
8437 break;
8438 case 5: /* ldrh */
8439 tmp = gen_ld16u(addr, IS_USER(s));
8440 break;
8441 case 6: /* ldrb */
8442 tmp = gen_ld8u(addr, IS_USER(s));
8443 break;
8444 case 7: /* ldrsh */
8445 tmp = gen_ld16s(addr, IS_USER(s));
8446 break;
8447 }
8448 if (op >= 3) /* load */
8449 store_reg(s, rd, tmp);
8450 dead_tmp(addr);
8451 break;
8452
8453 case 6:
8454 /* load/store word immediate offset */
8455 rd = insn & 7;
8456 rn = (insn >> 3) & 7;
8457 addr = load_reg(s, rn);
8458 val = (insn >> 4) & 0x7c;
8459 tcg_gen_addi_i32(addr, addr, val);
8460
8461 if (insn & (1 << 11)) {
8462 /* load */
8463 tmp = gen_ld32(addr, IS_USER(s));
8464 store_reg(s, rd, tmp);
8465 } else {
8466 /* store */
8467 tmp = load_reg(s, rd);
8468 gen_st32(tmp, addr, IS_USER(s));
8469 }
8470 dead_tmp(addr);
8471 break;
8472
8473 case 7:
8474 /* load/store byte immediate offset */
8475 rd = insn & 7;
8476 rn = (insn >> 3) & 7;
8477 addr = load_reg(s, rn);
8478 val = (insn >> 6) & 0x1f;
8479 tcg_gen_addi_i32(addr, addr, val);
8480
8481 if (insn & (1 << 11)) {
8482 /* load */
8483 tmp = gen_ld8u(addr, IS_USER(s));
8484 store_reg(s, rd, tmp);
8485 } else {
8486 /* store */
8487 tmp = load_reg(s, rd);
8488 gen_st8(tmp, addr, IS_USER(s));
8489 }
8490 dead_tmp(addr);
8491 break;
8492
8493 case 8:
8494 /* load/store halfword immediate offset */
8495 rd = insn & 7;
8496 rn = (insn >> 3) & 7;
8497 addr = load_reg(s, rn);
8498 val = (insn >> 5) & 0x3e;
8499 tcg_gen_addi_i32(addr, addr, val);
8500
8501 if (insn & (1 << 11)) {
8502 /* load */
8503 tmp = gen_ld16u(addr, IS_USER(s));
8504 store_reg(s, rd, tmp);
8505 } else {
8506 /* store */
8507 tmp = load_reg(s, rd);
8508 gen_st16(tmp, addr, IS_USER(s));
8509 }
8510 dead_tmp(addr);
8511 break;
8512
8513 case 9:
8514 /* load/store from stack */
8515 rd = (insn >> 8) & 7;
8516 addr = load_reg(s, 13);
8517 val = (insn & 0xff) * 4;
8518 tcg_gen_addi_i32(addr, addr, val);
8519
8520 if (insn & (1 << 11)) {
8521 /* load */
8522 tmp = gen_ld32(addr, IS_USER(s));
8523 store_reg(s, rd, tmp);
8524 } else {
8525 /* store */
8526 tmp = load_reg(s, rd);
8527 gen_st32(tmp, addr, IS_USER(s));
8528 }
8529 dead_tmp(addr);
8530 break;
8531
8532 case 10:
8533 /* add to high reg */
8534 rd = (insn >> 8) & 7;
8535 if (insn & (1 << 11)) {
8536 /* SP */
8537 tmp = load_reg(s, 13);
8538 } else {
8539 /* PC. bit 1 is ignored. */
8540 tmp = new_tmp();
8541 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8542 }
8543 val = (insn & 0xff) * 4;
8544 tcg_gen_addi_i32(tmp, tmp, val);
8545 store_reg(s, rd, tmp);
8546 break;
8547
8548 case 11:
8549 /* misc */
8550 op = (insn >> 8) & 0xf;
8551 switch (op) {
8552 case 0:
8553 /* adjust stack pointer */
8554 tmp = load_reg(s, 13);
8555 val = (insn & 0x7f) * 4;
8556 if (insn & (1 << 7))
8557 val = -(int32_t)val;
8558 tcg_gen_addi_i32(tmp, tmp, val);
8559 store_reg(s, 13, tmp);
8560 break;
8561
8562 case 2: /* sign/zero extend. */
8563 ARCH(6);
8564 rd = insn & 7;
8565 rm = (insn >> 3) & 7;
8566 tmp = load_reg(s, rm);
8567 switch ((insn >> 6) & 3) {
8568 case 0: gen_sxth(tmp); break;
8569 case 1: gen_sxtb(tmp); break;
8570 case 2: gen_uxth(tmp); break;
8571 case 3: gen_uxtb(tmp); break;
8572 }
8573 store_reg(s, rd, tmp);
8574 break;
8575 case 4: case 5: case 0xc: case 0xd:
8576 /* push/pop */
8577 addr = load_reg(s, 13);
8578 if (insn & (1 << 8))
8579 offset = 4;
8580 else
8581 offset = 0;
8582 for (i = 0; i < 8; i++) {
8583 if (insn & (1 << i))
8584 offset += 4;
8585 }
8586 if ((insn & (1 << 11)) == 0) {
8587 tcg_gen_addi_i32(addr, addr, -offset);
8588 }
8589 for (i = 0; i < 8; i++) {
8590 if (insn & (1 << i)) {
8591 if (insn & (1 << 11)) {
8592 /* pop */
8593 tmp = gen_ld32(addr, IS_USER(s));
8594 store_reg(s, i, tmp);
8595 } else {
8596 /* push */
8597 tmp = load_reg(s, i);
8598 gen_st32(tmp, addr, IS_USER(s));
8599 }
8600 /* advance to the next address. */
8601 tcg_gen_addi_i32(addr, addr, 4);
8602 }
8603 }
8604 TCGV_UNUSED(tmp);
8605 if (insn & (1 << 8)) {
8606 if (insn & (1 << 11)) {
8607 /* pop pc */
8608 tmp = gen_ld32(addr, IS_USER(s));
8609 /* don't set the pc until the rest of the instruction
8610 has completed */
8611 } else {
8612 /* push lr */
8613 tmp = load_reg(s, 14);
8614 gen_st32(tmp, addr, IS_USER(s));
8615 }
8616 tcg_gen_addi_i32(addr, addr, 4);
8617 }
8618 if ((insn & (1 << 11)) == 0) {
8619 tcg_gen_addi_i32(addr, addr, -offset);
8620 }
8621 /* write back the new stack pointer */
8622 store_reg(s, 13, addr);
8623 /* set the new PC value */
8624 if ((insn & 0x0900) == 0x0900)
8625 gen_bx(s, tmp);
8626 break;
8627
8628 case 1: case 3: case 9: case 11: /* czb */
8629 rm = insn & 7;
8630 tmp = load_reg(s, rm);
8631 s->condlabel = gen_new_label();
8632 s->condjmp = 1;
8633 if (insn & (1 << 11))
8634 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8635 else
8636 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8637 dead_tmp(tmp);
8638 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8639 val = (uint32_t)s->pc + 2;
8640 val += offset;
8641 gen_jmp(s, val);
8642 break;
8643
8644 case 15: /* IT, nop-hint. */
8645 if ((insn & 0xf) == 0) {
8646 gen_nop_hint(s, (insn >> 4) & 0xf);
8647 break;
8648 }
8649 /* If Then. */
8650 s->condexec_cond = (insn >> 4) & 0xe;
8651 s->condexec_mask = insn & 0x1f;
8652 /* No actual code generated for this insn, just setup state. */
8653 break;
8654
8655 case 0xe: /* bkpt */
8656 gen_set_condexec(s);
8657 gen_set_pc_im(s->pc - 2);
8658 gen_exception(EXCP_BKPT);
8659 s->is_jmp = DISAS_JUMP;
8660 break;
8661
8662 case 0xa: /* rev */
8663 ARCH(6);
8664 rn = (insn >> 3) & 0x7;
8665 rd = insn & 0x7;
8666 tmp = load_reg(s, rn);
8667 switch ((insn >> 6) & 3) {
8668 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8669 case 1: gen_rev16(tmp); break;
8670 case 3: gen_revsh(tmp); break;
8671 default: goto illegal_op;
8672 }
8673 store_reg(s, rd, tmp);
8674 break;
8675
8676 case 6: /* cps */
8677 ARCH(6);
8678 if (IS_USER(s))
8679 break;
8680 if (IS_M(env)) {
8681 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8682 /* PRIMASK */
8683 if (insn & 1) {
8684 addr = tcg_const_i32(16);
8685 gen_helper_v7m_msr(cpu_env, addr, tmp);
8686 }
8687 /* FAULTMASK */
8688 if (insn & 2) {
8689 addr = tcg_const_i32(17);
8690 gen_helper_v7m_msr(cpu_env, addr, tmp);
8691 }
8692 gen_lookup_tb(s);
8693 } else {
8694 if (insn & (1 << 4))
8695 shift = CPSR_A | CPSR_I | CPSR_F;
8696 else
8697 shift = 0;
8698
8699 val = ((insn & 7) << 6) & shift;
8700 gen_op_movl_T0_im(val);
8701 gen_set_psr_T0(s, shift, 0);
8702 }
8703 break;
8704
8705 default:
8706 goto undef;
8707 }
8708 break;
8709
8710 case 12:
8711 /* load/store multiple */
8712 rn = (insn >> 8) & 0x7;
8713 addr = load_reg(s, rn);
8714 for (i = 0; i < 8; i++) {
8715 if (insn & (1 << i)) {
8716 if (insn & (1 << 11)) {
8717 /* load */
8718 tmp = gen_ld32(addr, IS_USER(s));
8719 store_reg(s, i, tmp);
8720 } else {
8721 /* store */
8722 tmp = load_reg(s, i);
8723 gen_st32(tmp, addr, IS_USER(s));
8724 }
8725 /* advance to the next address */
8726 tcg_gen_addi_i32(addr, addr, 4);
8727 }
8728 }
8729 /* Base register writeback. */
8730 if ((insn & (1 << rn)) == 0) {
8731 store_reg(s, rn, addr);
8732 } else {
8733 dead_tmp(addr);
8734 }
8735 break;
8736
8737 case 13:
8738 /* conditional branch or swi */
8739 cond = (insn >> 8) & 0xf;
8740 if (cond == 0xe)
8741 goto undef;
8742
8743 if (cond == 0xf) {
8744 /* swi */
8745 gen_set_condexec(s);
8746 gen_set_pc_im(s->pc);
8747 s->is_jmp = DISAS_SWI;
8748 break;
8749 }
8750 /* generate a conditional jump to next instruction */
8751 s->condlabel = gen_new_label();
8752 gen_test_cc(cond ^ 1, s->condlabel);
8753 s->condjmp = 1;
8754 gen_movl_T1_reg(s, 15);
8755
8756 /* jump to the offset */
8757 val = (uint32_t)s->pc + 2;
8758 offset = ((int32_t)insn << 24) >> 24;
8759 val += offset << 1;
8760 gen_jmp(s, val);
8761 break;
8762
8763 case 14:
8764 if (insn & (1 << 11)) {
8765 if (disas_thumb2_insn(env, s, insn))
8766 goto undef32;
8767 break;
8768 }
8769 /* unconditional branch */
8770 val = (uint32_t)s->pc;
8771 offset = ((int32_t)insn << 21) >> 21;
8772 val += (offset << 1) + 2;
8773 gen_jmp(s, val);
8774 break;
8775
8776 case 15:
8777 if (disas_thumb2_insn(env, s, insn))
8778 goto undef32;
8779 break;
8780 }
8781 return;
8782 undef32:
8783 gen_set_condexec(s);
8784 gen_set_pc_im(s->pc - 4);
8785 gen_exception(EXCP_UDEF);
8786 s->is_jmp = DISAS_JUMP;
8787 return;
8788 illegal_op:
8789 undef:
8790 gen_set_condexec(s);
8791 gen_set_pc_im(s->pc - 2);
8792 gen_exception(EXCP_UDEF);
8793 s->is_jmp = DISAS_JUMP;
8794 }
8795
8796 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8797 basic block 'tb'. If search_pc is TRUE, also generate PC
8798 information for each intermediate instruction. */
gen_intermediate_code_internal(CPUState * env,TranslationBlock * tb,int search_pc)8799 static inline void gen_intermediate_code_internal(CPUState *env,
8800 TranslationBlock *tb,
8801 int search_pc)
8802 {
8803 DisasContext dc1, *dc = &dc1;
8804 CPUBreakpoint *bp;
8805 uint16_t *gen_opc_end;
8806 int j, lj;
8807 target_ulong pc_start;
8808 uint32_t next_page_start;
8809 int num_insns;
8810 int max_insns;
8811
8812 /* generate intermediate code */
8813 num_temps = 0;
8814 memset(temps, 0, sizeof(temps));
8815
8816 pc_start = tb->pc;
8817
8818 dc->tb = tb;
8819
8820 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8821
8822 dc->is_jmp = DISAS_NEXT;
8823 dc->pc = pc_start;
8824 dc->singlestep_enabled = env->singlestep_enabled;
8825 dc->condjmp = 0;
8826 dc->thumb = env->thumb;
8827 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8828 dc->condexec_mask_prev = dc->condexec_mask;
8829 dc->condexec_cond = env->condexec_bits >> 4;
8830 #if !defined(CONFIG_USER_ONLY)
8831 if (IS_M(env)) {
8832 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8833 } else {
8834 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8835 }
8836 #endif
8837 cpu_F0s = tcg_temp_new_i32();
8838 cpu_F1s = tcg_temp_new_i32();
8839 cpu_F0d = tcg_temp_new_i64();
8840 cpu_F1d = tcg_temp_new_i64();
8841 cpu_V0 = cpu_F0d;
8842 cpu_V1 = cpu_F1d;
8843 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8844 cpu_M0 = tcg_temp_new_i64();
8845 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8846 lj = -1;
8847 num_insns = 0;
8848 max_insns = tb->cflags & CF_COUNT_MASK;
8849 if (max_insns == 0)
8850 max_insns = CF_COUNT_MASK;
8851
8852 gen_icount_start();
8853 #ifdef CONFIG_TRACE
8854 if (tracing) {
8855 gen_traceBB(trace_static.bb_num, (target_phys_addr_t)tb );
8856 trace_bb_start(dc->pc);
8857 }
8858 #endif
8859
8860 do {
8861 #ifdef CONFIG_USER_ONLY
8862 /* Intercept jump to the magic kernel page. */
8863 if (dc->pc >= 0xffff0000) {
8864 /* We always get here via a jump, so know we are not in a
8865 conditional execution block. */
8866 gen_exception(EXCP_KERNEL_TRAP);
8867 dc->is_jmp = DISAS_UPDATE;
8868 break;
8869 }
8870 #else
8871 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8872 /* We always get here via a jump, so know we are not in a
8873 conditional execution block. */
8874 gen_exception(EXCP_EXCEPTION_EXIT);
8875 dc->is_jmp = DISAS_UPDATE;
8876 break;
8877 }
8878 #endif
8879
8880 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8881 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8882 if (bp->pc == dc->pc) {
8883 gen_set_condexec(dc);
8884 gen_set_pc_im(dc->pc);
8885 gen_exception(EXCP_DEBUG);
8886 dc->is_jmp = DISAS_JUMP;
8887 /* Advance PC so that clearing the breakpoint will
8888 invalidate this TB. */
8889 dc->pc += 2;
8890 goto done_generating;
8891 break;
8892 }
8893 }
8894 }
8895 if (search_pc) {
8896 j = gen_opc_ptr - gen_opc_buf;
8897 if (lj < j) {
8898 lj++;
8899 while (lj < j)
8900 gen_opc_instr_start[lj++] = 0;
8901 }
8902 gen_opc_pc[lj] = dc->pc;
8903 gen_opc_instr_start[lj] = 1;
8904 gen_opc_icount[lj] = num_insns;
8905 }
8906
8907 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8908 gen_io_start();
8909
8910 if (env->thumb) {
8911 disas_thumb_insn(env, dc);
8912 dc->condexec_mask_prev = dc->condexec_mask;
8913 if (dc->condexec_mask) {
8914 dc->condexec_cond = (dc->condexec_cond & 0xe)
8915 | ((dc->condexec_mask >> 4) & 1);
8916 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8917 if (dc->condexec_mask == 0) {
8918 dc->condexec_cond = 0;
8919 }
8920 }
8921 } else {
8922 disas_arm_insn(env, dc);
8923 }
8924 if (num_temps) {
8925 fprintf(stderr, "Internal resource leak before %08x (%d temps)\n", dc->pc, num_temps);
8926 tcg_dump_ops(&tcg_ctx, stderr);
8927 num_temps = 0;
8928 }
8929
8930 if (dc->condjmp && !dc->is_jmp) {
8931 gen_set_label(dc->condlabel);
8932 dc->condjmp = 0;
8933 }
8934 /* Translation stops when a conditional branch is encountered.
8935 * Otherwise the subsequent code could get translated several times.
8936 * Also stop translation when a page boundary is reached. This
8937 * ensures prefetch aborts occur at the right place. */
8938 num_insns ++;
8939 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8940 !env->singlestep_enabled &&
8941 !singlestep &&
8942 dc->pc < next_page_start &&
8943 num_insns < max_insns);
8944
8945 #ifdef CONFIG_TRACE
8946 if (tracing) {
8947 trace_bb_end();
8948 }
8949 #endif
8950
8951 if (tb->cflags & CF_LAST_IO) {
8952 if (dc->condjmp) {
8953 /* FIXME: This can theoretically happen with self-modifying
8954 code. */
8955 cpu_abort(env, "IO on conditional branch instruction");
8956 }
8957 gen_io_end();
8958 }
8959
8960 /* At this stage dc->condjmp will only be set when the skipped
8961 instruction was a conditional branch or trap, and the PC has
8962 already been written. */
8963 if (unlikely(env->singlestep_enabled)) {
8964 /* Make sure the pc is updated, and raise a debug exception. */
8965 if (dc->condjmp) {
8966 gen_set_condexec(dc);
8967 if (dc->is_jmp == DISAS_SWI) {
8968 gen_exception(EXCP_SWI);
8969 } else {
8970 gen_exception(EXCP_DEBUG);
8971 }
8972 gen_set_label(dc->condlabel);
8973 }
8974 if (dc->condjmp || !dc->is_jmp) {
8975 gen_set_pc_im(dc->pc);
8976 dc->condjmp = 0;
8977 }
8978 gen_set_condexec(dc);
8979 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8980 gen_exception(EXCP_SWI);
8981 } else {
8982 /* FIXME: Single stepping a WFI insn will not halt
8983 the CPU. */
8984 gen_exception(EXCP_DEBUG);
8985 }
8986 } else {
8987 /* While branches must always occur at the end of an IT block,
8988 there are a few other things that can cause us to terminate
8989 the TB in the middel of an IT block:
8990 - Exception generating instructions (bkpt, swi, undefined).
8991 - Page boundaries.
8992 - Hardware watchpoints.
8993 Hardware breakpoints have already been handled and skip this code.
8994 */
8995 gen_set_condexec(dc);
8996 switch(dc->is_jmp) {
8997 case DISAS_NEXT:
8998 gen_goto_tb(dc, 1, dc->pc);
8999 break;
9000 default:
9001 case DISAS_JUMP:
9002 case DISAS_UPDATE:
9003 /* indicate that the hash table must be used to find the next TB */
9004 tcg_gen_exit_tb(0);
9005 break;
9006 case DISAS_TB_JUMP:
9007 /* nothing more to generate */
9008 break;
9009 case DISAS_WFI:
9010 gen_helper_wfi();
9011 break;
9012 case DISAS_SWI:
9013 gen_exception(EXCP_SWI);
9014 break;
9015 }
9016 if (dc->condjmp) {
9017 gen_set_label(dc->condlabel);
9018 gen_set_condexec(dc);
9019 gen_goto_tb(dc, 1, dc->pc);
9020 dc->condjmp = 0;
9021 }
9022 }
9023
9024 done_generating:
9025 gen_icount_end(tb, num_insns);
9026 *gen_opc_ptr = INDEX_op_end;
9027
9028 #ifdef DEBUG_DISAS
9029 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9030 qemu_log("----------------\n");
9031 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9032 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9033 qemu_log("\n");
9034 }
9035 #endif
9036 if (search_pc) {
9037 j = gen_opc_ptr - gen_opc_buf;
9038 lj++;
9039 while (lj <= j)
9040 gen_opc_instr_start[lj++] = 0;
9041 } else {
9042 tb->size = dc->pc - pc_start;
9043 tb->icount = num_insns;
9044 }
9045 }
9046
gen_intermediate_code(CPUState * env,TranslationBlock * tb)9047 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9048 {
9049 gen_intermediate_code_internal(env, tb, 0);
9050 }
9051
gen_intermediate_code_pc(CPUState * env,TranslationBlock * tb)9052 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9053 {
9054 gen_intermediate_code_internal(env, tb, 1);
9055 }
9056
9057 static const char *cpu_mode_names[16] = {
9058 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9059 "???", "???", "???", "und", "???", "???", "???", "sys"
9060 };
9061
cpu_dump_state(CPUState * env,FILE * f,int (* cpu_fprintf)(FILE * f,const char * fmt,...),int flags)9062 void cpu_dump_state(CPUState *env, FILE *f,
9063 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9064 int flags)
9065 {
9066 int i;
9067 #if 0
9068 union {
9069 uint32_t i;
9070 float s;
9071 } s0, s1;
9072 CPU_DoubleU d;
9073 /* ??? This assumes float64 and double have the same layout.
9074 Oh well, it's only debug dumps. */
9075 union {
9076 float64 f64;
9077 double d;
9078 } d0;
9079 #endif
9080 uint32_t psr;
9081
9082 for(i=0;i<16;i++) {
9083 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9084 if ((i % 4) == 3)
9085 cpu_fprintf(f, "\n");
9086 else
9087 cpu_fprintf(f, " ");
9088 }
9089 psr = cpsr_read(env);
9090 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9091 psr,
9092 psr & (1 << 31) ? 'N' : '-',
9093 psr & (1 << 30) ? 'Z' : '-',
9094 psr & (1 << 29) ? 'C' : '-',
9095 psr & (1 << 28) ? 'V' : '-',
9096 psr & CPSR_T ? 'T' : 'A',
9097 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9098
9099 #if 0
9100 for (i = 0; i < 16; i++) {
9101 d.d = env->vfp.regs[i];
9102 s0.i = d.l.lower;
9103 s1.i = d.l.upper;
9104 d0.f64 = d.d;
9105 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9106 i * 2, (int)s0.i, s0.s,
9107 i * 2 + 1, (int)s1.i, s1.s,
9108 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9109 d0.d);
9110 }
9111 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9112 #endif
9113 }
9114
gen_pc_load(CPUState * env,TranslationBlock * tb,unsigned long searched_pc,int pc_pos,void * puc)9115 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9116 unsigned long searched_pc, int pc_pos, void *puc)
9117 {
9118 env->regs[15] = gen_opc_pc[pc_pos];
9119 }
9120