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, see <http://www.gnu.org/licenses/>. 20 */ 21 #include <stdarg.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <inttypes.h> 26 27 #include "cpu.h" 28 #include "exec-all.h" 29 #include "disas.h" 30 #include "tcg-op.h" 31 #include "qemu-log.h" 32 33 #include "helper.h" 34 #define GEN_HELPER 1 35 #include "helper.h" 36 37 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T) 38 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5) 39 /* currently all emulated v5 cores are also v5TE, so don't bother */ 40 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5) 41 #define ENABLE_ARCH_5J 0 42 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) 43 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K) 44 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) 45 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) 46 47 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) 48 49 /* internal defines */ 50 typedef struct DisasContext { 51 target_ulong pc; 52 int is_jmp; 53 /* Nonzero if this instruction has been conditionally skipped. */ 54 int condjmp; 55 /* The label that will be jumped to when the instruction is skipped. */ 56 int condlabel; 57 /* Thumb-2 condtional execution bits. */ 58 int condexec_mask; 59 int condexec_cond; 60 struct TranslationBlock *tb; 61 int singlestep_enabled; 62 int thumb; 63 #if !defined(CONFIG_USER_ONLY) 64 int user; 65 #endif 66 int vfp_enabled; 67 int vec_len; 68 int vec_stride; 69 #ifdef CONFIG_MEMCHECK 70 int search_pc; 71 #endif 72 } DisasContext; 73 74 #include "translate-android.h" 75 76 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE]; 77 78 #if defined(CONFIG_USER_ONLY) 79 #define IS_USER(s) 1 80 #else 81 #define IS_USER(s) (s->user) 82 #endif 83 84 /* These instructions trap after executing, so defer them until after the 85 conditional executions state has been updated. */ 86 #define DISAS_WFI 4 87 #define DISAS_SWI 5 88 #define DISAS_SMC 6 89 90 static TCGv_ptr cpu_env; 91 /* We reuse the same 64-bit temporaries for efficiency. */ 92 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; 93 static TCGv_i32 cpu_R[16]; 94 static TCGv_i32 cpu_exclusive_addr; 95 static TCGv_i32 cpu_exclusive_val; 96 static TCGv_i32 cpu_exclusive_high; 97 #ifdef CONFIG_USER_ONLY 98 static TCGv_i32 cpu_exclusive_test; 99 static TCGv_i32 cpu_exclusive_info; 100 #endif 101 102 /* FIXME: These should be removed. */ 103 static TCGv cpu_F0s, cpu_F1s; 104 static TCGv_i64 cpu_F0d, cpu_F1d; 105 106 #include "gen-icount.h" 107 108 static const char *regnames[] = 109 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 110 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" }; 111 112 /* initialize TCG globals. */ 113 void arm_translate_init(void) 114 { 115 int i; 116 117 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 118 119 for (i = 0; i < 16; i++) { 120 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, 121 offsetof(CPUState, regs[i]), 122 regnames[i]); 123 } 124 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0, 125 offsetof(CPUState, exclusive_addr), "exclusive_addr"); 126 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0, 127 offsetof(CPUState, exclusive_val), "exclusive_val"); 128 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0, 129 offsetof(CPUState, exclusive_high), "exclusive_high"); 130 #ifdef CONFIG_USER_ONLY 131 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0, 132 offsetof(CPUState, exclusive_test), "exclusive_test"); 133 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0, 134 offsetof(CPUState, exclusive_info), "exclusive_info"); 135 #endif 136 137 #define GEN_HELPER 2 138 #include "helper.h" 139 } 140 141 static inline TCGv load_cpu_offset(int offset) 142 { 143 TCGv tmp = tcg_temp_new_i32(); 144 tcg_gen_ld_i32(tmp, cpu_env, offset); 145 return tmp; 146 } 147 148 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name)) 149 150 static inline void store_cpu_offset(TCGv var, int offset) 151 { 152 tcg_gen_st_i32(var, cpu_env, offset); 153 tcg_temp_free_i32(var); 154 } 155 156 #define store_cpu_field(var, name) \ 157 store_cpu_offset(var, offsetof(CPUState, name)) 158 159 /* Set a variable to the value of a CPU register. */ 160 static void load_reg_var(DisasContext *s, TCGv var, int reg) 161 { 162 if (reg == 15) { 163 uint32_t addr; 164 /* normaly, since we updated PC, we need only to add one insn */ 165 if (s->thumb) 166 addr = (long)s->pc + 2; 167 else 168 addr = (long)s->pc + 4; 169 tcg_gen_movi_i32(var, addr); 170 } else { 171 tcg_gen_mov_i32(var, cpu_R[reg]); 172 } 173 } 174 175 /* Create a new temporary and set it to the value of a CPU register. */ 176 static inline TCGv load_reg(DisasContext *s, int reg) 177 { 178 TCGv tmp = tcg_temp_new_i32(); 179 load_reg_var(s, tmp, reg); 180 return tmp; 181 } 182 183 /* Set a CPU register. The source must be a temporary and will be 184 marked as dead. */ 185 static void store_reg(DisasContext *s, int reg, TCGv var) 186 { 187 if (reg == 15) { 188 tcg_gen_andi_i32(var, var, ~1); 189 s->is_jmp = DISAS_JUMP; 190 } 191 tcg_gen_mov_i32(cpu_R[reg], var); 192 tcg_temp_free_i32(var); 193 } 194 195 /* Value extensions. */ 196 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) 197 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var) 198 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) 199 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var) 200 201 #define gen_sxtb16(var) gen_helper_sxtb16(var, var) 202 #define gen_uxtb16(var) gen_helper_uxtb16(var, var) 203 204 205 static inline void gen_set_cpsr(TCGv var, uint32_t mask) 206 { 207 TCGv tmp_mask = tcg_const_i32(mask); 208 gen_helper_cpsr_write(var, tmp_mask); 209 tcg_temp_free_i32(tmp_mask); 210 } 211 /* Set NZCV flags from the high 4 bits of var. */ 212 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) 213 214 static void gen_exception(int excp) 215 { 216 TCGv tmp = tcg_temp_new_i32(); 217 tcg_gen_movi_i32(tmp, excp); 218 gen_helper_exception(tmp); 219 tcg_temp_free_i32(tmp); 220 } 221 222 static void gen_smul_dual(TCGv a, TCGv b) 223 { 224 TCGv tmp1 = tcg_temp_new_i32(); 225 TCGv tmp2 = tcg_temp_new_i32(); 226 tcg_gen_ext16s_i32(tmp1, a); 227 tcg_gen_ext16s_i32(tmp2, b); 228 tcg_gen_mul_i32(tmp1, tmp1, tmp2); 229 tcg_temp_free_i32(tmp2); 230 tcg_gen_sari_i32(a, a, 16); 231 tcg_gen_sari_i32(b, b, 16); 232 tcg_gen_mul_i32(b, b, a); 233 tcg_gen_mov_i32(a, tmp1); 234 tcg_temp_free_i32(tmp1); 235 } 236 237 /* Byteswap each halfword. */ 238 static void gen_rev16(TCGv var) 239 { 240 TCGv tmp = tcg_temp_new_i32(); 241 tcg_gen_shri_i32(tmp, var, 8); 242 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff); 243 tcg_gen_shli_i32(var, var, 8); 244 tcg_gen_andi_i32(var, var, 0xff00ff00); 245 tcg_gen_or_i32(var, var, tmp); 246 tcg_temp_free_i32(tmp); 247 } 248 249 /* Byteswap low halfword and sign extend. */ 250 static void gen_revsh(TCGv var) 251 { 252 tcg_gen_ext16u_i32(var, var); 253 tcg_gen_bswap16_i32(var, var); 254 tcg_gen_ext16s_i32(var, var); 255 } 256 257 /* Unsigned bitfield extract. */ 258 static void gen_ubfx(TCGv var, int shift, uint32_t mask) 259 { 260 if (shift) 261 tcg_gen_shri_i32(var, var, shift); 262 tcg_gen_andi_i32(var, var, mask); 263 } 264 265 /* Signed bitfield extract. */ 266 static void gen_sbfx(TCGv var, int shift, int width) 267 { 268 uint32_t signbit; 269 270 if (shift) 271 tcg_gen_sari_i32(var, var, shift); 272 if (shift + width < 32) { 273 signbit = 1u << (width - 1); 274 tcg_gen_andi_i32(var, var, (1u << width) - 1); 275 tcg_gen_xori_i32(var, var, signbit); 276 tcg_gen_subi_i32(var, var, signbit); 277 } 278 } 279 280 /* Bitfield insertion. Insert val into base. Clobbers base and val. */ 281 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask) 282 { 283 tcg_gen_andi_i32(val, val, mask); 284 tcg_gen_shli_i32(val, val, shift); 285 tcg_gen_andi_i32(base, base, ~(mask << shift)); 286 tcg_gen_or_i32(dest, base, val); 287 } 288 289 /* Return (b << 32) + a. Mark inputs as dead */ 290 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) 291 { 292 TCGv_i64 tmp64 = tcg_temp_new_i64(); 293 294 tcg_gen_extu_i32_i64(tmp64, b); 295 tcg_temp_free_i32(b); 296 tcg_gen_shli_i64(tmp64, tmp64, 32); 297 tcg_gen_add_i64(a, tmp64, a); 298 299 tcg_temp_free_i64(tmp64); 300 return a; 301 } 302 303 /* Return (b << 32) - a. Mark inputs as dead. */ 304 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) 305 { 306 TCGv_i64 tmp64 = tcg_temp_new_i64(); 307 308 tcg_gen_extu_i32_i64(tmp64, b); 309 tcg_temp_free_i32(b); 310 tcg_gen_shli_i64(tmp64, tmp64, 32); 311 tcg_gen_sub_i64(a, tmp64, a); 312 313 tcg_temp_free_i64(tmp64); 314 return a; 315 } 316 317 /* FIXME: Most targets have native widening multiplication. 318 It would be good to use that instead of a full wide multiply. */ 319 /* 32x32->64 multiply. Marks inputs as dead. */ 320 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) 321 { 322 TCGv_i64 tmp1 = tcg_temp_new_i64(); 323 TCGv_i64 tmp2 = tcg_temp_new_i64(); 324 325 tcg_gen_extu_i32_i64(tmp1, a); 326 tcg_temp_free_i32(a); 327 tcg_gen_extu_i32_i64(tmp2, b); 328 tcg_temp_free_i32(b); 329 tcg_gen_mul_i64(tmp1, tmp1, tmp2); 330 tcg_temp_free_i64(tmp2); 331 return tmp1; 332 } 333 334 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) 335 { 336 TCGv_i64 tmp1 = tcg_temp_new_i64(); 337 TCGv_i64 tmp2 = tcg_temp_new_i64(); 338 339 tcg_gen_ext_i32_i64(tmp1, a); 340 tcg_temp_free_i32(a); 341 tcg_gen_ext_i32_i64(tmp2, b); 342 tcg_temp_free_i32(b); 343 tcg_gen_mul_i64(tmp1, tmp1, tmp2); 344 tcg_temp_free_i64(tmp2); 345 return tmp1; 346 } 347 348 /* Swap low and high halfwords. */ 349 static void gen_swap_half(TCGv var) 350 { 351 TCGv tmp = tcg_temp_new_i32(); 352 tcg_gen_shri_i32(tmp, var, 16); 353 tcg_gen_shli_i32(var, var, 16); 354 tcg_gen_or_i32(var, var, tmp); 355 tcg_temp_free_i32(tmp); 356 } 357 358 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. 359 tmp = (t0 ^ t1) & 0x8000; 360 t0 &= ~0x8000; 361 t1 &= ~0x8000; 362 t0 = (t0 + t1) ^ tmp; 363 */ 364 365 static void gen_add16(TCGv t0, TCGv t1) 366 { 367 TCGv tmp = tcg_temp_new_i32(); 368 tcg_gen_xor_i32(tmp, t0, t1); 369 tcg_gen_andi_i32(tmp, tmp, 0x8000); 370 tcg_gen_andi_i32(t0, t0, ~0x8000); 371 tcg_gen_andi_i32(t1, t1, ~0x8000); 372 tcg_gen_add_i32(t0, t0, t1); 373 tcg_gen_xor_i32(t0, t0, tmp); 374 tcg_temp_free_i32(tmp); 375 tcg_temp_free_i32(t1); 376 } 377 378 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF)) 379 380 /* Set CF to the top bit of var. */ 381 static void gen_set_CF_bit31(TCGv var) 382 { 383 TCGv tmp = tcg_temp_new_i32(); 384 tcg_gen_shri_i32(tmp, var, 31); 385 gen_set_CF(tmp); 386 tcg_temp_free_i32(tmp); 387 } 388 389 /* Set N and Z flags from var. */ 390 static inline void gen_logic_CC(TCGv var) 391 { 392 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF)); 393 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF)); 394 } 395 396 /* T0 += T1 + CF. */ 397 static void gen_adc(TCGv t0, TCGv t1) 398 { 399 TCGv tmp; 400 tcg_gen_add_i32(t0, t0, t1); 401 tmp = load_cpu_field(CF); 402 tcg_gen_add_i32(t0, t0, tmp); 403 tcg_temp_free_i32(tmp); 404 } 405 406 /* dest = T0 + T1 + CF. */ 407 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) 408 { 409 TCGv tmp; 410 tcg_gen_add_i32(dest, t0, t1); 411 tmp = load_cpu_field(CF); 412 tcg_gen_add_i32(dest, dest, tmp); 413 tcg_temp_free_i32(tmp); 414 } 415 416 /* dest = T0 - T1 + CF - 1. */ 417 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) 418 { 419 TCGv tmp; 420 tcg_gen_sub_i32(dest, t0, t1); 421 tmp = load_cpu_field(CF); 422 tcg_gen_add_i32(dest, dest, tmp); 423 tcg_gen_subi_i32(dest, dest, 1); 424 tcg_temp_free_i32(tmp); 425 } 426 427 /* FIXME: Implement this natively. */ 428 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) 429 430 static void shifter_out_im(TCGv var, int shift) 431 { 432 TCGv tmp = tcg_temp_new_i32(); 433 if (shift == 0) { 434 tcg_gen_andi_i32(tmp, var, 1); 435 } else { 436 tcg_gen_shri_i32(tmp, var, shift); 437 if (shift != 31) 438 tcg_gen_andi_i32(tmp, tmp, 1); 439 } 440 gen_set_CF(tmp); 441 tcg_temp_free_i32(tmp); 442 } 443 444 /* Shift by immediate. Includes special handling for shift == 0. */ 445 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) 446 { 447 switch (shiftop) { 448 case 0: /* LSL */ 449 if (shift != 0) { 450 if (flags) 451 shifter_out_im(var, 32 - shift); 452 tcg_gen_shli_i32(var, var, shift); 453 } 454 break; 455 case 1: /* LSR */ 456 if (shift == 0) { 457 if (flags) { 458 tcg_gen_shri_i32(var, var, 31); 459 gen_set_CF(var); 460 } 461 tcg_gen_movi_i32(var, 0); 462 } else { 463 if (flags) 464 shifter_out_im(var, shift - 1); 465 tcg_gen_shri_i32(var, var, shift); 466 } 467 break; 468 case 2: /* ASR */ 469 if (shift == 0) 470 shift = 32; 471 if (flags) 472 shifter_out_im(var, shift - 1); 473 if (shift == 32) 474 shift = 31; 475 tcg_gen_sari_i32(var, var, shift); 476 break; 477 case 3: /* ROR/RRX */ 478 if (shift != 0) { 479 if (flags) 480 shifter_out_im(var, shift - 1); 481 tcg_gen_rotri_i32(var, var, shift); break; 482 } else { 483 TCGv tmp = load_cpu_field(CF); 484 if (flags) 485 shifter_out_im(var, 0); 486 tcg_gen_shri_i32(var, var, 1); 487 tcg_gen_shli_i32(tmp, tmp, 31); 488 tcg_gen_or_i32(var, var, tmp); 489 tcg_temp_free_i32(tmp); 490 } 491 } 492 }; 493 494 static inline void gen_arm_shift_reg(TCGv var, int shiftop, 495 TCGv shift, int flags) 496 { 497 if (flags) { 498 switch (shiftop) { 499 case 0: gen_helper_shl_cc(var, var, shift); break; 500 case 1: gen_helper_shr_cc(var, var, shift); break; 501 case 2: gen_helper_sar_cc(var, var, shift); break; 502 case 3: gen_helper_ror_cc(var, var, shift); break; 503 } 504 } else { 505 switch (shiftop) { 506 case 0: gen_helper_shl(var, var, shift); break; 507 case 1: gen_helper_shr(var, var, shift); break; 508 case 2: gen_helper_sar(var, var, shift); break; 509 case 3: tcg_gen_andi_i32(shift, shift, 0x1f); 510 tcg_gen_rotr_i32(var, var, shift); break; 511 } 512 } 513 tcg_temp_free_i32(shift); 514 } 515 516 #define PAS_OP(pfx) \ 517 switch (op2) { \ 518 case 0: gen_pas_helper(glue(pfx,add16)); break; \ 519 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \ 520 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \ 521 case 3: gen_pas_helper(glue(pfx,sub16)); break; \ 522 case 4: gen_pas_helper(glue(pfx,add8)); break; \ 523 case 7: gen_pas_helper(glue(pfx,sub8)); break; \ 524 } 525 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 526 { 527 TCGv_ptr tmp; 528 529 switch (op1) { 530 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 531 case 1: 532 tmp = tcg_temp_new_ptr(); 533 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 534 PAS_OP(s) 535 tcg_temp_free_ptr(tmp); 536 break; 537 case 5: 538 tmp = tcg_temp_new_ptr(); 539 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 540 PAS_OP(u) 541 tcg_temp_free_ptr(tmp); 542 break; 543 #undef gen_pas_helper 544 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 545 case 2: 546 PAS_OP(q); 547 break; 548 case 3: 549 PAS_OP(sh); 550 break; 551 case 6: 552 PAS_OP(uq); 553 break; 554 case 7: 555 PAS_OP(uh); 556 break; 557 #undef gen_pas_helper 558 } 559 } 560 #undef PAS_OP 561 562 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */ 563 #define PAS_OP(pfx) \ 564 switch (op1) { \ 565 case 0: gen_pas_helper(glue(pfx,add8)); break; \ 566 case 1: gen_pas_helper(glue(pfx,add16)); break; \ 567 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \ 568 case 4: gen_pas_helper(glue(pfx,sub8)); break; \ 569 case 5: gen_pas_helper(glue(pfx,sub16)); break; \ 570 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ 571 } 572 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 573 { 574 TCGv_ptr tmp; 575 576 switch (op2) { 577 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 578 case 0: 579 tmp = tcg_temp_new_ptr(); 580 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 581 PAS_OP(s) 582 tcg_temp_free_ptr(tmp); 583 break; 584 case 4: 585 tmp = tcg_temp_new_ptr(); 586 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 587 PAS_OP(u) 588 tcg_temp_free_ptr(tmp); 589 break; 590 #undef gen_pas_helper 591 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 592 case 1: 593 PAS_OP(q); 594 break; 595 case 2: 596 PAS_OP(sh); 597 break; 598 case 5: 599 PAS_OP(uq); 600 break; 601 case 6: 602 PAS_OP(uh); 603 break; 604 #undef gen_pas_helper 605 } 606 } 607 #undef PAS_OP 608 609 static void gen_test_cc(int cc, int label) 610 { 611 TCGv tmp; 612 TCGv tmp2; 613 int inv; 614 615 switch (cc) { 616 case 0: /* eq: Z */ 617 tmp = load_cpu_field(ZF); 618 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 619 break; 620 case 1: /* ne: !Z */ 621 tmp = load_cpu_field(ZF); 622 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 623 break; 624 case 2: /* cs: C */ 625 tmp = load_cpu_field(CF); 626 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 627 break; 628 case 3: /* cc: !C */ 629 tmp = load_cpu_field(CF); 630 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 631 break; 632 case 4: /* mi: N */ 633 tmp = load_cpu_field(NF); 634 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 635 break; 636 case 5: /* pl: !N */ 637 tmp = load_cpu_field(NF); 638 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 639 break; 640 case 6: /* vs: V */ 641 tmp = load_cpu_field(VF); 642 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 643 break; 644 case 7: /* vc: !V */ 645 tmp = load_cpu_field(VF); 646 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 647 break; 648 case 8: /* hi: C && !Z */ 649 inv = gen_new_label(); 650 tmp = load_cpu_field(CF); 651 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 652 tcg_temp_free_i32(tmp); 653 tmp = load_cpu_field(ZF); 654 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 655 gen_set_label(inv); 656 break; 657 case 9: /* ls: !C || Z */ 658 tmp = load_cpu_field(CF); 659 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 660 tcg_temp_free_i32(tmp); 661 tmp = load_cpu_field(ZF); 662 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 663 break; 664 case 10: /* ge: N == V -> N ^ V == 0 */ 665 tmp = load_cpu_field(VF); 666 tmp2 = load_cpu_field(NF); 667 tcg_gen_xor_i32(tmp, tmp, tmp2); 668 tcg_temp_free_i32(tmp2); 669 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 670 break; 671 case 11: /* lt: N != V -> N ^ V != 0 */ 672 tmp = load_cpu_field(VF); 673 tmp2 = load_cpu_field(NF); 674 tcg_gen_xor_i32(tmp, tmp, tmp2); 675 tcg_temp_free_i32(tmp2); 676 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 677 break; 678 case 12: /* gt: !Z && N == V */ 679 inv = gen_new_label(); 680 tmp = load_cpu_field(ZF); 681 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 682 tcg_temp_free_i32(tmp); 683 tmp = load_cpu_field(VF); 684 tmp2 = load_cpu_field(NF); 685 tcg_gen_xor_i32(tmp, tmp, tmp2); 686 tcg_temp_free_i32(tmp2); 687 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 688 gen_set_label(inv); 689 break; 690 case 13: /* le: Z || N != V */ 691 tmp = load_cpu_field(ZF); 692 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 693 tcg_temp_free_i32(tmp); 694 tmp = load_cpu_field(VF); 695 tmp2 = load_cpu_field(NF); 696 tcg_gen_xor_i32(tmp, tmp, tmp2); 697 tcg_temp_free_i32(tmp2); 698 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 699 break; 700 default: 701 fprintf(stderr, "Bad condition code 0x%x\n", cc); 702 abort(); 703 } 704 tcg_temp_free_i32(tmp); 705 } 706 707 static const uint8_t table_logic_cc[16] = { 708 1, /* and */ 709 1, /* xor */ 710 0, /* sub */ 711 0, /* rsb */ 712 0, /* add */ 713 0, /* adc */ 714 0, /* sbc */ 715 0, /* rsc */ 716 1, /* andl */ 717 1, /* xorl */ 718 0, /* cmp */ 719 0, /* cmn */ 720 1, /* orr */ 721 1, /* mov */ 722 1, /* bic */ 723 1, /* mvn */ 724 }; 725 726 /* Set PC and Thumb state from an immediate address. */ 727 static inline void gen_bx_im(DisasContext *s, uint32_t addr) 728 { 729 TCGv tmp; 730 731 s->is_jmp = DISAS_UPDATE; 732 if (s->thumb != (addr & 1)) { 733 tmp = tcg_temp_new_i32(); 734 tcg_gen_movi_i32(tmp, addr & 1); 735 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); 736 tcg_temp_free_i32(tmp); 737 } 738 tcg_gen_movi_i32(cpu_R[15], addr & ~1); 739 } 740 741 /* Set PC and Thumb state from var. var is marked as dead. */ 742 static inline void gen_bx(DisasContext *s, TCGv var) 743 { 744 s->is_jmp = DISAS_UPDATE; 745 tcg_gen_andi_i32(cpu_R[15], var, ~1); 746 tcg_gen_andi_i32(var, var, 1); 747 store_cpu_field(var, thumb); 748 } 749 750 /* Variant of store_reg which uses branch&exchange logic when storing 751 to r15 in ARM architecture v7 and above. The source must be a temporary 752 and will be marked as dead. */ 753 static inline void store_reg_bx(CPUState *env, DisasContext *s, 754 int reg, TCGv var) 755 { 756 if (reg == 15 && ENABLE_ARCH_7) { 757 gen_bx(s, var); 758 } else { 759 store_reg(s, reg, var); 760 } 761 } 762 763 /* Variant of store_reg which uses branch&exchange logic when storing 764 * to r15 in ARM architecture v5T and above. This is used for storing 765 * the results of a LDR/LDM/POP into r15, and corresponds to the cases 766 * in the ARM ARM which use the LoadWritePC() pseudocode function. */ 767 static inline void store_reg_from_load(CPUState *env, DisasContext *s, 768 int reg, TCGv var) 769 { 770 if (reg == 15 && ENABLE_ARCH_5) { 771 gen_bx(s, var); 772 } else { 773 store_reg(s, reg, var); 774 } 775 } 776 777 static inline void gen_smc(CPUState *env, DisasContext *s) 778 { 779 tcg_gen_movi_i32(cpu_R[15], s->pc); 780 s->is_jmp = DISAS_SMC; 781 } 782 783 static inline TCGv gen_ld8s(TCGv addr, int index) 784 { 785 TCGv tmp = tcg_temp_new_i32(); 786 tcg_gen_qemu_ld8s(tmp, addr, index); 787 return tmp; 788 } 789 static inline TCGv gen_ld8u(TCGv addr, int index) 790 { 791 TCGv tmp = tcg_temp_new_i32(); 792 tcg_gen_qemu_ld8u(tmp, addr, index); 793 return tmp; 794 } 795 static inline TCGv gen_ld16s(TCGv addr, int index) 796 { 797 TCGv tmp = tcg_temp_new_i32(); 798 tcg_gen_qemu_ld16s(tmp, addr, index); 799 return tmp; 800 } 801 static inline TCGv gen_ld16u(TCGv addr, int index) 802 { 803 TCGv tmp = tcg_temp_new_i32(); 804 tcg_gen_qemu_ld16u(tmp, addr, index); 805 return tmp; 806 } 807 static inline TCGv gen_ld32(TCGv addr, int index) 808 { 809 TCGv tmp = tcg_temp_new_i32(); 810 tcg_gen_qemu_ld32u(tmp, addr, index); 811 return tmp; 812 } 813 static inline TCGv_i64 gen_ld64(TCGv addr, int index) 814 { 815 TCGv_i64 tmp = tcg_temp_new_i64(); 816 tcg_gen_qemu_ld64(tmp, addr, index); 817 return tmp; 818 } 819 static inline void gen_st8(TCGv val, TCGv addr, int index) 820 { 821 tcg_gen_qemu_st8(val, addr, index); 822 tcg_temp_free_i32(val); 823 } 824 static inline void gen_st16(TCGv val, TCGv addr, int index) 825 { 826 tcg_gen_qemu_st16(val, addr, index); 827 tcg_temp_free_i32(val); 828 } 829 static inline void gen_st32(TCGv val, TCGv addr, int index) 830 { 831 tcg_gen_qemu_st32(val, addr, index); 832 tcg_temp_free_i32(val); 833 } 834 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index) 835 { 836 tcg_gen_qemu_st64(val, addr, index); 837 tcg_temp_free_i64(val); 838 } 839 840 static inline void gen_set_pc_im(uint32_t val) 841 { 842 tcg_gen_movi_i32(cpu_R[15], val); 843 } 844 845 /* Force a TB lookup after an instruction that changes the CPU state. */ 846 static inline void gen_lookup_tb(DisasContext *s) 847 { 848 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1); 849 s->is_jmp = DISAS_UPDATE; 850 } 851 852 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, 853 TCGv var) 854 { 855 int val, rm, shift, shiftop; 856 TCGv offset; 857 858 if (!(insn & (1 << 25))) { 859 /* immediate */ 860 val = insn & 0xfff; 861 if (!(insn & (1 << 23))) 862 val = -val; 863 if (val != 0) 864 tcg_gen_addi_i32(var, var, val); 865 } else { 866 /* shift/register */ 867 rm = (insn) & 0xf; 868 shift = (insn >> 7) & 0x1f; 869 shiftop = (insn >> 5) & 3; 870 offset = load_reg(s, rm); 871 gen_arm_shift_im(offset, shiftop, shift, 0); 872 if (!(insn & (1 << 23))) 873 tcg_gen_sub_i32(var, var, offset); 874 else 875 tcg_gen_add_i32(var, var, offset); 876 tcg_temp_free_i32(offset); 877 } 878 } 879 880 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, 881 int extra, TCGv var) 882 { 883 int val, rm; 884 TCGv offset; 885 886 if (insn & (1 << 22)) { 887 /* immediate */ 888 val = (insn & 0xf) | ((insn >> 4) & 0xf0); 889 if (!(insn & (1 << 23))) 890 val = -val; 891 val += extra; 892 if (val != 0) 893 tcg_gen_addi_i32(var, var, val); 894 } else { 895 /* register */ 896 if (extra) 897 tcg_gen_addi_i32(var, var, extra); 898 rm = (insn) & 0xf; 899 offset = load_reg(s, rm); 900 if (!(insn & (1 << 23))) 901 tcg_gen_sub_i32(var, var, offset); 902 else 903 tcg_gen_add_i32(var, var, offset); 904 tcg_temp_free_i32(offset); 905 } 906 } 907 908 #define VFP_OP2(name) \ 909 static inline void gen_vfp_##name(int dp) \ 910 { \ 911 if (dp) \ 912 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \ 913 else \ 914 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \ 915 } 916 917 VFP_OP2(add) 918 VFP_OP2(sub) 919 VFP_OP2(mul) 920 VFP_OP2(div) 921 922 #undef VFP_OP2 923 924 static inline void gen_vfp_F1_mul(int dp) 925 { 926 /* Like gen_vfp_mul() but put result in F1 */ 927 if (dp) { 928 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env); 929 } else { 930 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env); 931 } 932 } 933 934 static inline void gen_vfp_F1_neg(int dp) 935 { 936 /* Like gen_vfp_neg() but put result in F1 */ 937 if (dp) { 938 gen_helper_vfp_negd(cpu_F1d, cpu_F0d); 939 } else { 940 gen_helper_vfp_negs(cpu_F1s, cpu_F0s); 941 } 942 } 943 944 static inline void gen_vfp_abs(int dp) 945 { 946 if (dp) 947 gen_helper_vfp_absd(cpu_F0d, cpu_F0d); 948 else 949 gen_helper_vfp_abss(cpu_F0s, cpu_F0s); 950 } 951 952 static inline void gen_vfp_neg(int dp) 953 { 954 if (dp) 955 gen_helper_vfp_negd(cpu_F0d, cpu_F0d); 956 else 957 gen_helper_vfp_negs(cpu_F0s, cpu_F0s); 958 } 959 960 static inline void gen_vfp_sqrt(int dp) 961 { 962 if (dp) 963 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env); 964 else 965 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env); 966 } 967 968 static inline void gen_vfp_cmp(int dp) 969 { 970 if (dp) 971 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env); 972 else 973 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env); 974 } 975 976 static inline void gen_vfp_cmpe(int dp) 977 { 978 if (dp) 979 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env); 980 else 981 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env); 982 } 983 984 static inline void gen_vfp_F1_ld0(int dp) 985 { 986 if (dp) 987 tcg_gen_movi_i64(cpu_F1d, 0); 988 else 989 tcg_gen_movi_i32(cpu_F1s, 0); 990 } 991 992 #define VFP_GEN_ITOF(name) \ 993 static inline void gen_vfp_##name(int dp, int neon) \ 994 { \ 995 TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 996 int offset; \ 997 if (neon) { \ 998 offset = offsetof(CPUState, vfp.standard_fp_status); \ 999 } else { \ 1000 offset = offsetof(CPUState, vfp.fp_status); \ 1001 } \ 1002 tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 1003 if (dp) { \ 1004 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \ 1005 } else { \ 1006 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 1007 } \ 1008 tcg_temp_free_ptr(statusptr); \ 1009 } 1010 1011 VFP_GEN_ITOF(uito) 1012 VFP_GEN_ITOF(sito) 1013 #undef VFP_GEN_ITOF 1014 1015 #define VFP_GEN_FTOI(name) \ 1016 static inline void gen_vfp_##name(int dp, int neon) \ 1017 { \ 1018 TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 1019 int offset; \ 1020 if (neon) { \ 1021 offset = offsetof(CPUState, vfp.standard_fp_status); \ 1022 } else { \ 1023 offset = offsetof(CPUState, vfp.fp_status); \ 1024 } \ 1025 tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 1026 if (dp) { \ 1027 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \ 1028 } else { \ 1029 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 1030 } \ 1031 tcg_temp_free_ptr(statusptr); \ 1032 } 1033 1034 VFP_GEN_FTOI(toui) 1035 VFP_GEN_FTOI(touiz) 1036 VFP_GEN_FTOI(tosi) 1037 VFP_GEN_FTOI(tosiz) 1038 #undef VFP_GEN_FTOI 1039 1040 #define VFP_GEN_FIX(name) \ 1041 static inline void gen_vfp_##name(int dp, int shift, int neon) \ 1042 { \ 1043 TCGv tmp_shift = tcg_const_i32(shift); \ 1044 TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 1045 int offset; \ 1046 if (neon) { \ 1047 offset = offsetof(CPUState, vfp.standard_fp_status); \ 1048 } else { \ 1049 offset = offsetof(CPUState, vfp.fp_status); \ 1050 } \ 1051 tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 1052 if (dp) { \ 1053 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ 1054 } else { \ 1055 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \ 1056 } \ 1057 tcg_temp_free_i32(tmp_shift); \ 1058 tcg_temp_free_ptr(statusptr); \ 1059 } 1060 VFP_GEN_FIX(tosh) 1061 VFP_GEN_FIX(tosl) 1062 VFP_GEN_FIX(touh) 1063 VFP_GEN_FIX(toul) 1064 VFP_GEN_FIX(shto) 1065 VFP_GEN_FIX(slto) 1066 VFP_GEN_FIX(uhto) 1067 VFP_GEN_FIX(ulto) 1068 #undef VFP_GEN_FIX 1069 1070 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) 1071 { 1072 if (dp) 1073 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s)); 1074 else 1075 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s)); 1076 } 1077 1078 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr) 1079 { 1080 if (dp) 1081 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s)); 1082 else 1083 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s)); 1084 } 1085 1086 static inline long 1087 vfp_reg_offset (int dp, int reg) 1088 { 1089 if (dp) 1090 return offsetof(CPUARMState, vfp.regs[reg]); 1091 else if (reg & 1) { 1092 return offsetof(CPUARMState, vfp.regs[reg >> 1]) 1093 + offsetof(CPU_DoubleU, l.upper); 1094 } else { 1095 return offsetof(CPUARMState, vfp.regs[reg >> 1]) 1096 + offsetof(CPU_DoubleU, l.lower); 1097 } 1098 } 1099 1100 /* Return the offset of a 32-bit piece of a NEON register. 1101 zero is the least significant end of the register. */ 1102 static inline long 1103 neon_reg_offset (int reg, int n) 1104 { 1105 int sreg; 1106 sreg = reg * 2 + n; 1107 return vfp_reg_offset(0, sreg); 1108 } 1109 1110 static TCGv neon_load_reg(int reg, int pass) 1111 { 1112 TCGv tmp = tcg_temp_new_i32(); 1113 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); 1114 return tmp; 1115 } 1116 1117 static void neon_store_reg(int reg, int pass, TCGv var) 1118 { 1119 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); 1120 tcg_temp_free_i32(var); 1121 } 1122 1123 static inline void neon_load_reg64(TCGv_i64 var, int reg) 1124 { 1125 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); 1126 } 1127 1128 static inline void neon_store_reg64(TCGv_i64 var, int reg) 1129 { 1130 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); 1131 } 1132 1133 #define tcg_gen_ld_f32 tcg_gen_ld_i32 1134 #define tcg_gen_ld_f64 tcg_gen_ld_i64 1135 #define tcg_gen_st_f32 tcg_gen_st_i32 1136 #define tcg_gen_st_f64 tcg_gen_st_i64 1137 1138 static inline void gen_mov_F0_vreg(int dp, int reg) 1139 { 1140 if (dp) 1141 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 1142 else 1143 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 1144 } 1145 1146 static inline void gen_mov_F1_vreg(int dp, int reg) 1147 { 1148 if (dp) 1149 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg)); 1150 else 1151 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg)); 1152 } 1153 1154 static inline void gen_mov_vreg_F0(int dp, int reg) 1155 { 1156 if (dp) 1157 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 1158 else 1159 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 1160 } 1161 1162 #define ARM_CP_RW_BIT (1 << 20) 1163 1164 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg) 1165 { 1166 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg])); 1167 } 1168 1169 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg) 1170 { 1171 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg])); 1172 } 1173 1174 static inline TCGv iwmmxt_load_creg(int reg) 1175 { 1176 TCGv var = tcg_temp_new_i32(); 1177 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); 1178 return var; 1179 } 1180 1181 static inline void iwmmxt_store_creg(int reg, TCGv var) 1182 { 1183 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); 1184 tcg_temp_free_i32(var); 1185 } 1186 1187 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn) 1188 { 1189 iwmmxt_store_reg(cpu_M0, rn); 1190 } 1191 1192 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn) 1193 { 1194 iwmmxt_load_reg(cpu_M0, rn); 1195 } 1196 1197 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn) 1198 { 1199 iwmmxt_load_reg(cpu_V1, rn); 1200 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1); 1201 } 1202 1203 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn) 1204 { 1205 iwmmxt_load_reg(cpu_V1, rn); 1206 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1); 1207 } 1208 1209 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn) 1210 { 1211 iwmmxt_load_reg(cpu_V1, rn); 1212 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1); 1213 } 1214 1215 #define IWMMXT_OP(name) \ 1216 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \ 1217 { \ 1218 iwmmxt_load_reg(cpu_V1, rn); \ 1219 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \ 1220 } 1221 1222 #define IWMMXT_OP_SIZE(name) \ 1223 IWMMXT_OP(name##b) \ 1224 IWMMXT_OP(name##w) \ 1225 IWMMXT_OP(name##l) 1226 1227 #define IWMMXT_OP_1(name) \ 1228 static inline void gen_op_iwmmxt_##name##_M0(void) \ 1229 { \ 1230 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \ 1231 } 1232 1233 IWMMXT_OP(maddsq) 1234 IWMMXT_OP(madduq) 1235 IWMMXT_OP(sadb) 1236 IWMMXT_OP(sadw) 1237 IWMMXT_OP(mulslw) 1238 IWMMXT_OP(mulshw) 1239 IWMMXT_OP(mululw) 1240 IWMMXT_OP(muluhw) 1241 IWMMXT_OP(macsw) 1242 IWMMXT_OP(macuw) 1243 1244 IWMMXT_OP_SIZE(unpackl) 1245 IWMMXT_OP_SIZE(unpackh) 1246 1247 IWMMXT_OP_1(unpacklub) 1248 IWMMXT_OP_1(unpackluw) 1249 IWMMXT_OP_1(unpacklul) 1250 IWMMXT_OP_1(unpackhub) 1251 IWMMXT_OP_1(unpackhuw) 1252 IWMMXT_OP_1(unpackhul) 1253 IWMMXT_OP_1(unpacklsb) 1254 IWMMXT_OP_1(unpacklsw) 1255 IWMMXT_OP_1(unpacklsl) 1256 IWMMXT_OP_1(unpackhsb) 1257 IWMMXT_OP_1(unpackhsw) 1258 IWMMXT_OP_1(unpackhsl) 1259 1260 IWMMXT_OP_SIZE(cmpeq) 1261 IWMMXT_OP_SIZE(cmpgtu) 1262 IWMMXT_OP_SIZE(cmpgts) 1263 1264 IWMMXT_OP_SIZE(mins) 1265 IWMMXT_OP_SIZE(minu) 1266 IWMMXT_OP_SIZE(maxs) 1267 IWMMXT_OP_SIZE(maxu) 1268 1269 IWMMXT_OP_SIZE(subn) 1270 IWMMXT_OP_SIZE(addn) 1271 IWMMXT_OP_SIZE(subu) 1272 IWMMXT_OP_SIZE(addu) 1273 IWMMXT_OP_SIZE(subs) 1274 IWMMXT_OP_SIZE(adds) 1275 1276 IWMMXT_OP(avgb0) 1277 IWMMXT_OP(avgb1) 1278 IWMMXT_OP(avgw0) 1279 IWMMXT_OP(avgw1) 1280 1281 IWMMXT_OP(msadb) 1282 1283 IWMMXT_OP(packuw) 1284 IWMMXT_OP(packul) 1285 IWMMXT_OP(packuq) 1286 IWMMXT_OP(packsw) 1287 IWMMXT_OP(packsl) 1288 IWMMXT_OP(packsq) 1289 1290 static void gen_op_iwmmxt_set_mup(void) 1291 { 1292 TCGv tmp; 1293 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 1294 tcg_gen_ori_i32(tmp, tmp, 2); 1295 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 1296 } 1297 1298 static void gen_op_iwmmxt_set_cup(void) 1299 { 1300 TCGv tmp; 1301 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 1302 tcg_gen_ori_i32(tmp, tmp, 1); 1303 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 1304 } 1305 1306 static void gen_op_iwmmxt_setpsr_nz(void) 1307 { 1308 TCGv tmp = tcg_temp_new_i32(); 1309 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0); 1310 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]); 1311 } 1312 1313 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn) 1314 { 1315 iwmmxt_load_reg(cpu_V1, rn); 1316 tcg_gen_ext32u_i64(cpu_V1, cpu_V1); 1317 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 1318 } 1319 1320 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) 1321 { 1322 int rd; 1323 uint32_t offset; 1324 TCGv tmp; 1325 1326 rd = (insn >> 16) & 0xf; 1327 tmp = load_reg(s, rd); 1328 1329 offset = (insn & 0xff) << ((insn >> 7) & 2); 1330 if (insn & (1 << 24)) { 1331 /* Pre indexed */ 1332 if (insn & (1 << 23)) 1333 tcg_gen_addi_i32(tmp, tmp, offset); 1334 else 1335 tcg_gen_addi_i32(tmp, tmp, -offset); 1336 tcg_gen_mov_i32(dest, tmp); 1337 if (insn & (1 << 21)) 1338 store_reg(s, rd, tmp); 1339 else 1340 tcg_temp_free_i32(tmp); 1341 } else if (insn & (1 << 21)) { 1342 /* Post indexed */ 1343 tcg_gen_mov_i32(dest, tmp); 1344 if (insn & (1 << 23)) 1345 tcg_gen_addi_i32(tmp, tmp, offset); 1346 else 1347 tcg_gen_addi_i32(tmp, tmp, -offset); 1348 store_reg(s, rd, tmp); 1349 } else if (!(insn & (1 << 23))) 1350 return 1; 1351 return 0; 1352 } 1353 1354 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest) 1355 { 1356 int rd = (insn >> 0) & 0xf; 1357 TCGv tmp; 1358 1359 if (insn & (1 << 8)) { 1360 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) { 1361 return 1; 1362 } else { 1363 tmp = iwmmxt_load_creg(rd); 1364 } 1365 } else { 1366 tmp = tcg_temp_new_i32(); 1367 iwmmxt_load_reg(cpu_V0, rd); 1368 tcg_gen_trunc_i64_i32(tmp, cpu_V0); 1369 } 1370 tcg_gen_andi_i32(tmp, tmp, mask); 1371 tcg_gen_mov_i32(dest, tmp); 1372 tcg_temp_free_i32(tmp); 1373 return 0; 1374 } 1375 1376 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred 1377 (ie. an undefined instruction). */ 1378 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) 1379 { 1380 int rd, wrd; 1381 int rdhi, rdlo, rd0, rd1, i; 1382 TCGv addr; 1383 TCGv tmp, tmp2, tmp3; 1384 1385 if ((insn & 0x0e000e00) == 0x0c000000) { 1386 if ((insn & 0x0fe00ff0) == 0x0c400000) { 1387 wrd = insn & 0xf; 1388 rdlo = (insn >> 12) & 0xf; 1389 rdhi = (insn >> 16) & 0xf; 1390 if (insn & ARM_CP_RW_BIT) { /* TMRRC */ 1391 iwmmxt_load_reg(cpu_V0, wrd); 1392 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 1393 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 1394 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 1395 } else { /* TMCRR */ 1396 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 1397 iwmmxt_store_reg(cpu_V0, wrd); 1398 gen_op_iwmmxt_set_mup(); 1399 } 1400 return 0; 1401 } 1402 1403 wrd = (insn >> 12) & 0xf; 1404 addr = tcg_temp_new_i32(); 1405 if (gen_iwmmxt_address(s, insn, addr)) { 1406 tcg_temp_free_i32(addr); 1407 return 1; 1408 } 1409 if (insn & ARM_CP_RW_BIT) { 1410 if ((insn >> 28) == 0xf) { /* WLDRW wCx */ 1411 tmp = tcg_temp_new_i32(); 1412 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); 1413 iwmmxt_store_creg(wrd, tmp); 1414 } else { 1415 i = 1; 1416 if (insn & (1 << 8)) { 1417 if (insn & (1 << 22)) { /* WLDRD */ 1418 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s)); 1419 i = 0; 1420 } else { /* WLDRW wRd */ 1421 tmp = gen_ld32(addr, IS_USER(s)); 1422 } 1423 } else { 1424 if (insn & (1 << 22)) { /* WLDRH */ 1425 tmp = gen_ld16u(addr, IS_USER(s)); 1426 } else { /* WLDRB */ 1427 tmp = gen_ld8u(addr, IS_USER(s)); 1428 } 1429 } 1430 if (i) { 1431 tcg_gen_extu_i32_i64(cpu_M0, tmp); 1432 tcg_temp_free_i32(tmp); 1433 } 1434 gen_op_iwmmxt_movq_wRn_M0(wrd); 1435 } 1436 } else { 1437 if ((insn >> 28) == 0xf) { /* WSTRW wCx */ 1438 tmp = iwmmxt_load_creg(wrd); 1439 gen_st32(tmp, addr, IS_USER(s)); 1440 } else { 1441 gen_op_iwmmxt_movq_M0_wRn(wrd); 1442 tmp = tcg_temp_new_i32(); 1443 if (insn & (1 << 8)) { 1444 if (insn & (1 << 22)) { /* WSTRD */ 1445 tcg_temp_free_i32(tmp); 1446 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s)); 1447 } else { /* WSTRW wRd */ 1448 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1449 gen_st32(tmp, addr, IS_USER(s)); 1450 } 1451 } else { 1452 if (insn & (1 << 22)) { /* WSTRH */ 1453 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1454 gen_st16(tmp, addr, IS_USER(s)); 1455 } else { /* WSTRB */ 1456 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1457 gen_st8(tmp, addr, IS_USER(s)); 1458 } 1459 } 1460 } 1461 } 1462 tcg_temp_free_i32(addr); 1463 return 0; 1464 } 1465 1466 if ((insn & 0x0f000000) != 0x0e000000) 1467 return 1; 1468 1469 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) { 1470 case 0x000: /* WOR */ 1471 wrd = (insn >> 12) & 0xf; 1472 rd0 = (insn >> 0) & 0xf; 1473 rd1 = (insn >> 16) & 0xf; 1474 gen_op_iwmmxt_movq_M0_wRn(rd0); 1475 gen_op_iwmmxt_orq_M0_wRn(rd1); 1476 gen_op_iwmmxt_setpsr_nz(); 1477 gen_op_iwmmxt_movq_wRn_M0(wrd); 1478 gen_op_iwmmxt_set_mup(); 1479 gen_op_iwmmxt_set_cup(); 1480 break; 1481 case 0x011: /* TMCR */ 1482 if (insn & 0xf) 1483 return 1; 1484 rd = (insn >> 12) & 0xf; 1485 wrd = (insn >> 16) & 0xf; 1486 switch (wrd) { 1487 case ARM_IWMMXT_wCID: 1488 case ARM_IWMMXT_wCASF: 1489 break; 1490 case ARM_IWMMXT_wCon: 1491 gen_op_iwmmxt_set_cup(); 1492 /* Fall through. */ 1493 case ARM_IWMMXT_wCSSF: 1494 tmp = iwmmxt_load_creg(wrd); 1495 tmp2 = load_reg(s, rd); 1496 tcg_gen_andc_i32(tmp, tmp, tmp2); 1497 tcg_temp_free_i32(tmp2); 1498 iwmmxt_store_creg(wrd, tmp); 1499 break; 1500 case ARM_IWMMXT_wCGR0: 1501 case ARM_IWMMXT_wCGR1: 1502 case ARM_IWMMXT_wCGR2: 1503 case ARM_IWMMXT_wCGR3: 1504 gen_op_iwmmxt_set_cup(); 1505 tmp = load_reg(s, rd); 1506 iwmmxt_store_creg(wrd, tmp); 1507 break; 1508 default: 1509 return 1; 1510 } 1511 break; 1512 case 0x100: /* WXOR */ 1513 wrd = (insn >> 12) & 0xf; 1514 rd0 = (insn >> 0) & 0xf; 1515 rd1 = (insn >> 16) & 0xf; 1516 gen_op_iwmmxt_movq_M0_wRn(rd0); 1517 gen_op_iwmmxt_xorq_M0_wRn(rd1); 1518 gen_op_iwmmxt_setpsr_nz(); 1519 gen_op_iwmmxt_movq_wRn_M0(wrd); 1520 gen_op_iwmmxt_set_mup(); 1521 gen_op_iwmmxt_set_cup(); 1522 break; 1523 case 0x111: /* TMRC */ 1524 if (insn & 0xf) 1525 return 1; 1526 rd = (insn >> 12) & 0xf; 1527 wrd = (insn >> 16) & 0xf; 1528 tmp = iwmmxt_load_creg(wrd); 1529 store_reg(s, rd, tmp); 1530 break; 1531 case 0x300: /* WANDN */ 1532 wrd = (insn >> 12) & 0xf; 1533 rd0 = (insn >> 0) & 0xf; 1534 rd1 = (insn >> 16) & 0xf; 1535 gen_op_iwmmxt_movq_M0_wRn(rd0); 1536 tcg_gen_neg_i64(cpu_M0, cpu_M0); 1537 gen_op_iwmmxt_andq_M0_wRn(rd1); 1538 gen_op_iwmmxt_setpsr_nz(); 1539 gen_op_iwmmxt_movq_wRn_M0(wrd); 1540 gen_op_iwmmxt_set_mup(); 1541 gen_op_iwmmxt_set_cup(); 1542 break; 1543 case 0x200: /* WAND */ 1544 wrd = (insn >> 12) & 0xf; 1545 rd0 = (insn >> 0) & 0xf; 1546 rd1 = (insn >> 16) & 0xf; 1547 gen_op_iwmmxt_movq_M0_wRn(rd0); 1548 gen_op_iwmmxt_andq_M0_wRn(rd1); 1549 gen_op_iwmmxt_setpsr_nz(); 1550 gen_op_iwmmxt_movq_wRn_M0(wrd); 1551 gen_op_iwmmxt_set_mup(); 1552 gen_op_iwmmxt_set_cup(); 1553 break; 1554 case 0x810: case 0xa10: /* WMADD */ 1555 wrd = (insn >> 12) & 0xf; 1556 rd0 = (insn >> 0) & 0xf; 1557 rd1 = (insn >> 16) & 0xf; 1558 gen_op_iwmmxt_movq_M0_wRn(rd0); 1559 if (insn & (1 << 21)) 1560 gen_op_iwmmxt_maddsq_M0_wRn(rd1); 1561 else 1562 gen_op_iwmmxt_madduq_M0_wRn(rd1); 1563 gen_op_iwmmxt_movq_wRn_M0(wrd); 1564 gen_op_iwmmxt_set_mup(); 1565 break; 1566 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */ 1567 wrd = (insn >> 12) & 0xf; 1568 rd0 = (insn >> 16) & 0xf; 1569 rd1 = (insn >> 0) & 0xf; 1570 gen_op_iwmmxt_movq_M0_wRn(rd0); 1571 switch ((insn >> 22) & 3) { 1572 case 0: 1573 gen_op_iwmmxt_unpacklb_M0_wRn(rd1); 1574 break; 1575 case 1: 1576 gen_op_iwmmxt_unpacklw_M0_wRn(rd1); 1577 break; 1578 case 2: 1579 gen_op_iwmmxt_unpackll_M0_wRn(rd1); 1580 break; 1581 case 3: 1582 return 1; 1583 } 1584 gen_op_iwmmxt_movq_wRn_M0(wrd); 1585 gen_op_iwmmxt_set_mup(); 1586 gen_op_iwmmxt_set_cup(); 1587 break; 1588 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */ 1589 wrd = (insn >> 12) & 0xf; 1590 rd0 = (insn >> 16) & 0xf; 1591 rd1 = (insn >> 0) & 0xf; 1592 gen_op_iwmmxt_movq_M0_wRn(rd0); 1593 switch ((insn >> 22) & 3) { 1594 case 0: 1595 gen_op_iwmmxt_unpackhb_M0_wRn(rd1); 1596 break; 1597 case 1: 1598 gen_op_iwmmxt_unpackhw_M0_wRn(rd1); 1599 break; 1600 case 2: 1601 gen_op_iwmmxt_unpackhl_M0_wRn(rd1); 1602 break; 1603 case 3: 1604 return 1; 1605 } 1606 gen_op_iwmmxt_movq_wRn_M0(wrd); 1607 gen_op_iwmmxt_set_mup(); 1608 gen_op_iwmmxt_set_cup(); 1609 break; 1610 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */ 1611 wrd = (insn >> 12) & 0xf; 1612 rd0 = (insn >> 16) & 0xf; 1613 rd1 = (insn >> 0) & 0xf; 1614 gen_op_iwmmxt_movq_M0_wRn(rd0); 1615 if (insn & (1 << 22)) 1616 gen_op_iwmmxt_sadw_M0_wRn(rd1); 1617 else 1618 gen_op_iwmmxt_sadb_M0_wRn(rd1); 1619 if (!(insn & (1 << 20))) 1620 gen_op_iwmmxt_addl_M0_wRn(wrd); 1621 gen_op_iwmmxt_movq_wRn_M0(wrd); 1622 gen_op_iwmmxt_set_mup(); 1623 break; 1624 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */ 1625 wrd = (insn >> 12) & 0xf; 1626 rd0 = (insn >> 16) & 0xf; 1627 rd1 = (insn >> 0) & 0xf; 1628 gen_op_iwmmxt_movq_M0_wRn(rd0); 1629 if (insn & (1 << 21)) { 1630 if (insn & (1 << 20)) 1631 gen_op_iwmmxt_mulshw_M0_wRn(rd1); 1632 else 1633 gen_op_iwmmxt_mulslw_M0_wRn(rd1); 1634 } else { 1635 if (insn & (1 << 20)) 1636 gen_op_iwmmxt_muluhw_M0_wRn(rd1); 1637 else 1638 gen_op_iwmmxt_mululw_M0_wRn(rd1); 1639 } 1640 gen_op_iwmmxt_movq_wRn_M0(wrd); 1641 gen_op_iwmmxt_set_mup(); 1642 break; 1643 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */ 1644 wrd = (insn >> 12) & 0xf; 1645 rd0 = (insn >> 16) & 0xf; 1646 rd1 = (insn >> 0) & 0xf; 1647 gen_op_iwmmxt_movq_M0_wRn(rd0); 1648 if (insn & (1 << 21)) 1649 gen_op_iwmmxt_macsw_M0_wRn(rd1); 1650 else 1651 gen_op_iwmmxt_macuw_M0_wRn(rd1); 1652 if (!(insn & (1 << 20))) { 1653 iwmmxt_load_reg(cpu_V1, wrd); 1654 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 1655 } 1656 gen_op_iwmmxt_movq_wRn_M0(wrd); 1657 gen_op_iwmmxt_set_mup(); 1658 break; 1659 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */ 1660 wrd = (insn >> 12) & 0xf; 1661 rd0 = (insn >> 16) & 0xf; 1662 rd1 = (insn >> 0) & 0xf; 1663 gen_op_iwmmxt_movq_M0_wRn(rd0); 1664 switch ((insn >> 22) & 3) { 1665 case 0: 1666 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1); 1667 break; 1668 case 1: 1669 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1); 1670 break; 1671 case 2: 1672 gen_op_iwmmxt_cmpeql_M0_wRn(rd1); 1673 break; 1674 case 3: 1675 return 1; 1676 } 1677 gen_op_iwmmxt_movq_wRn_M0(wrd); 1678 gen_op_iwmmxt_set_mup(); 1679 gen_op_iwmmxt_set_cup(); 1680 break; 1681 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */ 1682 wrd = (insn >> 12) & 0xf; 1683 rd0 = (insn >> 16) & 0xf; 1684 rd1 = (insn >> 0) & 0xf; 1685 gen_op_iwmmxt_movq_M0_wRn(rd0); 1686 if (insn & (1 << 22)) { 1687 if (insn & (1 << 20)) 1688 gen_op_iwmmxt_avgw1_M0_wRn(rd1); 1689 else 1690 gen_op_iwmmxt_avgw0_M0_wRn(rd1); 1691 } else { 1692 if (insn & (1 << 20)) 1693 gen_op_iwmmxt_avgb1_M0_wRn(rd1); 1694 else 1695 gen_op_iwmmxt_avgb0_M0_wRn(rd1); 1696 } 1697 gen_op_iwmmxt_movq_wRn_M0(wrd); 1698 gen_op_iwmmxt_set_mup(); 1699 gen_op_iwmmxt_set_cup(); 1700 break; 1701 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */ 1702 wrd = (insn >> 12) & 0xf; 1703 rd0 = (insn >> 16) & 0xf; 1704 rd1 = (insn >> 0) & 0xf; 1705 gen_op_iwmmxt_movq_M0_wRn(rd0); 1706 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3)); 1707 tcg_gen_andi_i32(tmp, tmp, 7); 1708 iwmmxt_load_reg(cpu_V1, rd1); 1709 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 1710 tcg_temp_free_i32(tmp); 1711 gen_op_iwmmxt_movq_wRn_M0(wrd); 1712 gen_op_iwmmxt_set_mup(); 1713 break; 1714 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */ 1715 if (((insn >> 6) & 3) == 3) 1716 return 1; 1717 rd = (insn >> 12) & 0xf; 1718 wrd = (insn >> 16) & 0xf; 1719 tmp = load_reg(s, rd); 1720 gen_op_iwmmxt_movq_M0_wRn(wrd); 1721 switch ((insn >> 6) & 3) { 1722 case 0: 1723 tmp2 = tcg_const_i32(0xff); 1724 tmp3 = tcg_const_i32((insn & 7) << 3); 1725 break; 1726 case 1: 1727 tmp2 = tcg_const_i32(0xffff); 1728 tmp3 = tcg_const_i32((insn & 3) << 4); 1729 break; 1730 case 2: 1731 tmp2 = tcg_const_i32(0xffffffff); 1732 tmp3 = tcg_const_i32((insn & 1) << 5); 1733 break; 1734 default: 1735 TCGV_UNUSED(tmp2); 1736 TCGV_UNUSED(tmp3); 1737 } 1738 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3); 1739 tcg_temp_free(tmp3); 1740 tcg_temp_free(tmp2); 1741 tcg_temp_free_i32(tmp); 1742 gen_op_iwmmxt_movq_wRn_M0(wrd); 1743 gen_op_iwmmxt_set_mup(); 1744 break; 1745 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */ 1746 rd = (insn >> 12) & 0xf; 1747 wrd = (insn >> 16) & 0xf; 1748 if (rd == 15 || ((insn >> 22) & 3) == 3) 1749 return 1; 1750 gen_op_iwmmxt_movq_M0_wRn(wrd); 1751 tmp = tcg_temp_new_i32(); 1752 switch ((insn >> 22) & 3) { 1753 case 0: 1754 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3); 1755 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1756 if (insn & 8) { 1757 tcg_gen_ext8s_i32(tmp, tmp); 1758 } else { 1759 tcg_gen_andi_i32(tmp, tmp, 0xff); 1760 } 1761 break; 1762 case 1: 1763 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4); 1764 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1765 if (insn & 8) { 1766 tcg_gen_ext16s_i32(tmp, tmp); 1767 } else { 1768 tcg_gen_andi_i32(tmp, tmp, 0xffff); 1769 } 1770 break; 1771 case 2: 1772 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5); 1773 tcg_gen_trunc_i64_i32(tmp, cpu_M0); 1774 break; 1775 } 1776 store_reg(s, rd, tmp); 1777 break; 1778 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */ 1779 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3) 1780 return 1; 1781 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 1782 switch ((insn >> 22) & 3) { 1783 case 0: 1784 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0); 1785 break; 1786 case 1: 1787 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4); 1788 break; 1789 case 2: 1790 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12); 1791 break; 1792 } 1793 tcg_gen_shli_i32(tmp, tmp, 28); 1794 gen_set_nzcv(tmp); 1795 tcg_temp_free_i32(tmp); 1796 break; 1797 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */ 1798 if (((insn >> 6) & 3) == 3) 1799 return 1; 1800 rd = (insn >> 12) & 0xf; 1801 wrd = (insn >> 16) & 0xf; 1802 tmp = load_reg(s, rd); 1803 switch ((insn >> 6) & 3) { 1804 case 0: 1805 gen_helper_iwmmxt_bcstb(cpu_M0, tmp); 1806 break; 1807 case 1: 1808 gen_helper_iwmmxt_bcstw(cpu_M0, tmp); 1809 break; 1810 case 2: 1811 gen_helper_iwmmxt_bcstl(cpu_M0, tmp); 1812 break; 1813 } 1814 tcg_temp_free_i32(tmp); 1815 gen_op_iwmmxt_movq_wRn_M0(wrd); 1816 gen_op_iwmmxt_set_mup(); 1817 break; 1818 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */ 1819 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 1820 return 1; 1821 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 1822 tmp2 = tcg_temp_new_i32(); 1823 tcg_gen_mov_i32(tmp2, tmp); 1824 switch ((insn >> 22) & 3) { 1825 case 0: 1826 for (i = 0; i < 7; i ++) { 1827 tcg_gen_shli_i32(tmp2, tmp2, 4); 1828 tcg_gen_and_i32(tmp, tmp, tmp2); 1829 } 1830 break; 1831 case 1: 1832 for (i = 0; i < 3; i ++) { 1833 tcg_gen_shli_i32(tmp2, tmp2, 8); 1834 tcg_gen_and_i32(tmp, tmp, tmp2); 1835 } 1836 break; 1837 case 2: 1838 tcg_gen_shli_i32(tmp2, tmp2, 16); 1839 tcg_gen_and_i32(tmp, tmp, tmp2); 1840 break; 1841 } 1842 gen_set_nzcv(tmp); 1843 tcg_temp_free_i32(tmp2); 1844 tcg_temp_free_i32(tmp); 1845 break; 1846 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */ 1847 wrd = (insn >> 12) & 0xf; 1848 rd0 = (insn >> 16) & 0xf; 1849 gen_op_iwmmxt_movq_M0_wRn(rd0); 1850 switch ((insn >> 22) & 3) { 1851 case 0: 1852 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0); 1853 break; 1854 case 1: 1855 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0); 1856 break; 1857 case 2: 1858 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0); 1859 break; 1860 case 3: 1861 return 1; 1862 } 1863 gen_op_iwmmxt_movq_wRn_M0(wrd); 1864 gen_op_iwmmxt_set_mup(); 1865 break; 1866 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */ 1867 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 1868 return 1; 1869 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 1870 tmp2 = tcg_temp_new_i32(); 1871 tcg_gen_mov_i32(tmp2, tmp); 1872 switch ((insn >> 22) & 3) { 1873 case 0: 1874 for (i = 0; i < 7; i ++) { 1875 tcg_gen_shli_i32(tmp2, tmp2, 4); 1876 tcg_gen_or_i32(tmp, tmp, tmp2); 1877 } 1878 break; 1879 case 1: 1880 for (i = 0; i < 3; i ++) { 1881 tcg_gen_shli_i32(tmp2, tmp2, 8); 1882 tcg_gen_or_i32(tmp, tmp, tmp2); 1883 } 1884 break; 1885 case 2: 1886 tcg_gen_shli_i32(tmp2, tmp2, 16); 1887 tcg_gen_or_i32(tmp, tmp, tmp2); 1888 break; 1889 } 1890 gen_set_nzcv(tmp); 1891 tcg_temp_free_i32(tmp2); 1892 tcg_temp_free_i32(tmp); 1893 break; 1894 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */ 1895 rd = (insn >> 12) & 0xf; 1896 rd0 = (insn >> 16) & 0xf; 1897 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3) 1898 return 1; 1899 gen_op_iwmmxt_movq_M0_wRn(rd0); 1900 tmp = tcg_temp_new_i32(); 1901 switch ((insn >> 22) & 3) { 1902 case 0: 1903 gen_helper_iwmmxt_msbb(tmp, cpu_M0); 1904 break; 1905 case 1: 1906 gen_helper_iwmmxt_msbw(tmp, cpu_M0); 1907 break; 1908 case 2: 1909 gen_helper_iwmmxt_msbl(tmp, cpu_M0); 1910 break; 1911 } 1912 store_reg(s, rd, tmp); 1913 break; 1914 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */ 1915 case 0x906: case 0xb06: case 0xd06: case 0xf06: 1916 wrd = (insn >> 12) & 0xf; 1917 rd0 = (insn >> 16) & 0xf; 1918 rd1 = (insn >> 0) & 0xf; 1919 gen_op_iwmmxt_movq_M0_wRn(rd0); 1920 switch ((insn >> 22) & 3) { 1921 case 0: 1922 if (insn & (1 << 21)) 1923 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1); 1924 else 1925 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1); 1926 break; 1927 case 1: 1928 if (insn & (1 << 21)) 1929 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1); 1930 else 1931 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1); 1932 break; 1933 case 2: 1934 if (insn & (1 << 21)) 1935 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1); 1936 else 1937 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1); 1938 break; 1939 case 3: 1940 return 1; 1941 } 1942 gen_op_iwmmxt_movq_wRn_M0(wrd); 1943 gen_op_iwmmxt_set_mup(); 1944 gen_op_iwmmxt_set_cup(); 1945 break; 1946 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */ 1947 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e: 1948 wrd = (insn >> 12) & 0xf; 1949 rd0 = (insn >> 16) & 0xf; 1950 gen_op_iwmmxt_movq_M0_wRn(rd0); 1951 switch ((insn >> 22) & 3) { 1952 case 0: 1953 if (insn & (1 << 21)) 1954 gen_op_iwmmxt_unpacklsb_M0(); 1955 else 1956 gen_op_iwmmxt_unpacklub_M0(); 1957 break; 1958 case 1: 1959 if (insn & (1 << 21)) 1960 gen_op_iwmmxt_unpacklsw_M0(); 1961 else 1962 gen_op_iwmmxt_unpackluw_M0(); 1963 break; 1964 case 2: 1965 if (insn & (1 << 21)) 1966 gen_op_iwmmxt_unpacklsl_M0(); 1967 else 1968 gen_op_iwmmxt_unpacklul_M0(); 1969 break; 1970 case 3: 1971 return 1; 1972 } 1973 gen_op_iwmmxt_movq_wRn_M0(wrd); 1974 gen_op_iwmmxt_set_mup(); 1975 gen_op_iwmmxt_set_cup(); 1976 break; 1977 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */ 1978 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c: 1979 wrd = (insn >> 12) & 0xf; 1980 rd0 = (insn >> 16) & 0xf; 1981 gen_op_iwmmxt_movq_M0_wRn(rd0); 1982 switch ((insn >> 22) & 3) { 1983 case 0: 1984 if (insn & (1 << 21)) 1985 gen_op_iwmmxt_unpackhsb_M0(); 1986 else 1987 gen_op_iwmmxt_unpackhub_M0(); 1988 break; 1989 case 1: 1990 if (insn & (1 << 21)) 1991 gen_op_iwmmxt_unpackhsw_M0(); 1992 else 1993 gen_op_iwmmxt_unpackhuw_M0(); 1994 break; 1995 case 2: 1996 if (insn & (1 << 21)) 1997 gen_op_iwmmxt_unpackhsl_M0(); 1998 else 1999 gen_op_iwmmxt_unpackhul_M0(); 2000 break; 2001 case 3: 2002 return 1; 2003 } 2004 gen_op_iwmmxt_movq_wRn_M0(wrd); 2005 gen_op_iwmmxt_set_mup(); 2006 gen_op_iwmmxt_set_cup(); 2007 break; 2008 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */ 2009 case 0x214: case 0x614: case 0xa14: case 0xe14: 2010 if (((insn >> 22) & 3) == 0) 2011 return 1; 2012 wrd = (insn >> 12) & 0xf; 2013 rd0 = (insn >> 16) & 0xf; 2014 gen_op_iwmmxt_movq_M0_wRn(rd0); 2015 tmp = tcg_temp_new_i32(); 2016 if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 2017 tcg_temp_free_i32(tmp); 2018 return 1; 2019 } 2020 switch ((insn >> 22) & 3) { 2021 case 1: 2022 gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp); 2023 break; 2024 case 2: 2025 gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp); 2026 break; 2027 case 3: 2028 gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp); 2029 break; 2030 } 2031 tcg_temp_free_i32(tmp); 2032 gen_op_iwmmxt_movq_wRn_M0(wrd); 2033 gen_op_iwmmxt_set_mup(); 2034 gen_op_iwmmxt_set_cup(); 2035 break; 2036 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */ 2037 case 0x014: case 0x414: case 0x814: case 0xc14: 2038 if (((insn >> 22) & 3) == 0) 2039 return 1; 2040 wrd = (insn >> 12) & 0xf; 2041 rd0 = (insn >> 16) & 0xf; 2042 gen_op_iwmmxt_movq_M0_wRn(rd0); 2043 tmp = tcg_temp_new_i32(); 2044 if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 2045 tcg_temp_free_i32(tmp); 2046 return 1; 2047 } 2048 switch ((insn >> 22) & 3) { 2049 case 1: 2050 gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp); 2051 break; 2052 case 2: 2053 gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp); 2054 break; 2055 case 3: 2056 gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp); 2057 break; 2058 } 2059 tcg_temp_free_i32(tmp); 2060 gen_op_iwmmxt_movq_wRn_M0(wrd); 2061 gen_op_iwmmxt_set_mup(); 2062 gen_op_iwmmxt_set_cup(); 2063 break; 2064 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */ 2065 case 0x114: case 0x514: case 0x914: case 0xd14: 2066 if (((insn >> 22) & 3) == 0) 2067 return 1; 2068 wrd = (insn >> 12) & 0xf; 2069 rd0 = (insn >> 16) & 0xf; 2070 gen_op_iwmmxt_movq_M0_wRn(rd0); 2071 tmp = tcg_temp_new_i32(); 2072 if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 2073 tcg_temp_free_i32(tmp); 2074 return 1; 2075 } 2076 switch ((insn >> 22) & 3) { 2077 case 1: 2078 gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp); 2079 break; 2080 case 2: 2081 gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp); 2082 break; 2083 case 3: 2084 gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp); 2085 break; 2086 } 2087 tcg_temp_free_i32(tmp); 2088 gen_op_iwmmxt_movq_wRn_M0(wrd); 2089 gen_op_iwmmxt_set_mup(); 2090 gen_op_iwmmxt_set_cup(); 2091 break; 2092 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */ 2093 case 0x314: case 0x714: case 0xb14: case 0xf14: 2094 if (((insn >> 22) & 3) == 0) 2095 return 1; 2096 wrd = (insn >> 12) & 0xf; 2097 rd0 = (insn >> 16) & 0xf; 2098 gen_op_iwmmxt_movq_M0_wRn(rd0); 2099 tmp = tcg_temp_new_i32(); 2100 switch ((insn >> 22) & 3) { 2101 case 1: 2102 if (gen_iwmmxt_shift(insn, 0xf, tmp)) { 2103 tcg_temp_free_i32(tmp); 2104 return 1; 2105 } 2106 gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp); 2107 break; 2108 case 2: 2109 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) { 2110 tcg_temp_free_i32(tmp); 2111 return 1; 2112 } 2113 gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp); 2114 break; 2115 case 3: 2116 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) { 2117 tcg_temp_free_i32(tmp); 2118 return 1; 2119 } 2120 gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp); 2121 break; 2122 } 2123 tcg_temp_free_i32(tmp); 2124 gen_op_iwmmxt_movq_wRn_M0(wrd); 2125 gen_op_iwmmxt_set_mup(); 2126 gen_op_iwmmxt_set_cup(); 2127 break; 2128 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */ 2129 case 0x916: case 0xb16: case 0xd16: case 0xf16: 2130 wrd = (insn >> 12) & 0xf; 2131 rd0 = (insn >> 16) & 0xf; 2132 rd1 = (insn >> 0) & 0xf; 2133 gen_op_iwmmxt_movq_M0_wRn(rd0); 2134 switch ((insn >> 22) & 3) { 2135 case 0: 2136 if (insn & (1 << 21)) 2137 gen_op_iwmmxt_minsb_M0_wRn(rd1); 2138 else 2139 gen_op_iwmmxt_minub_M0_wRn(rd1); 2140 break; 2141 case 1: 2142 if (insn & (1 << 21)) 2143 gen_op_iwmmxt_minsw_M0_wRn(rd1); 2144 else 2145 gen_op_iwmmxt_minuw_M0_wRn(rd1); 2146 break; 2147 case 2: 2148 if (insn & (1 << 21)) 2149 gen_op_iwmmxt_minsl_M0_wRn(rd1); 2150 else 2151 gen_op_iwmmxt_minul_M0_wRn(rd1); 2152 break; 2153 case 3: 2154 return 1; 2155 } 2156 gen_op_iwmmxt_movq_wRn_M0(wrd); 2157 gen_op_iwmmxt_set_mup(); 2158 break; 2159 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */ 2160 case 0x816: case 0xa16: case 0xc16: case 0xe16: 2161 wrd = (insn >> 12) & 0xf; 2162 rd0 = (insn >> 16) & 0xf; 2163 rd1 = (insn >> 0) & 0xf; 2164 gen_op_iwmmxt_movq_M0_wRn(rd0); 2165 switch ((insn >> 22) & 3) { 2166 case 0: 2167 if (insn & (1 << 21)) 2168 gen_op_iwmmxt_maxsb_M0_wRn(rd1); 2169 else 2170 gen_op_iwmmxt_maxub_M0_wRn(rd1); 2171 break; 2172 case 1: 2173 if (insn & (1 << 21)) 2174 gen_op_iwmmxt_maxsw_M0_wRn(rd1); 2175 else 2176 gen_op_iwmmxt_maxuw_M0_wRn(rd1); 2177 break; 2178 case 2: 2179 if (insn & (1 << 21)) 2180 gen_op_iwmmxt_maxsl_M0_wRn(rd1); 2181 else 2182 gen_op_iwmmxt_maxul_M0_wRn(rd1); 2183 break; 2184 case 3: 2185 return 1; 2186 } 2187 gen_op_iwmmxt_movq_wRn_M0(wrd); 2188 gen_op_iwmmxt_set_mup(); 2189 break; 2190 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */ 2191 case 0x402: case 0x502: case 0x602: case 0x702: 2192 wrd = (insn >> 12) & 0xf; 2193 rd0 = (insn >> 16) & 0xf; 2194 rd1 = (insn >> 0) & 0xf; 2195 gen_op_iwmmxt_movq_M0_wRn(rd0); 2196 tmp = tcg_const_i32((insn >> 20) & 3); 2197 iwmmxt_load_reg(cpu_V1, rd1); 2198 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 2199 tcg_temp_free(tmp); 2200 gen_op_iwmmxt_movq_wRn_M0(wrd); 2201 gen_op_iwmmxt_set_mup(); 2202 break; 2203 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */ 2204 case 0x41a: case 0x51a: case 0x61a: case 0x71a: 2205 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a: 2206 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a: 2207 wrd = (insn >> 12) & 0xf; 2208 rd0 = (insn >> 16) & 0xf; 2209 rd1 = (insn >> 0) & 0xf; 2210 gen_op_iwmmxt_movq_M0_wRn(rd0); 2211 switch ((insn >> 20) & 0xf) { 2212 case 0x0: 2213 gen_op_iwmmxt_subnb_M0_wRn(rd1); 2214 break; 2215 case 0x1: 2216 gen_op_iwmmxt_subub_M0_wRn(rd1); 2217 break; 2218 case 0x3: 2219 gen_op_iwmmxt_subsb_M0_wRn(rd1); 2220 break; 2221 case 0x4: 2222 gen_op_iwmmxt_subnw_M0_wRn(rd1); 2223 break; 2224 case 0x5: 2225 gen_op_iwmmxt_subuw_M0_wRn(rd1); 2226 break; 2227 case 0x7: 2228 gen_op_iwmmxt_subsw_M0_wRn(rd1); 2229 break; 2230 case 0x8: 2231 gen_op_iwmmxt_subnl_M0_wRn(rd1); 2232 break; 2233 case 0x9: 2234 gen_op_iwmmxt_subul_M0_wRn(rd1); 2235 break; 2236 case 0xb: 2237 gen_op_iwmmxt_subsl_M0_wRn(rd1); 2238 break; 2239 default: 2240 return 1; 2241 } 2242 gen_op_iwmmxt_movq_wRn_M0(wrd); 2243 gen_op_iwmmxt_set_mup(); 2244 gen_op_iwmmxt_set_cup(); 2245 break; 2246 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */ 2247 case 0x41e: case 0x51e: case 0x61e: case 0x71e: 2248 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e: 2249 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e: 2250 wrd = (insn >> 12) & 0xf; 2251 rd0 = (insn >> 16) & 0xf; 2252 gen_op_iwmmxt_movq_M0_wRn(rd0); 2253 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f)); 2254 gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp); 2255 tcg_temp_free(tmp); 2256 gen_op_iwmmxt_movq_wRn_M0(wrd); 2257 gen_op_iwmmxt_set_mup(); 2258 gen_op_iwmmxt_set_cup(); 2259 break; 2260 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */ 2261 case 0x418: case 0x518: case 0x618: case 0x718: 2262 case 0x818: case 0x918: case 0xa18: case 0xb18: 2263 case 0xc18: case 0xd18: case 0xe18: case 0xf18: 2264 wrd = (insn >> 12) & 0xf; 2265 rd0 = (insn >> 16) & 0xf; 2266 rd1 = (insn >> 0) & 0xf; 2267 gen_op_iwmmxt_movq_M0_wRn(rd0); 2268 switch ((insn >> 20) & 0xf) { 2269 case 0x0: 2270 gen_op_iwmmxt_addnb_M0_wRn(rd1); 2271 break; 2272 case 0x1: 2273 gen_op_iwmmxt_addub_M0_wRn(rd1); 2274 break; 2275 case 0x3: 2276 gen_op_iwmmxt_addsb_M0_wRn(rd1); 2277 break; 2278 case 0x4: 2279 gen_op_iwmmxt_addnw_M0_wRn(rd1); 2280 break; 2281 case 0x5: 2282 gen_op_iwmmxt_adduw_M0_wRn(rd1); 2283 break; 2284 case 0x7: 2285 gen_op_iwmmxt_addsw_M0_wRn(rd1); 2286 break; 2287 case 0x8: 2288 gen_op_iwmmxt_addnl_M0_wRn(rd1); 2289 break; 2290 case 0x9: 2291 gen_op_iwmmxt_addul_M0_wRn(rd1); 2292 break; 2293 case 0xb: 2294 gen_op_iwmmxt_addsl_M0_wRn(rd1); 2295 break; 2296 default: 2297 return 1; 2298 } 2299 gen_op_iwmmxt_movq_wRn_M0(wrd); 2300 gen_op_iwmmxt_set_mup(); 2301 gen_op_iwmmxt_set_cup(); 2302 break; 2303 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */ 2304 case 0x408: case 0x508: case 0x608: case 0x708: 2305 case 0x808: case 0x908: case 0xa08: case 0xb08: 2306 case 0xc08: case 0xd08: case 0xe08: case 0xf08: 2307 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0) 2308 return 1; 2309 wrd = (insn >> 12) & 0xf; 2310 rd0 = (insn >> 16) & 0xf; 2311 rd1 = (insn >> 0) & 0xf; 2312 gen_op_iwmmxt_movq_M0_wRn(rd0); 2313 switch ((insn >> 22) & 3) { 2314 case 1: 2315 if (insn & (1 << 21)) 2316 gen_op_iwmmxt_packsw_M0_wRn(rd1); 2317 else 2318 gen_op_iwmmxt_packuw_M0_wRn(rd1); 2319 break; 2320 case 2: 2321 if (insn & (1 << 21)) 2322 gen_op_iwmmxt_packsl_M0_wRn(rd1); 2323 else 2324 gen_op_iwmmxt_packul_M0_wRn(rd1); 2325 break; 2326 case 3: 2327 if (insn & (1 << 21)) 2328 gen_op_iwmmxt_packsq_M0_wRn(rd1); 2329 else 2330 gen_op_iwmmxt_packuq_M0_wRn(rd1); 2331 break; 2332 } 2333 gen_op_iwmmxt_movq_wRn_M0(wrd); 2334 gen_op_iwmmxt_set_mup(); 2335 gen_op_iwmmxt_set_cup(); 2336 break; 2337 case 0x201: case 0x203: case 0x205: case 0x207: 2338 case 0x209: case 0x20b: case 0x20d: case 0x20f: 2339 case 0x211: case 0x213: case 0x215: case 0x217: 2340 case 0x219: case 0x21b: case 0x21d: case 0x21f: 2341 wrd = (insn >> 5) & 0xf; 2342 rd0 = (insn >> 12) & 0xf; 2343 rd1 = (insn >> 0) & 0xf; 2344 if (rd0 == 0xf || rd1 == 0xf) 2345 return 1; 2346 gen_op_iwmmxt_movq_M0_wRn(wrd); 2347 tmp = load_reg(s, rd0); 2348 tmp2 = load_reg(s, rd1); 2349 switch ((insn >> 16) & 0xf) { 2350 case 0x0: /* TMIA */ 2351 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 2352 break; 2353 case 0x8: /* TMIAPH */ 2354 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 2355 break; 2356 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */ 2357 if (insn & (1 << 16)) 2358 tcg_gen_shri_i32(tmp, tmp, 16); 2359 if (insn & (1 << 17)) 2360 tcg_gen_shri_i32(tmp2, tmp2, 16); 2361 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 2362 break; 2363 default: 2364 tcg_temp_free_i32(tmp2); 2365 tcg_temp_free_i32(tmp); 2366 return 1; 2367 } 2368 tcg_temp_free_i32(tmp2); 2369 tcg_temp_free_i32(tmp); 2370 gen_op_iwmmxt_movq_wRn_M0(wrd); 2371 gen_op_iwmmxt_set_mup(); 2372 break; 2373 default: 2374 return 1; 2375 } 2376 2377 return 0; 2378 } 2379 2380 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred 2381 (ie. an undefined instruction). */ 2382 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) 2383 { 2384 int acc, rd0, rd1, rdhi, rdlo; 2385 TCGv tmp, tmp2; 2386 2387 if ((insn & 0x0ff00f10) == 0x0e200010) { 2388 /* Multiply with Internal Accumulate Format */ 2389 rd0 = (insn >> 12) & 0xf; 2390 rd1 = insn & 0xf; 2391 acc = (insn >> 5) & 7; 2392 2393 if (acc != 0) 2394 return 1; 2395 2396 tmp = load_reg(s, rd0); 2397 tmp2 = load_reg(s, rd1); 2398 switch ((insn >> 16) & 0xf) { 2399 case 0x0: /* MIA */ 2400 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 2401 break; 2402 case 0x8: /* MIAPH */ 2403 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 2404 break; 2405 case 0xc: /* MIABB */ 2406 case 0xd: /* MIABT */ 2407 case 0xe: /* MIATB */ 2408 case 0xf: /* MIATT */ 2409 if (insn & (1 << 16)) 2410 tcg_gen_shri_i32(tmp, tmp, 16); 2411 if (insn & (1 << 17)) 2412 tcg_gen_shri_i32(tmp2, tmp2, 16); 2413 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 2414 break; 2415 default: 2416 return 1; 2417 } 2418 tcg_temp_free_i32(tmp2); 2419 tcg_temp_free_i32(tmp); 2420 2421 gen_op_iwmmxt_movq_wRn_M0(acc); 2422 return 0; 2423 } 2424 2425 if ((insn & 0x0fe00ff8) == 0x0c400000) { 2426 /* Internal Accumulator Access Format */ 2427 rdhi = (insn >> 16) & 0xf; 2428 rdlo = (insn >> 12) & 0xf; 2429 acc = insn & 7; 2430 2431 if (acc != 0) 2432 return 1; 2433 2434 if (insn & ARM_CP_RW_BIT) { /* MRA */ 2435 iwmmxt_load_reg(cpu_V0, acc); 2436 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 2437 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 2438 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 2439 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1); 2440 } else { /* MAR */ 2441 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 2442 iwmmxt_store_reg(cpu_V0, acc); 2443 } 2444 return 0; 2445 } 2446 2447 return 1; 2448 } 2449 2450 /* Disassemble system coprocessor instruction. Return nonzero if 2451 instruction is not defined. */ 2452 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) 2453 { 2454 TCGv tmp, tmp2; 2455 uint32_t rd = (insn >> 12) & 0xf; 2456 uint32_t cp = (insn >> 8) & 0xf; 2457 2458 if (insn & ARM_CP_RW_BIT) { 2459 if (!env->cp[cp].cp_read) 2460 return 1; 2461 gen_set_pc_im(s->pc); 2462 tmp = tcg_temp_new_i32(); 2463 tmp2 = tcg_const_i32(insn); 2464 gen_helper_get_cp(tmp, cpu_env, tmp2); 2465 tcg_temp_free(tmp2); 2466 store_reg(s, rd, tmp); 2467 } else { 2468 if (!env->cp[cp].cp_write) 2469 return 1; 2470 gen_set_pc_im(s->pc); 2471 tmp = load_reg(s, rd); 2472 tmp2 = tcg_const_i32(insn); 2473 gen_helper_set_cp(cpu_env, tmp2, tmp); 2474 tcg_temp_free(tmp2); 2475 tcg_temp_free_i32(tmp); 2476 } 2477 return 0; 2478 } 2479 2480 static int cp15_user_ok(uint32_t insn) 2481 { 2482 int cpn = (insn >> 16) & 0xf; 2483 int cpm = insn & 0xf; 2484 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 2485 2486 if (cpn == 13 && cpm == 0) { 2487 /* TLS register. */ 2488 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT))) 2489 return 1; 2490 } 2491 if (cpn == 7) { 2492 /* ISB, DSB, DMB. */ 2493 if ((cpm == 5 && op == 4) 2494 || (cpm == 10 && (op == 4 || op == 5))) 2495 return 1; 2496 } 2497 return 0; 2498 } 2499 2500 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd) 2501 { 2502 TCGv tmp; 2503 int cpn = (insn >> 16) & 0xf; 2504 int cpm = insn & 0xf; 2505 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 2506 2507 if (!arm_feature(env, ARM_FEATURE_V6K)) 2508 return 0; 2509 2510 if (!(cpn == 13 && cpm == 0)) 2511 return 0; 2512 2513 if (insn & ARM_CP_RW_BIT) { 2514 switch (op) { 2515 case 2: 2516 tmp = load_cpu_field(cp15.c13_tls1); 2517 break; 2518 case 3: 2519 tmp = load_cpu_field(cp15.c13_tls2); 2520 break; 2521 case 4: 2522 tmp = load_cpu_field(cp15.c13_tls3); 2523 break; 2524 default: 2525 return 0; 2526 } 2527 store_reg(s, rd, tmp); 2528 2529 } else { 2530 tmp = load_reg(s, rd); 2531 switch (op) { 2532 case 2: 2533 store_cpu_field(tmp, cp15.c13_tls1); 2534 break; 2535 case 3: 2536 store_cpu_field(tmp, cp15.c13_tls2); 2537 break; 2538 case 4: 2539 store_cpu_field(tmp, cp15.c13_tls3); 2540 break; 2541 default: 2542 tcg_temp_free_i32(tmp); 2543 return 0; 2544 } 2545 } 2546 return 1; 2547 } 2548 2549 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if 2550 instruction is not defined. */ 2551 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) 2552 { 2553 uint32_t rd; 2554 TCGv tmp, tmp2; 2555 2556 /* M profile cores use memory mapped registers instead of cp15. */ 2557 if (arm_feature(env, ARM_FEATURE_M)) 2558 return 1; 2559 2560 if ((insn & (1 << 25)) == 0) { 2561 if (insn & (1 << 20)) { 2562 /* mrrc */ 2563 return 1; 2564 } 2565 /* mcrr. Used for block cache operations, so implement as no-op. */ 2566 return 0; 2567 } 2568 if ((insn & (1 << 4)) == 0) { 2569 /* cdp */ 2570 return 1; 2571 } 2572 if (IS_USER(s) && !cp15_user_ok(insn)) { 2573 return 1; 2574 } 2575 2576 /* Pre-v7 versions of the architecture implemented WFI via coprocessor 2577 * instructions rather than a separate instruction. 2578 */ 2579 if ((insn & 0x0fff0fff) == 0x0e070f90) { 2580 /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores). 2581 * In v7, this must NOP. 2582 */ 2583 if (!arm_feature(env, ARM_FEATURE_V7)) { 2584 /* Wait for interrupt. */ 2585 gen_set_pc_im(s->pc); 2586 s->is_jmp = DISAS_WFI; 2587 } 2588 return 0; 2589 } 2590 2591 if ((insn & 0x0fff0fff) == 0x0e070f58) { 2592 /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI, 2593 * so this is slightly over-broad. 2594 */ 2595 if (!arm_feature(env, ARM_FEATURE_V6)) { 2596 /* Wait for interrupt. */ 2597 gen_set_pc_im(s->pc); 2598 s->is_jmp = DISAS_WFI; 2599 return 0; 2600 } 2601 /* Otherwise fall through to handle via helper function. 2602 * In particular, on v7 and some v6 cores this is one of 2603 * the VA-PA registers. 2604 */ 2605 } 2606 2607 rd = (insn >> 12) & 0xf; 2608 2609 if (cp15_tls_load_store(env, s, insn, rd)) 2610 return 0; 2611 2612 tmp2 = tcg_const_i32(insn); 2613 if (insn & ARM_CP_RW_BIT) { 2614 tmp = tcg_temp_new_i32(); 2615 gen_helper_get_cp15(tmp, cpu_env, tmp2); 2616 /* If the destination register is r15 then sets condition codes. */ 2617 if (rd != 15) 2618 store_reg(s, rd, tmp); 2619 else 2620 tcg_temp_free_i32(tmp); 2621 } else { 2622 tmp = load_reg(s, rd); 2623 gen_helper_set_cp15(cpu_env, tmp2, tmp); 2624 tcg_temp_free_i32(tmp); 2625 /* Normally we would always end the TB here, but Linux 2626 * arch/arm/mach-pxa/sleep.S expects two instructions following 2627 * an MMU enable to execute from cache. Imitate this behaviour. */ 2628 if (!arm_feature(env, ARM_FEATURE_XSCALE) || 2629 (insn & 0x0fff0fff) != 0x0e010f10) 2630 gen_lookup_tb(s); 2631 } 2632 tcg_temp_free_i32(tmp2); 2633 return 0; 2634 } 2635 2636 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n)) 2637 #define VFP_SREG(insn, bigbit, smallbit) \ 2638 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1)) 2639 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \ 2640 if (arm_feature(env, ARM_FEATURE_VFP3)) { \ 2641 reg = (((insn) >> (bigbit)) & 0x0f) \ 2642 | (((insn) >> ((smallbit) - 4)) & 0x10); \ 2643 } else { \ 2644 if (insn & (1 << (smallbit))) \ 2645 return 1; \ 2646 reg = ((insn) >> (bigbit)) & 0x0f; \ 2647 }} while (0) 2648 2649 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22) 2650 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22) 2651 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7) 2652 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7) 2653 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) 2654 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) 2655 2656 /* Move between integer and VFP cores. */ 2657 static TCGv gen_vfp_mrs(void) 2658 { 2659 TCGv tmp = tcg_temp_new_i32(); 2660 tcg_gen_mov_i32(tmp, cpu_F0s); 2661 return tmp; 2662 } 2663 2664 static void gen_vfp_msr(TCGv tmp) 2665 { 2666 tcg_gen_mov_i32(cpu_F0s, tmp); 2667 tcg_temp_free_i32(tmp); 2668 } 2669 2670 static void gen_neon_dup_u8(TCGv var, int shift) 2671 { 2672 TCGv tmp = tcg_temp_new_i32(); 2673 if (shift) 2674 tcg_gen_shri_i32(var, var, shift); 2675 tcg_gen_ext8u_i32(var, var); 2676 tcg_gen_shli_i32(tmp, var, 8); 2677 tcg_gen_or_i32(var, var, tmp); 2678 tcg_gen_shli_i32(tmp, var, 16); 2679 tcg_gen_or_i32(var, var, tmp); 2680 tcg_temp_free_i32(tmp); 2681 } 2682 2683 static void gen_neon_dup_low16(TCGv var) 2684 { 2685 TCGv tmp = tcg_temp_new_i32(); 2686 tcg_gen_ext16u_i32(var, var); 2687 tcg_gen_shli_i32(tmp, var, 16); 2688 tcg_gen_or_i32(var, var, tmp); 2689 tcg_temp_free_i32(tmp); 2690 } 2691 2692 static void gen_neon_dup_high16(TCGv var) 2693 { 2694 TCGv tmp = tcg_temp_new_i32(); 2695 tcg_gen_andi_i32(var, var, 0xffff0000); 2696 tcg_gen_shri_i32(tmp, var, 16); 2697 tcg_gen_or_i32(var, var, tmp); 2698 tcg_temp_free_i32(tmp); 2699 } 2700 2701 static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size) 2702 { 2703 /* Load a single Neon element and replicate into a 32 bit TCG reg */ 2704 TCGv tmp; 2705 switch (size) { 2706 case 0: 2707 tmp = gen_ld8u(addr, IS_USER(s)); 2708 gen_neon_dup_u8(tmp, 0); 2709 break; 2710 case 1: 2711 tmp = gen_ld16u(addr, IS_USER(s)); 2712 gen_neon_dup_low16(tmp); 2713 break; 2714 case 2: 2715 tmp = gen_ld32(addr, IS_USER(s)); 2716 break; 2717 default: /* Avoid compiler warnings. */ 2718 abort(); 2719 } 2720 return tmp; 2721 } 2722 2723 /* Disassemble a VFP instruction. Returns nonzero if an error occurred 2724 (ie. an undefined instruction). */ 2725 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) 2726 { 2727 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; 2728 int dp, veclen; 2729 TCGv addr; 2730 TCGv tmp; 2731 TCGv tmp2; 2732 2733 if (!arm_feature(env, ARM_FEATURE_VFP)) 2734 return 1; 2735 2736 if (!s->vfp_enabled) { 2737 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */ 2738 if ((insn & 0x0fe00fff) != 0x0ee00a10) 2739 return 1; 2740 rn = (insn >> 16) & 0xf; 2741 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC 2742 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) 2743 return 1; 2744 } 2745 dp = ((insn & 0xf00) == 0xb00); 2746 switch ((insn >> 24) & 0xf) { 2747 case 0xe: 2748 if (insn & (1 << 4)) { 2749 /* single register transfer */ 2750 rd = (insn >> 12) & 0xf; 2751 if (dp) { 2752 int size; 2753 int pass; 2754 2755 VFP_DREG_N(rn, insn); 2756 if (insn & 0xf) 2757 return 1; 2758 if (insn & 0x00c00060 2759 && !arm_feature(env, ARM_FEATURE_NEON)) 2760 return 1; 2761 2762 pass = (insn >> 21) & 1; 2763 if (insn & (1 << 22)) { 2764 size = 0; 2765 offset = ((insn >> 5) & 3) * 8; 2766 } else if (insn & (1 << 5)) { 2767 size = 1; 2768 offset = (insn & (1 << 6)) ? 16 : 0; 2769 } else { 2770 size = 2; 2771 offset = 0; 2772 } 2773 if (insn & ARM_CP_RW_BIT) { 2774 /* vfp->arm */ 2775 tmp = neon_load_reg(rn, pass); 2776 switch (size) { 2777 case 0: 2778 if (offset) 2779 tcg_gen_shri_i32(tmp, tmp, offset); 2780 if (insn & (1 << 23)) 2781 gen_uxtb(tmp); 2782 else 2783 gen_sxtb(tmp); 2784 break; 2785 case 1: 2786 if (insn & (1 << 23)) { 2787 if (offset) { 2788 tcg_gen_shri_i32(tmp, tmp, 16); 2789 } else { 2790 gen_uxth(tmp); 2791 } 2792 } else { 2793 if (offset) { 2794 tcg_gen_sari_i32(tmp, tmp, 16); 2795 } else { 2796 gen_sxth(tmp); 2797 } 2798 } 2799 break; 2800 case 2: 2801 break; 2802 } 2803 store_reg(s, rd, tmp); 2804 } else { 2805 /* arm->vfp */ 2806 tmp = load_reg(s, rd); 2807 if (insn & (1 << 23)) { 2808 /* VDUP */ 2809 if (size == 0) { 2810 gen_neon_dup_u8(tmp, 0); 2811 } else if (size == 1) { 2812 gen_neon_dup_low16(tmp); 2813 } 2814 for (n = 0; n <= pass * 2; n++) { 2815 tmp2 = tcg_temp_new_i32(); 2816 tcg_gen_mov_i32(tmp2, tmp); 2817 neon_store_reg(rn, n, tmp2); 2818 } 2819 neon_store_reg(rn, n, tmp); 2820 } else { 2821 /* VMOV */ 2822 switch (size) { 2823 case 0: 2824 tmp2 = neon_load_reg(rn, pass); 2825 gen_bfi(tmp, tmp2, tmp, offset, 0xff); 2826 tcg_temp_free_i32(tmp2); 2827 break; 2828 case 1: 2829 tmp2 = neon_load_reg(rn, pass); 2830 gen_bfi(tmp, tmp2, tmp, offset, 0xffff); 2831 tcg_temp_free_i32(tmp2); 2832 break; 2833 case 2: 2834 break; 2835 } 2836 neon_store_reg(rn, pass, tmp); 2837 } 2838 } 2839 } else { /* !dp */ 2840 if ((insn & 0x6f) != 0x00) 2841 return 1; 2842 rn = VFP_SREG_N(insn); 2843 if (insn & ARM_CP_RW_BIT) { 2844 /* vfp->arm */ 2845 if (insn & (1 << 21)) { 2846 /* system register */ 2847 rn >>= 1; 2848 2849 switch (rn) { 2850 case ARM_VFP_FPSID: 2851 /* VFP2 allows access to FSID from userspace. 2852 VFP3 restricts all id registers to privileged 2853 accesses. */ 2854 if (IS_USER(s) 2855 && arm_feature(env, ARM_FEATURE_VFP3)) 2856 return 1; 2857 tmp = load_cpu_field(vfp.xregs[rn]); 2858 break; 2859 case ARM_VFP_FPEXC: 2860 if (IS_USER(s)) 2861 return 1; 2862 tmp = load_cpu_field(vfp.xregs[rn]); 2863 break; 2864 case ARM_VFP_FPINST: 2865 case ARM_VFP_FPINST2: 2866 /* Not present in VFP3. */ 2867 if (IS_USER(s) 2868 || arm_feature(env, ARM_FEATURE_VFP3)) 2869 return 1; 2870 tmp = load_cpu_field(vfp.xregs[rn]); 2871 break; 2872 case ARM_VFP_FPSCR: 2873 if (rd == 15) { 2874 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]); 2875 tcg_gen_andi_i32(tmp, tmp, 0xf0000000); 2876 } else { 2877 tmp = tcg_temp_new_i32(); 2878 gen_helper_vfp_get_fpscr(tmp, cpu_env); 2879 } 2880 break; 2881 case ARM_VFP_MVFR0: 2882 case ARM_VFP_MVFR1: 2883 if (IS_USER(s) 2884 || !arm_feature(env, ARM_FEATURE_VFP3)) 2885 return 1; 2886 tmp = load_cpu_field(vfp.xregs[rn]); 2887 break; 2888 default: 2889 return 1; 2890 } 2891 } else { 2892 gen_mov_F0_vreg(0, rn); 2893 tmp = gen_vfp_mrs(); 2894 } 2895 if (rd == 15) { 2896 /* Set the 4 flag bits in the CPSR. */ 2897 gen_set_nzcv(tmp); 2898 tcg_temp_free_i32(tmp); 2899 } else { 2900 store_reg(s, rd, tmp); 2901 } 2902 } else { 2903 /* arm->vfp */ 2904 tmp = load_reg(s, rd); 2905 if (insn & (1 << 21)) { 2906 rn >>= 1; 2907 /* system register */ 2908 switch (rn) { 2909 case ARM_VFP_FPSID: 2910 case ARM_VFP_MVFR0: 2911 case ARM_VFP_MVFR1: 2912 /* Writes are ignored. */ 2913 break; 2914 case ARM_VFP_FPSCR: 2915 gen_helper_vfp_set_fpscr(cpu_env, tmp); 2916 tcg_temp_free_i32(tmp); 2917 gen_lookup_tb(s); 2918 break; 2919 case ARM_VFP_FPEXC: 2920 if (IS_USER(s)) 2921 return 1; 2922 /* TODO: VFP subarchitecture support. 2923 * For now, keep the EN bit only */ 2924 tcg_gen_andi_i32(tmp, tmp, 1 << 30); 2925 store_cpu_field(tmp, vfp.xregs[rn]); 2926 gen_lookup_tb(s); 2927 break; 2928 case ARM_VFP_FPINST: 2929 case ARM_VFP_FPINST2: 2930 store_cpu_field(tmp, vfp.xregs[rn]); 2931 break; 2932 default: 2933 return 1; 2934 } 2935 } else { 2936 gen_vfp_msr(tmp); 2937 gen_mov_vreg_F0(0, rn); 2938 } 2939 } 2940 } 2941 } else { 2942 /* data processing */ 2943 /* The opcode is in bits 23, 21, 20 and 6. */ 2944 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1); 2945 if (dp) { 2946 if (op == 15) { 2947 /* rn is opcode */ 2948 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 2949 } else { 2950 /* rn is register number */ 2951 VFP_DREG_N(rn, insn); 2952 } 2953 2954 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) { 2955 /* Integer or single precision destination. */ 2956 rd = VFP_SREG_D(insn); 2957 } else { 2958 VFP_DREG_D(rd, insn); 2959 } 2960 if (op == 15 && 2961 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) { 2962 /* VCVT from int is always from S reg regardless of dp bit. 2963 * VCVT with immediate frac_bits has same format as SREG_M 2964 */ 2965 rm = VFP_SREG_M(insn); 2966 } else { 2967 VFP_DREG_M(rm, insn); 2968 } 2969 } else { 2970 rn = VFP_SREG_N(insn); 2971 if (op == 15 && rn == 15) { 2972 /* Double precision destination. */ 2973 VFP_DREG_D(rd, insn); 2974 } else { 2975 rd = VFP_SREG_D(insn); 2976 } 2977 /* NB that we implicitly rely on the encoding for the frac_bits 2978 * in VCVT of fixed to float being the same as that of an SREG_M 2979 */ 2980 rm = VFP_SREG_M(insn); 2981 } 2982 2983 veclen = s->vec_len; 2984 if (op == 15 && rn > 3) 2985 veclen = 0; 2986 2987 /* Shut up compiler warnings. */ 2988 delta_m = 0; 2989 delta_d = 0; 2990 bank_mask = 0; 2991 2992 if (veclen > 0) { 2993 if (dp) 2994 bank_mask = 0xc; 2995 else 2996 bank_mask = 0x18; 2997 2998 /* Figure out what type of vector operation this is. */ 2999 if ((rd & bank_mask) == 0) { 3000 /* scalar */ 3001 veclen = 0; 3002 } else { 3003 if (dp) 3004 delta_d = (s->vec_stride >> 1) + 1; 3005 else 3006 delta_d = s->vec_stride + 1; 3007 3008 if ((rm & bank_mask) == 0) { 3009 /* mixed scalar/vector */ 3010 delta_m = 0; 3011 } else { 3012 /* vector */ 3013 delta_m = delta_d; 3014 } 3015 } 3016 } 3017 3018 /* Load the initial operands. */ 3019 if (op == 15) { 3020 switch (rn) { 3021 case 16: 3022 case 17: 3023 /* Integer source */ 3024 gen_mov_F0_vreg(0, rm); 3025 break; 3026 case 8: 3027 case 9: 3028 /* Compare */ 3029 gen_mov_F0_vreg(dp, rd); 3030 gen_mov_F1_vreg(dp, rm); 3031 break; 3032 case 10: 3033 case 11: 3034 /* Compare with zero */ 3035 gen_mov_F0_vreg(dp, rd); 3036 gen_vfp_F1_ld0(dp); 3037 break; 3038 case 20: 3039 case 21: 3040 case 22: 3041 case 23: 3042 case 28: 3043 case 29: 3044 case 30: 3045 case 31: 3046 /* Source and destination the same. */ 3047 gen_mov_F0_vreg(dp, rd); 3048 break; 3049 default: 3050 /* One source operand. */ 3051 gen_mov_F0_vreg(dp, rm); 3052 break; 3053 } 3054 } else { 3055 /* Two source operands. */ 3056 gen_mov_F0_vreg(dp, rn); 3057 gen_mov_F1_vreg(dp, rm); 3058 } 3059 3060 for (;;) { 3061 /* Perform the calculation. */ 3062 switch (op) { 3063 case 0: /* VMLA: fd + (fn * fm) */ 3064 /* Note that order of inputs to the add matters for NaNs */ 3065 gen_vfp_F1_mul(dp); 3066 gen_mov_F0_vreg(dp, rd); 3067 gen_vfp_add(dp); 3068 break; 3069 case 1: /* VMLS: fd + -(fn * fm) */ 3070 gen_vfp_mul(dp); 3071 gen_vfp_F1_neg(dp); 3072 gen_mov_F0_vreg(dp, rd); 3073 gen_vfp_add(dp); 3074 break; 3075 case 2: /* VNMLS: -fd + (fn * fm) */ 3076 /* Note that it isn't valid to replace (-A + B) with (B - A) 3077 * or similar plausible looking simplifications 3078 * because this will give wrong results for NaNs. 3079 */ 3080 gen_vfp_F1_mul(dp); 3081 gen_mov_F0_vreg(dp, rd); 3082 gen_vfp_neg(dp); 3083 gen_vfp_add(dp); 3084 break; 3085 case 3: /* VNMLA: -fd + -(fn * fm) */ 3086 gen_vfp_mul(dp); 3087 gen_vfp_F1_neg(dp); 3088 gen_mov_F0_vreg(dp, rd); 3089 gen_vfp_neg(dp); 3090 gen_vfp_add(dp); 3091 break; 3092 case 4: /* mul: fn * fm */ 3093 gen_vfp_mul(dp); 3094 break; 3095 case 5: /* nmul: -(fn * fm) */ 3096 gen_vfp_mul(dp); 3097 gen_vfp_neg(dp); 3098 break; 3099 case 6: /* add: fn + fm */ 3100 gen_vfp_add(dp); 3101 break; 3102 case 7: /* sub: fn - fm */ 3103 gen_vfp_sub(dp); 3104 break; 3105 case 8: /* div: fn / fm */ 3106 gen_vfp_div(dp); 3107 break; 3108 case 14: /* fconst */ 3109 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3110 return 1; 3111 3112 n = (insn << 12) & 0x80000000; 3113 i = ((insn >> 12) & 0x70) | (insn & 0xf); 3114 if (dp) { 3115 if (i & 0x40) 3116 i |= 0x3f80; 3117 else 3118 i |= 0x4000; 3119 n |= i << 16; 3120 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32); 3121 } else { 3122 if (i & 0x40) 3123 i |= 0x780; 3124 else 3125 i |= 0x800; 3126 n |= i << 19; 3127 tcg_gen_movi_i32(cpu_F0s, n); 3128 } 3129 break; 3130 case 15: /* extension space */ 3131 switch (rn) { 3132 case 0: /* cpy */ 3133 /* no-op */ 3134 break; 3135 case 1: /* abs */ 3136 gen_vfp_abs(dp); 3137 break; 3138 case 2: /* neg */ 3139 gen_vfp_neg(dp); 3140 break; 3141 case 3: /* sqrt */ 3142 gen_vfp_sqrt(dp); 3143 break; 3144 case 4: /* vcvtb.f32.f16 */ 3145 if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 3146 return 1; 3147 tmp = gen_vfp_mrs(); 3148 tcg_gen_ext16u_i32(tmp, tmp); 3149 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 3150 tcg_temp_free_i32(tmp); 3151 break; 3152 case 5: /* vcvtt.f32.f16 */ 3153 if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 3154 return 1; 3155 tmp = gen_vfp_mrs(); 3156 tcg_gen_shri_i32(tmp, tmp, 16); 3157 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 3158 tcg_temp_free_i32(tmp); 3159 break; 3160 case 6: /* vcvtb.f16.f32 */ 3161 if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 3162 return 1; 3163 tmp = tcg_temp_new_i32(); 3164 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 3165 gen_mov_F0_vreg(0, rd); 3166 tmp2 = gen_vfp_mrs(); 3167 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 3168 tcg_gen_or_i32(tmp, tmp, tmp2); 3169 tcg_temp_free_i32(tmp2); 3170 gen_vfp_msr(tmp); 3171 break; 3172 case 7: /* vcvtt.f16.f32 */ 3173 if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 3174 return 1; 3175 tmp = tcg_temp_new_i32(); 3176 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 3177 tcg_gen_shli_i32(tmp, tmp, 16); 3178 gen_mov_F0_vreg(0, rd); 3179 tmp2 = gen_vfp_mrs(); 3180 tcg_gen_ext16u_i32(tmp2, tmp2); 3181 tcg_gen_or_i32(tmp, tmp, tmp2); 3182 tcg_temp_free_i32(tmp2); 3183 gen_vfp_msr(tmp); 3184 break; 3185 case 8: /* cmp */ 3186 gen_vfp_cmp(dp); 3187 break; 3188 case 9: /* cmpe */ 3189 gen_vfp_cmpe(dp); 3190 break; 3191 case 10: /* cmpz */ 3192 gen_vfp_cmp(dp); 3193 break; 3194 case 11: /* cmpez */ 3195 gen_vfp_F1_ld0(dp); 3196 gen_vfp_cmpe(dp); 3197 break; 3198 case 15: /* single<->double conversion */ 3199 if (dp) 3200 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env); 3201 else 3202 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env); 3203 break; 3204 case 16: /* fuito */ 3205 gen_vfp_uito(dp, 0); 3206 break; 3207 case 17: /* fsito */ 3208 gen_vfp_sito(dp, 0); 3209 break; 3210 case 20: /* fshto */ 3211 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3212 return 1; 3213 gen_vfp_shto(dp, 16 - rm, 0); 3214 break; 3215 case 21: /* fslto */ 3216 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3217 return 1; 3218 gen_vfp_slto(dp, 32 - rm, 0); 3219 break; 3220 case 22: /* fuhto */ 3221 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3222 return 1; 3223 gen_vfp_uhto(dp, 16 - rm, 0); 3224 break; 3225 case 23: /* fulto */ 3226 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3227 return 1; 3228 gen_vfp_ulto(dp, 32 - rm, 0); 3229 break; 3230 case 24: /* ftoui */ 3231 gen_vfp_toui(dp, 0); 3232 break; 3233 case 25: /* ftouiz */ 3234 gen_vfp_touiz(dp, 0); 3235 break; 3236 case 26: /* ftosi */ 3237 gen_vfp_tosi(dp, 0); 3238 break; 3239 case 27: /* ftosiz */ 3240 gen_vfp_tosiz(dp, 0); 3241 break; 3242 case 28: /* ftosh */ 3243 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3244 return 1; 3245 gen_vfp_tosh(dp, 16 - rm, 0); 3246 break; 3247 case 29: /* ftosl */ 3248 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3249 return 1; 3250 gen_vfp_tosl(dp, 32 - rm, 0); 3251 break; 3252 case 30: /* ftouh */ 3253 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3254 return 1; 3255 gen_vfp_touh(dp, 16 - rm, 0); 3256 break; 3257 case 31: /* ftoul */ 3258 if (!arm_feature(env, ARM_FEATURE_VFP3)) 3259 return 1; 3260 gen_vfp_toul(dp, 32 - rm, 0); 3261 break; 3262 default: /* undefined */ 3263 printf ("rn:%d\n", rn); 3264 return 1; 3265 } 3266 break; 3267 default: /* undefined */ 3268 printf ("op:%d\n", op); 3269 return 1; 3270 } 3271 3272 /* Write back the result. */ 3273 if (op == 15 && (rn >= 8 && rn <= 11)) 3274 ; /* Comparison, do nothing. */ 3275 else if (op == 15 && dp && ((rn & 0x1c) == 0x18)) 3276 /* VCVT double to int: always integer result. */ 3277 gen_mov_vreg_F0(0, rd); 3278 else if (op == 15 && rn == 15) 3279 /* conversion */ 3280 gen_mov_vreg_F0(!dp, rd); 3281 else 3282 gen_mov_vreg_F0(dp, rd); 3283 3284 /* break out of the loop if we have finished */ 3285 if (veclen == 0) 3286 break; 3287 3288 if (op == 15 && delta_m == 0) { 3289 /* single source one-many */ 3290 while (veclen--) { 3291 rd = ((rd + delta_d) & (bank_mask - 1)) 3292 | (rd & bank_mask); 3293 gen_mov_vreg_F0(dp, rd); 3294 } 3295 break; 3296 } 3297 /* Setup the next operands. */ 3298 veclen--; 3299 rd = ((rd + delta_d) & (bank_mask - 1)) 3300 | (rd & bank_mask); 3301 3302 if (op == 15) { 3303 /* One source operand. */ 3304 rm = ((rm + delta_m) & (bank_mask - 1)) 3305 | (rm & bank_mask); 3306 gen_mov_F0_vreg(dp, rm); 3307 } else { 3308 /* Two source operands. */ 3309 rn = ((rn + delta_d) & (bank_mask - 1)) 3310 | (rn & bank_mask); 3311 gen_mov_F0_vreg(dp, rn); 3312 if (delta_m) { 3313 rm = ((rm + delta_m) & (bank_mask - 1)) 3314 | (rm & bank_mask); 3315 gen_mov_F1_vreg(dp, rm); 3316 } 3317 } 3318 } 3319 } 3320 break; 3321 case 0xc: 3322 case 0xd: 3323 if ((insn & 0x03e00000) == 0x00400000) { 3324 /* two-register transfer */ 3325 rn = (insn >> 16) & 0xf; 3326 rd = (insn >> 12) & 0xf; 3327 if (dp) { 3328 VFP_DREG_M(rm, insn); 3329 } else { 3330 rm = VFP_SREG_M(insn); 3331 } 3332 3333 if (insn & ARM_CP_RW_BIT) { 3334 /* vfp->arm */ 3335 if (dp) { 3336 gen_mov_F0_vreg(0, rm * 2); 3337 tmp = gen_vfp_mrs(); 3338 store_reg(s, rd, tmp); 3339 gen_mov_F0_vreg(0, rm * 2 + 1); 3340 tmp = gen_vfp_mrs(); 3341 store_reg(s, rn, tmp); 3342 } else { 3343 gen_mov_F0_vreg(0, rm); 3344 tmp = gen_vfp_mrs(); 3345 store_reg(s, rd, tmp); 3346 gen_mov_F0_vreg(0, rm + 1); 3347 tmp = gen_vfp_mrs(); 3348 store_reg(s, rn, tmp); 3349 } 3350 } else { 3351 /* arm->vfp */ 3352 if (dp) { 3353 tmp = load_reg(s, rd); 3354 gen_vfp_msr(tmp); 3355 gen_mov_vreg_F0(0, rm * 2); 3356 tmp = load_reg(s, rn); 3357 gen_vfp_msr(tmp); 3358 gen_mov_vreg_F0(0, rm * 2 + 1); 3359 } else { 3360 tmp = load_reg(s, rd); 3361 gen_vfp_msr(tmp); 3362 gen_mov_vreg_F0(0, rm); 3363 tmp = load_reg(s, rn); 3364 gen_vfp_msr(tmp); 3365 gen_mov_vreg_F0(0, rm + 1); 3366 } 3367 } 3368 } else { 3369 /* Load/store */ 3370 rn = (insn >> 16) & 0xf; 3371 if (dp) 3372 VFP_DREG_D(rd, insn); 3373 else 3374 rd = VFP_SREG_D(insn); 3375 if (s->thumb && rn == 15) { 3376 addr = tcg_temp_new_i32(); 3377 tcg_gen_movi_i32(addr, s->pc & ~2); 3378 } else { 3379 addr = load_reg(s, rn); 3380 } 3381 if ((insn & 0x01200000) == 0x01000000) { 3382 /* Single load/store */ 3383 offset = (insn & 0xff) << 2; 3384 if ((insn & (1 << 23)) == 0) 3385 offset = -offset; 3386 tcg_gen_addi_i32(addr, addr, offset); 3387 if (insn & (1 << 20)) { 3388 gen_vfp_ld(s, dp, addr); 3389 gen_mov_vreg_F0(dp, rd); 3390 } else { 3391 gen_mov_F0_vreg(dp, rd); 3392 gen_vfp_st(s, dp, addr); 3393 } 3394 tcg_temp_free_i32(addr); 3395 } else { 3396 /* load/store multiple */ 3397 if (dp) 3398 n = (insn >> 1) & 0x7f; 3399 else 3400 n = insn & 0xff; 3401 3402 if (insn & (1 << 24)) /* pre-decrement */ 3403 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); 3404 3405 if (dp) 3406 offset = 8; 3407 else 3408 offset = 4; 3409 tmp = tcg_const_i32(offset); 3410 for (i = 0; i < n; i++) { 3411 if (insn & ARM_CP_RW_BIT) { 3412 /* load */ 3413 gen_vfp_ld(s, dp, addr); 3414 gen_mov_vreg_F0(dp, rd + i); 3415 } else { 3416 /* store */ 3417 gen_mov_F0_vreg(dp, rd + i); 3418 gen_vfp_st(s, dp, addr); 3419 } 3420 tcg_gen_add_i32(addr, addr, tmp); 3421 } 3422 tcg_temp_free_i32(tmp); 3423 if (insn & (1 << 21)) { 3424 /* writeback */ 3425 if (insn & (1 << 24)) 3426 offset = -offset * n; 3427 else if (dp && (insn & 1)) 3428 offset = 4; 3429 else 3430 offset = 0; 3431 3432 if (offset != 0) 3433 tcg_gen_addi_i32(addr, addr, offset); 3434 store_reg(s, rn, addr); 3435 } else { 3436 tcg_temp_free_i32(addr); 3437 } 3438 } 3439 } 3440 break; 3441 default: 3442 /* Should never happen. */ 3443 return 1; 3444 } 3445 return 0; 3446 } 3447 3448 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) 3449 { 3450 TranslationBlock *tb; 3451 3452 tb = s->tb; 3453 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { 3454 tcg_gen_goto_tb(n); 3455 gen_set_pc_im(dest); 3456 tcg_gen_exit_tb((tcg_target_long)tb + n); 3457 } else { 3458 gen_set_pc_im(dest); 3459 tcg_gen_exit_tb(0); 3460 } 3461 } 3462 3463 static inline void gen_jmp (DisasContext *s, uint32_t dest) 3464 { 3465 if (unlikely(s->singlestep_enabled)) { 3466 /* An indirect jump so that we still trigger the debug exception. */ 3467 if (s->thumb) 3468 dest |= 1; 3469 gen_bx_im(s, dest); 3470 } else { 3471 gen_goto_tb(s, 0, dest); 3472 s->is_jmp = DISAS_TB_JUMP; 3473 } 3474 } 3475 3476 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y) 3477 { 3478 if (x) 3479 tcg_gen_sari_i32(t0, t0, 16); 3480 else 3481 gen_sxth(t0); 3482 if (y) 3483 tcg_gen_sari_i32(t1, t1, 16); 3484 else 3485 gen_sxth(t1); 3486 tcg_gen_mul_i32(t0, t0, t1); 3487 } 3488 3489 /* Return the mask of PSR bits set by a MSR instruction. */ 3490 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) { 3491 uint32_t mask; 3492 3493 mask = 0; 3494 if (flags & (1 << 0)) 3495 mask |= 0xff; 3496 if (flags & (1 << 1)) 3497 mask |= 0xff00; 3498 if (flags & (1 << 2)) 3499 mask |= 0xff0000; 3500 if (flags & (1 << 3)) 3501 mask |= 0xff000000; 3502 3503 /* Mask out undefined bits. */ 3504 mask &= ~CPSR_RESERVED; 3505 if (!arm_feature(env, ARM_FEATURE_V4T)) 3506 mask &= ~CPSR_T; 3507 if (!arm_feature(env, ARM_FEATURE_V5)) 3508 mask &= ~CPSR_Q; /* V5TE in reality*/ 3509 if (!arm_feature(env, ARM_FEATURE_V6)) 3510 mask &= ~(CPSR_E | CPSR_GE); 3511 if (!arm_feature(env, ARM_FEATURE_THUMB2)) 3512 mask &= ~CPSR_IT; 3513 /* Mask out execution state bits. */ 3514 if (!spsr) 3515 mask &= ~CPSR_EXEC; 3516 /* Mask out privileged bits. */ 3517 if (IS_USER(s)) 3518 mask &= CPSR_USER; 3519 return mask; 3520 } 3521 3522 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ 3523 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) 3524 { 3525 TCGv tmp; 3526 if (spsr) { 3527 /* ??? This is also undefined in system mode. */ 3528 if (IS_USER(s)) 3529 return 1; 3530 3531 tmp = load_cpu_field(spsr); 3532 tcg_gen_andi_i32(tmp, tmp, ~mask); 3533 tcg_gen_andi_i32(t0, t0, mask); 3534 tcg_gen_or_i32(tmp, tmp, t0); 3535 store_cpu_field(tmp, spsr); 3536 } else { 3537 gen_set_cpsr(t0, mask); 3538 } 3539 tcg_temp_free_i32(t0); 3540 gen_lookup_tb(s); 3541 return 0; 3542 } 3543 3544 /* Returns nonzero if access to the PSR is not permitted. */ 3545 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val) 3546 { 3547 TCGv tmp; 3548 tmp = tcg_temp_new_i32(); 3549 tcg_gen_movi_i32(tmp, val); 3550 return gen_set_psr(s, mask, spsr, tmp); 3551 } 3552 3553 /* Generate an old-style exception return. Marks pc as dead. */ 3554 static void gen_exception_return(DisasContext *s, TCGv pc) 3555 { 3556 TCGv tmp; 3557 store_reg(s, 15, pc); 3558 tmp = load_cpu_field(spsr); 3559 gen_set_cpsr(tmp, 0xffffffff); 3560 tcg_temp_free_i32(tmp); 3561 s->is_jmp = DISAS_UPDATE; 3562 } 3563 3564 /* Generate a v6 exception return. Marks both values as dead. */ 3565 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) 3566 { 3567 gen_set_cpsr(cpsr, 0xffffffff); 3568 tcg_temp_free_i32(cpsr); 3569 store_reg(s, 15, pc); 3570 s->is_jmp = DISAS_UPDATE; 3571 } 3572 3573 static inline void 3574 gen_set_condexec (DisasContext *s) 3575 { 3576 if (s->condexec_mask) { 3577 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); 3578 TCGv tmp = tcg_temp_new_i32(); 3579 tcg_gen_movi_i32(tmp, val); 3580 store_cpu_field(tmp, condexec_bits); 3581 } 3582 } 3583 3584 static void gen_exception_insn(DisasContext *s, int offset, int excp) 3585 { 3586 gen_set_condexec(s); 3587 gen_set_pc_im(s->pc - offset); 3588 gen_exception(excp); 3589 s->is_jmp = DISAS_JUMP; 3590 } 3591 3592 static void gen_nop_hint(DisasContext *s, int val) 3593 { 3594 switch (val) { 3595 case 3: /* wfi */ 3596 gen_set_pc_im(s->pc); 3597 s->is_jmp = DISAS_WFI; 3598 break; 3599 case 2: /* wfe */ 3600 case 4: /* sev */ 3601 /* TODO: Implement SEV and WFE. May help SMP performance. */ 3602 default: /* nop */ 3603 break; 3604 } 3605 } 3606 3607 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1 3608 3609 static inline void gen_neon_add(int size, TCGv t0, TCGv t1) 3610 { 3611 switch (size) { 3612 case 0: gen_helper_neon_add_u8(t0, t0, t1); break; 3613 case 1: gen_helper_neon_add_u16(t0, t0, t1); break; 3614 case 2: tcg_gen_add_i32(t0, t0, t1); break; 3615 default: abort(); 3616 } 3617 } 3618 3619 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) 3620 { 3621 switch (size) { 3622 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; 3623 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break; 3624 case 2: tcg_gen_sub_i32(t0, t1, t0); break; 3625 default: return; 3626 } 3627 } 3628 3629 /* 32-bit pairwise ops end up the same as the elementwise versions. */ 3630 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32 3631 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32 3632 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32 3633 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32 3634 3635 #define GEN_NEON_INTEGER_OP(name) do { \ 3636 switch ((size << 1) | u) { \ 3637 case 0: \ 3638 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \ 3639 break; \ 3640 case 1: \ 3641 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \ 3642 break; \ 3643 case 2: \ 3644 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \ 3645 break; \ 3646 case 3: \ 3647 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \ 3648 break; \ 3649 case 4: \ 3650 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \ 3651 break; \ 3652 case 5: \ 3653 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \ 3654 break; \ 3655 default: return 1; \ 3656 }} while (0) 3657 3658 static TCGv neon_load_scratch(int scratch) 3659 { 3660 TCGv tmp = tcg_temp_new_i32(); 3661 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 3662 return tmp; 3663 } 3664 3665 static void neon_store_scratch(int scratch, TCGv var) 3666 { 3667 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 3668 tcg_temp_free_i32(var); 3669 } 3670 3671 static inline TCGv neon_get_scalar(int size, int reg) 3672 { 3673 TCGv tmp; 3674 if (size == 1) { 3675 tmp = neon_load_reg(reg & 7, reg >> 4); 3676 if (reg & 8) { 3677 gen_neon_dup_high16(tmp); 3678 } else { 3679 gen_neon_dup_low16(tmp); 3680 } 3681 } else { 3682 tmp = neon_load_reg(reg & 15, reg >> 4); 3683 } 3684 return tmp; 3685 } 3686 3687 static int gen_neon_unzip(int rd, int rm, int size, int q) 3688 { 3689 TCGv tmp, tmp2; 3690 if (!q && size == 2) { 3691 return 1; 3692 } 3693 tmp = tcg_const_i32(rd); 3694 tmp2 = tcg_const_i32(rm); 3695 if (q) { 3696 switch (size) { 3697 case 0: 3698 gen_helper_neon_qunzip8(tmp, tmp2); 3699 break; 3700 case 1: 3701 gen_helper_neon_qunzip16(tmp, tmp2); 3702 break; 3703 case 2: 3704 gen_helper_neon_qunzip32(tmp, tmp2); 3705 break; 3706 default: 3707 abort(); 3708 } 3709 } else { 3710 switch (size) { 3711 case 0: 3712 gen_helper_neon_unzip8(tmp, tmp2); 3713 break; 3714 case 1: 3715 gen_helper_neon_unzip16(tmp, tmp2); 3716 break; 3717 default: 3718 abort(); 3719 } 3720 } 3721 tcg_temp_free_i32(tmp); 3722 tcg_temp_free_i32(tmp2); 3723 return 0; 3724 } 3725 3726 static int gen_neon_zip(int rd, int rm, int size, int q) 3727 { 3728 TCGv tmp, tmp2; 3729 if (!q && size == 2) { 3730 return 1; 3731 } 3732 tmp = tcg_const_i32(rd); 3733 tmp2 = tcg_const_i32(rm); 3734 if (q) { 3735 switch (size) { 3736 case 0: 3737 gen_helper_neon_qzip8(tmp, tmp2); 3738 break; 3739 case 1: 3740 gen_helper_neon_qzip16(tmp, tmp2); 3741 break; 3742 case 2: 3743 gen_helper_neon_qzip32(tmp, tmp2); 3744 break; 3745 default: 3746 abort(); 3747 } 3748 } else { 3749 switch (size) { 3750 case 0: 3751 gen_helper_neon_zip8(tmp, tmp2); 3752 break; 3753 case 1: 3754 gen_helper_neon_zip16(tmp, tmp2); 3755 break; 3756 default: 3757 abort(); 3758 } 3759 } 3760 tcg_temp_free_i32(tmp); 3761 tcg_temp_free_i32(tmp2); 3762 return 0; 3763 } 3764 3765 static void gen_neon_trn_u8(TCGv t0, TCGv t1) 3766 { 3767 TCGv rd, tmp; 3768 3769 rd = tcg_temp_new_i32(); 3770 tmp = tcg_temp_new_i32(); 3771 3772 tcg_gen_shli_i32(rd, t0, 8); 3773 tcg_gen_andi_i32(rd, rd, 0xff00ff00); 3774 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); 3775 tcg_gen_or_i32(rd, rd, tmp); 3776 3777 tcg_gen_shri_i32(t1, t1, 8); 3778 tcg_gen_andi_i32(t1, t1, 0x00ff00ff); 3779 tcg_gen_andi_i32(tmp, t0, 0xff00ff00); 3780 tcg_gen_or_i32(t1, t1, tmp); 3781 tcg_gen_mov_i32(t0, rd); 3782 3783 tcg_temp_free_i32(tmp); 3784 tcg_temp_free_i32(rd); 3785 } 3786 3787 static void gen_neon_trn_u16(TCGv t0, TCGv t1) 3788 { 3789 TCGv rd, tmp; 3790 3791 rd = tcg_temp_new_i32(); 3792 tmp = tcg_temp_new_i32(); 3793 3794 tcg_gen_shli_i32(rd, t0, 16); 3795 tcg_gen_andi_i32(tmp, t1, 0xffff); 3796 tcg_gen_or_i32(rd, rd, tmp); 3797 tcg_gen_shri_i32(t1, t1, 16); 3798 tcg_gen_andi_i32(tmp, t0, 0xffff0000); 3799 tcg_gen_or_i32(t1, t1, tmp); 3800 tcg_gen_mov_i32(t0, rd); 3801 3802 tcg_temp_free_i32(tmp); 3803 tcg_temp_free_i32(rd); 3804 } 3805 3806 3807 static struct { 3808 int nregs; 3809 int interleave; 3810 int spacing; 3811 } neon_ls_element_type[11] = { 3812 {4, 4, 1}, 3813 {4, 4, 2}, 3814 {4, 1, 1}, 3815 {4, 2, 1}, 3816 {3, 3, 1}, 3817 {3, 3, 2}, 3818 {3, 1, 1}, 3819 {1, 1, 1}, 3820 {2, 2, 1}, 3821 {2, 2, 2}, 3822 {2, 1, 1} 3823 }; 3824 3825 /* Translate a NEON load/store element instruction. Return nonzero if the 3826 instruction is invalid. */ 3827 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) 3828 { 3829 int rd, rn, rm; 3830 int op; 3831 int nregs; 3832 int interleave; 3833 int spacing; 3834 int stride; 3835 int size; 3836 int reg; 3837 int pass; 3838 int load; 3839 int shift; 3840 TCGv addr; 3841 TCGv tmp; 3842 TCGv tmp2; 3843 3844 if (!s->vfp_enabled) 3845 return 1; 3846 VFP_DREG_D(rd, insn); 3847 rn = (insn >> 16) & 0xf; 3848 rm = insn & 0xf; 3849 load = (insn & (1 << 21)) != 0; 3850 if ((insn & (1 << 23)) == 0) { 3851 /* Load store all elements. */ 3852 op = (insn >> 8) & 0xf; 3853 size = (insn >> 6) & 3; 3854 if (op > 10) 3855 return 1; 3856 /* Catch UNDEF cases for bad values of align field */ 3857 switch (op & 0xc) { 3858 case 4: 3859 if (((insn >> 5) & 1) == 1) { 3860 return 1; 3861 } 3862 break; 3863 case 8: 3864 if (((insn >> 4) & 3) == 3) { 3865 return 1; 3866 } 3867 break; 3868 default: 3869 break; 3870 } 3871 nregs = neon_ls_element_type[op].nregs; 3872 interleave = neon_ls_element_type[op].interleave; 3873 spacing = neon_ls_element_type[op].spacing; 3874 if (size == 3 && (interleave | spacing) != 1) { 3875 return 1; 3876 } 3877 addr = tcg_const_i32(insn); 3878 gen_helper_neon_vldst_all(addr); 3879 tcg_temp_free_i32(addr); 3880 stride = nregs * 8; 3881 } else { 3882 size = (insn >> 10) & 3; 3883 if (size == 3) { 3884 /* Load single element to all lanes. */ 3885 int a = (insn >> 4) & 1; 3886 if (!load) { 3887 return 1; 3888 } 3889 size = (insn >> 6) & 3; 3890 nregs = ((insn >> 8) & 3) + 1; 3891 3892 if (size == 3) { 3893 if (nregs != 4 || a == 0) { 3894 return 1; 3895 } 3896 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */ 3897 size = 2; 3898 } 3899 if (nregs == 1 && a == 1 && size == 0) { 3900 return 1; 3901 } 3902 if (nregs == 3 && a == 1) { 3903 return 1; 3904 } 3905 addr = tcg_temp_new_i32(); 3906 load_reg_var(s, addr, rn); 3907 if (nregs == 1) { 3908 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */ 3909 tmp = gen_load_and_replicate(s, addr, size); 3910 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 3911 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 3912 if (insn & (1 << 5)) { 3913 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0)); 3914 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1)); 3915 } 3916 tcg_temp_free_i32(tmp); 3917 } else { 3918 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */ 3919 stride = (insn & (1 << 5)) ? 2 : 1; 3920 for (reg = 0; reg < nregs; reg++) { 3921 tmp = gen_load_and_replicate(s, addr, size); 3922 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 3923 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 3924 tcg_temp_free_i32(tmp); 3925 tcg_gen_addi_i32(addr, addr, 1 << size); 3926 rd += stride; 3927 } 3928 } 3929 tcg_temp_free_i32(addr); 3930 stride = (1 << size) * nregs; 3931 } else { 3932 /* Single element. */ 3933 int idx = (insn >> 4) & 0xf; 3934 pass = (insn >> 7) & 1; 3935 switch (size) { 3936 case 0: 3937 shift = ((insn >> 5) & 3) * 8; 3938 stride = 1; 3939 break; 3940 case 1: 3941 shift = ((insn >> 6) & 1) * 16; 3942 stride = (insn & (1 << 5)) ? 2 : 1; 3943 break; 3944 case 2: 3945 shift = 0; 3946 stride = (insn & (1 << 6)) ? 2 : 1; 3947 break; 3948 default: 3949 abort(); 3950 } 3951 nregs = ((insn >> 8) & 3) + 1; 3952 /* Catch the UNDEF cases. This is unavoidably a bit messy. */ 3953 switch (nregs) { 3954 case 1: 3955 if (((idx & (1 << size)) != 0) || 3956 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) { 3957 return 1; 3958 } 3959 break; 3960 case 3: 3961 if ((idx & 1) != 0) { 3962 return 1; 3963 } 3964 /* fall through */ 3965 case 2: 3966 if (size == 2 && (idx & 2) != 0) { 3967 return 1; 3968 } 3969 break; 3970 case 4: 3971 if ((size == 2) && ((idx & 3) == 3)) { 3972 return 1; 3973 } 3974 break; 3975 default: 3976 abort(); 3977 } 3978 if ((rd + stride * (nregs - 1)) > 31) { 3979 /* Attempts to write off the end of the register file 3980 * are UNPREDICTABLE; we choose to UNDEF because otherwise 3981 * the neon_load_reg() would write off the end of the array. 3982 */ 3983 return 1; 3984 } 3985 addr = tcg_temp_new_i32(); 3986 load_reg_var(s, addr, rn); 3987 for (reg = 0; reg < nregs; reg++) { 3988 if (load) { 3989 switch (size) { 3990 case 0: 3991 tmp = gen_ld8u(addr, IS_USER(s)); 3992 break; 3993 case 1: 3994 tmp = gen_ld16u(addr, IS_USER(s)); 3995 break; 3996 case 2: 3997 tmp = gen_ld32(addr, IS_USER(s)); 3998 break; 3999 default: /* Avoid compiler warnings. */ 4000 abort(); 4001 } 4002 if (size != 2) { 4003 tmp2 = neon_load_reg(rd, pass); 4004 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff); 4005 tcg_temp_free_i32(tmp2); 4006 } 4007 neon_store_reg(rd, pass, tmp); 4008 } else { /* Store */ 4009 tmp = neon_load_reg(rd, pass); 4010 if (shift) 4011 tcg_gen_shri_i32(tmp, tmp, shift); 4012 switch (size) { 4013 case 0: 4014 gen_st8(tmp, addr, IS_USER(s)); 4015 break; 4016 case 1: 4017 gen_st16(tmp, addr, IS_USER(s)); 4018 break; 4019 case 2: 4020 gen_st32(tmp, addr, IS_USER(s)); 4021 break; 4022 } 4023 } 4024 rd += stride; 4025 tcg_gen_addi_i32(addr, addr, 1 << size); 4026 } 4027 tcg_temp_free_i32(addr); 4028 stride = nregs * (1 << size); 4029 } 4030 } 4031 if (rm != 15) { 4032 TCGv base; 4033 4034 base = load_reg(s, rn); 4035 if (rm == 13) { 4036 tcg_gen_addi_i32(base, base, stride); 4037 } else { 4038 TCGv index; 4039 index = load_reg(s, rm); 4040 tcg_gen_add_i32(base, base, index); 4041 tcg_temp_free_i32(index); 4042 } 4043 store_reg(s, rn, base); 4044 } 4045 return 0; 4046 } 4047 4048 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */ 4049 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c) 4050 { 4051 tcg_gen_and_i32(t, t, c); 4052 tcg_gen_andc_i32(f, f, c); 4053 tcg_gen_or_i32(dest, t, f); 4054 } 4055 4056 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src) 4057 { 4058 switch (size) { 4059 case 0: gen_helper_neon_narrow_u8(dest, src); break; 4060 case 1: gen_helper_neon_narrow_u16(dest, src); break; 4061 case 2: tcg_gen_trunc_i64_i32(dest, src); break; 4062 default: abort(); 4063 } 4064 } 4065 4066 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src) 4067 { 4068 switch (size) { 4069 case 0: gen_helper_neon_narrow_sat_s8(dest, src); break; 4070 case 1: gen_helper_neon_narrow_sat_s16(dest, src); break; 4071 case 2: gen_helper_neon_narrow_sat_s32(dest, src); break; 4072 default: abort(); 4073 } 4074 } 4075 4076 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) 4077 { 4078 switch (size) { 4079 case 0: gen_helper_neon_narrow_sat_u8(dest, src); break; 4080 case 1: gen_helper_neon_narrow_sat_u16(dest, src); break; 4081 case 2: gen_helper_neon_narrow_sat_u32(dest, src); break; 4082 default: abort(); 4083 } 4084 } 4085 4086 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) 4087 { 4088 switch (size) { 4089 case 0: gen_helper_neon_unarrow_sat8(dest, src); break; 4090 case 1: gen_helper_neon_unarrow_sat16(dest, src); break; 4091 case 2: gen_helper_neon_unarrow_sat32(dest, src); break; 4092 default: abort(); 4093 } 4094 } 4095 4096 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, 4097 int q, int u) 4098 { 4099 if (q) { 4100 if (u) { 4101 switch (size) { 4102 case 1: gen_helper_neon_rshl_u16(var, var, shift); break; 4103 case 2: gen_helper_neon_rshl_u32(var, var, shift); break; 4104 default: abort(); 4105 } 4106 } else { 4107 switch (size) { 4108 case 1: gen_helper_neon_rshl_s16(var, var, shift); break; 4109 case 2: gen_helper_neon_rshl_s32(var, var, shift); break; 4110 default: abort(); 4111 } 4112 } 4113 } else { 4114 if (u) { 4115 switch (size) { 4116 case 1: gen_helper_neon_shl_u16(var, var, shift); break; 4117 case 2: gen_helper_neon_shl_u32(var, var, shift); break; 4118 default: abort(); 4119 } 4120 } else { 4121 switch (size) { 4122 case 1: gen_helper_neon_shl_s16(var, var, shift); break; 4123 case 2: gen_helper_neon_shl_s32(var, var, shift); break; 4124 default: abort(); 4125 } 4126 } 4127 } 4128 } 4129 4130 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u) 4131 { 4132 if (u) { 4133 switch (size) { 4134 case 0: gen_helper_neon_widen_u8(dest, src); break; 4135 case 1: gen_helper_neon_widen_u16(dest, src); break; 4136 case 2: tcg_gen_extu_i32_i64(dest, src); break; 4137 default: abort(); 4138 } 4139 } else { 4140 switch (size) { 4141 case 0: gen_helper_neon_widen_s8(dest, src); break; 4142 case 1: gen_helper_neon_widen_s16(dest, src); break; 4143 case 2: tcg_gen_ext_i32_i64(dest, src); break; 4144 default: abort(); 4145 } 4146 } 4147 tcg_temp_free_i32(src); 4148 } 4149 4150 static inline void gen_neon_addl(int size) 4151 { 4152 switch (size) { 4153 case 0: gen_helper_neon_addl_u16(CPU_V001); break; 4154 case 1: gen_helper_neon_addl_u32(CPU_V001); break; 4155 case 2: tcg_gen_add_i64(CPU_V001); break; 4156 default: abort(); 4157 } 4158 } 4159 4160 static inline void gen_neon_subl(int size) 4161 { 4162 switch (size) { 4163 case 0: gen_helper_neon_subl_u16(CPU_V001); break; 4164 case 1: gen_helper_neon_subl_u32(CPU_V001); break; 4165 case 2: tcg_gen_sub_i64(CPU_V001); break; 4166 default: abort(); 4167 } 4168 } 4169 4170 static inline void gen_neon_negl(TCGv_i64 var, int size) 4171 { 4172 switch (size) { 4173 case 0: gen_helper_neon_negl_u16(var, var); break; 4174 case 1: gen_helper_neon_negl_u32(var, var); break; 4175 case 2: gen_helper_neon_negl_u64(var, var); break; 4176 default: abort(); 4177 } 4178 } 4179 4180 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size) 4181 { 4182 switch (size) { 4183 case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break; 4184 case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break; 4185 default: abort(); 4186 } 4187 } 4188 4189 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) 4190 { 4191 TCGv_i64 tmp; 4192 4193 switch ((size << 1) | u) { 4194 case 0: gen_helper_neon_mull_s8(dest, a, b); break; 4195 case 1: gen_helper_neon_mull_u8(dest, a, b); break; 4196 case 2: gen_helper_neon_mull_s16(dest, a, b); break; 4197 case 3: gen_helper_neon_mull_u16(dest, a, b); break; 4198 case 4: 4199 tmp = gen_muls_i64_i32(a, b); 4200 tcg_gen_mov_i64(dest, tmp); 4201 tcg_temp_free_i64(tmp); 4202 break; 4203 case 5: 4204 tmp = gen_mulu_i64_i32(a, b); 4205 tcg_gen_mov_i64(dest, tmp); 4206 tcg_temp_free_i64(tmp); 4207 break; 4208 default: abort(); 4209 } 4210 4211 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters. 4212 Don't forget to clean them now. */ 4213 if (size < 2) { 4214 tcg_temp_free_i32(a); 4215 tcg_temp_free_i32(b); 4216 } 4217 } 4218 4219 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src) 4220 { 4221 if (op) { 4222 if (u) { 4223 gen_neon_unarrow_sats(size, dest, src); 4224 } else { 4225 gen_neon_narrow(size, dest, src); 4226 } 4227 } else { 4228 if (u) { 4229 gen_neon_narrow_satu(size, dest, src); 4230 } else { 4231 gen_neon_narrow_sats(size, dest, src); 4232 } 4233 } 4234 } 4235 4236 /* Symbolic constants for op fields for Neon 3-register same-length. 4237 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B 4238 * table A7-9. 4239 */ 4240 #define NEON_3R_VHADD 0 4241 #define NEON_3R_VQADD 1 4242 #define NEON_3R_VRHADD 2 4243 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */ 4244 #define NEON_3R_VHSUB 4 4245 #define NEON_3R_VQSUB 5 4246 #define NEON_3R_VCGT 6 4247 #define NEON_3R_VCGE 7 4248 #define NEON_3R_VSHL 8 4249 #define NEON_3R_VQSHL 9 4250 #define NEON_3R_VRSHL 10 4251 #define NEON_3R_VQRSHL 11 4252 #define NEON_3R_VMAX 12 4253 #define NEON_3R_VMIN 13 4254 #define NEON_3R_VABD 14 4255 #define NEON_3R_VABA 15 4256 #define NEON_3R_VADD_VSUB 16 4257 #define NEON_3R_VTST_VCEQ 17 4258 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */ 4259 #define NEON_3R_VMUL 19 4260 #define NEON_3R_VPMAX 20 4261 #define NEON_3R_VPMIN 21 4262 #define NEON_3R_VQDMULH_VQRDMULH 22 4263 #define NEON_3R_VPADD 23 4264 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */ 4265 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */ 4266 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */ 4267 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */ 4268 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */ 4269 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */ 4270 4271 static const uint8_t neon_3r_sizes[] = { 4272 [NEON_3R_VHADD] = 0x7, 4273 [NEON_3R_VQADD] = 0xf, 4274 [NEON_3R_VRHADD] = 0x7, 4275 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */ 4276 [NEON_3R_VHSUB] = 0x7, 4277 [NEON_3R_VQSUB] = 0xf, 4278 [NEON_3R_VCGT] = 0x7, 4279 [NEON_3R_VCGE] = 0x7, 4280 [NEON_3R_VSHL] = 0xf, 4281 [NEON_3R_VQSHL] = 0xf, 4282 [NEON_3R_VRSHL] = 0xf, 4283 [NEON_3R_VQRSHL] = 0xf, 4284 [NEON_3R_VMAX] = 0x7, 4285 [NEON_3R_VMIN] = 0x7, 4286 [NEON_3R_VABD] = 0x7, 4287 [NEON_3R_VABA] = 0x7, 4288 [NEON_3R_VADD_VSUB] = 0xf, 4289 [NEON_3R_VTST_VCEQ] = 0x7, 4290 [NEON_3R_VML] = 0x7, 4291 [NEON_3R_VMUL] = 0x7, 4292 [NEON_3R_VPMAX] = 0x7, 4293 [NEON_3R_VPMIN] = 0x7, 4294 [NEON_3R_VQDMULH_VQRDMULH] = 0x6, 4295 [NEON_3R_VPADD] = 0x7, 4296 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */ 4297 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */ 4298 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */ 4299 [NEON_3R_FLOAT_ACMP] = 0x5,