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