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