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