translate.c revision fed223d2bab55eda155e3463b9cb6966e69dd73c
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARM translation 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2005-2007 CodeSourcery 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2007 OpenedHand, Ltd. 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version. 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful, 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details. 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public 19a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>. 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h> 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h> 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h> 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h> 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <inttypes.h> 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h" 28852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/exec-all.h" 29cc33b2d8035092608c7cba4154e9c44452727e1bDavid 'Digit' Turner#include "disas/disas.h" 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-op.h" 31e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "qemu/log.h" 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h" 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_HELPER 1 355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h" 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T) 385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5) 395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* currently all emulated v5 cores are also v5TE, so don't bother */ 405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5) 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_5J 0 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K) 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* internal defines */ 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct DisasContext { 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong pc; 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int is_jmp; 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nonzero if this instruction has been conditionally skipped. */ 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int condjmp; 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The label that will be jumped to when the instruction is skipped. */ 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int condlabel; 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Thumb-2 condtional execution bits. */ 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int condexec_mask; 59a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine int condexec_cond; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct TranslationBlock *tb; 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int singlestep_enabled; 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int thumb; 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY) 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int user; 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int vfp_enabled; 675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int vec_len; 685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int vec_stride; 695bb450ee9cc5da0c6582e63f41c504c7861e2788David 'Digit' Turner#ifdef CONFIG_ANDROID_MEMCHECK 705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int search_pc; 71288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner#endif 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} DisasContext; 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 74288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner#include "translate-android.h" 75288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY) 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) 1 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) (s->user) 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These instructions trap after executing, so defer them until after the 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional executions state has been updated. */ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_WFI 4 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_SWI 5 865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define DISAS_SMC 6 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_ptr cpu_env; 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* We reuse the same 64-bit temporaries for efficiency. */ 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_V0, cpu_V1, cpu_M0; 915285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_R[16]; 925285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_addr; 935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_val; 945285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_high; 955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 965285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_test; 975285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_info; 985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: These should be removed. */ 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv cpu_F0s, cpu_F1s; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_F0d, cpu_F1d; 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 104852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/gen-icount.h" 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1065285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const char *regnames[] = 1075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" }; 1095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize TCG globals. */ 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid arm_translate_init(void) 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int i; 1145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (i = 0; i < 16; i++) { 1185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, 119e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, regs[i]), 1205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner regnames[i]); 1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 1225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0, 123e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, exclusive_addr), "exclusive_addr"); 1245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0, 125e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, exclusive_val), "exclusive_val"); 1265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0, 127e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, exclusive_high), "exclusive_high"); 1285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 1295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0, 130e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, exclusive_test), "exclusive_test"); 1315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0, 132e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner offsetof(CPUARMState, exclusive_info), "exclusive_info"); 1335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_cpu_offset(int offset) 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp, cpu_env, offset); 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 143e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name)) 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void store_cpu_offset(TCGv var, int offset) 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, offset); 1485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define store_cpu_field(var, name) \ 152e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner store_cpu_offset(var, offsetof(CPUARMState, name)) 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a variable to the value of a CPU register. */ 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void load_reg_var(DisasContext *s, TCGv var, int reg) 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (reg == 15) { 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr; 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* normaly, since we updated PC, we need only to add one insn */ 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb) 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = (long)s->pc + 2; 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = (long)s->pc + 4; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(var, addr); 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(var, cpu_R[reg]); 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Create a new temporary and set it to the value of a CPU register. */ 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_reg(DisasContext *s, int reg) 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load_reg_var(s, tmp, reg); 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a CPU register. The source must be a temporary and will be 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project marked as dead. */ 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void store_reg(DisasContext *s, int reg, TCGv var) 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (reg == 15) { 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, ~1); 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_JUMP; 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_R[reg], var); 1875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Value extensions. */ 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxth(var) tcg_gen_ext16u_i32(var, var) 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxth(var) tcg_gen_ext16s_i32(var, var) 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb16(var) gen_helper_sxtb16(var, var) 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb16(var) gen_helper_uxtb16(var, var) 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2005285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_set_cpsr(TCGv var, uint32_t mask) 2015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 2025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp_mask = tcg_const_i32(mask); 2030b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_cpsr_write(cpu_env, var, tmp_mask); 2045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp_mask); 2055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set NZCV flags from the high 4 bits of var. */ 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_exception(int excp) 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, excp); 2130b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_exception(cpu_env, tmp); 2145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_smul_dual(TCGv a, TCGv b) 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp1 = tcg_temp_new_i32(); 2205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16s_i32(tmp1, a); 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16s_i32(tmp2, b); 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp1, tmp1, tmp2); 2245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(a, a, 16); 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(b, b, 16); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(b, b, a); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(a, tmp1); 2295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp1); 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap each halfword. */ 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rev16(TCGv var) 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 8); 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff); 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, 8); 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, 0xff00ff00); 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 2415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap low halfword and sign extend. */ 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_revsh(TCGv var) 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(var, var); 2485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_bswap16_i32(var, var); 2495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16s_i32(var, var); 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned bitfield extract. */ 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_ubfx(TCGv var, int shift, uint32_t mask) 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, mask); 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed bitfield extract. */ 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sbfx(TCGv var, int shift, int width) 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t signbit; 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(var, var, shift); 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + width < 32) { 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project signbit = 1u << (width - 1); 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, (1u << width) - 1); 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xori_i32(var, var, signbit); 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(var, var, signbit); 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitfield insertion. Insert val into base. Clobbers base and val. */ 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask) 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(val, val, mask); 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(val, val, shift); 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(base, base, ~(mask << shift)); 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(dest, base, val); 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) + a. Mark inputs as dead */ 2855285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) 2865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 2875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp64 = tcg_temp_new_i64(); 2885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 2895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_extu_i32_i64(tmp64, b); 2905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 2915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(tmp64, tmp64, 32); 2925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i64(a, tmp64, a); 2935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 2945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 2955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return a; 2965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 2975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 2985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) - a. Mark inputs as dead. */ 2995285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) 3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp64 = tcg_temp_new_i64(); 3025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 3035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_extu_i32_i64(tmp64, b); 3045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(tmp64, tmp64, 32); 3065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i64(a, tmp64, a); 3075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 3085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 3095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return a; 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Most targets have native widening multiplication. 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project It would be good to use that instead of a full wide multiply. */ 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32x32->64 multiply. Marks inputs as dead. */ 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp1 = tcg_temp_new_i64(); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp2 = tcg_temp_new_i64(); 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp1, a); 3215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp2, b); 3235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i64(tmp1, tmp1, tmp2); 3255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp2); 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp1; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp1 = tcg_temp_new_i64(); 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp2 = tcg_temp_new_i64(); 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext_i32_i64(tmp1, a); 3355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext_i32_i64(tmp2, b); 3375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i64(tmp1, tmp1, tmp2); 3395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp2); 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp1; 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Swap low and high halfwords. */ 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_swap_half(TCGv var) 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 16); 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, 16); 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 3505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = (t0 ^ t1) & 0x8000; 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t0 &= ~0x8000; 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t1 &= ~0x8000; 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t0 = (t0 + t1) ^ tmp; 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_add16(TCGv t0, TCGv t1) 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, t0, t1); 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0x8000); 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(t0, t0, ~0x8000); 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(t1, t1, ~0x8000); 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(t0, t0, t1); 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(t0, t0, tmp); 3695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(t1); 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 373e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, CF)) 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set CF to the top bit of var. */ 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_set_CF_bit31(TCGv var) 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 31); 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_set_CF(tmp); 3815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from var. */ 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_logic_CC(TCGv var) 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 387e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, NF)); 388e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, ZF)); 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* T0 += T1 + CF. */ 3925285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_adc(TCGv t0, TCGv t1) 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 3955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, t1); 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 3975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, tmp); 3985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* dest = T0 + T1 + CF. */ 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(dest, t0, t1); 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(CF); 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(dest, dest, tmp); 4085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* dest = T0 - T1 + CF - 1. */ 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(dest, t0, t1); 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(dest, dest, tmp); 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(dest, dest, 1); 4195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Implement this natively. */ 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void shifter_out_im(TCGv var, int shift) 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) { 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, var, 1); 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, shift); 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (shift != 31) 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 1); 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_CF(tmp); 4365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Shift by immediate. Includes special handling for shift == 0. */ 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* LSL */ 4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, 32 - shift); 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, shift); 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* LSR */ 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) { 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) { 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, 31); 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_CF(var); 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(var, 0); 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* ASR */ 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 32; 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 32) 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(var, var, shift); 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* ROR/RRX */ 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(var, var, shift); break; 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp = load_cpu_field(CF); 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, 0); 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, 1); 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, 31); 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 4845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_reg(TCGv var, int shiftop, 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv shift, int flags) 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) { 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 4940b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break; 4950b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break; 4960b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break; 4970b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break; 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_shl(var, var, shift); break; 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_shr(var, var, shift); break; 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_sar(var, var, shift); break; 5045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: tcg_gen_andi_i32(shift, shift, 0x1f); 5055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotr_i32(var, var, shift); break; 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(shift); 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \ 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op2) { \ 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_pas_helper(glue(pfx,add16)); break; \ 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_pas_helper(glue(pfx,addsubx)); break; \ 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_pas_helper(glue(pfx,subaddx)); break; \ 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_pas_helper(glue(pfx,sub16)); break; \ 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_pas_helper(glue(pfx,add8)); break; \ 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: gen_pas_helper(glue(pfx,sub8)); break; \ 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_ptr tmp; 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 528e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE)); 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(s) 5305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 534e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE)); 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(u) 5365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(q); 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(sh); 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uq); 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uh); 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */ 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \ 5595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op1) { \ 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_pas_helper(glue(pfx,add8)); break; \ 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_pas_helper(glue(pfx,add16)); break; \ 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_pas_helper(glue(pfx,addsubx)); break; \ 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_pas_helper(glue(pfx,sub8)); break; \ 5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: gen_pas_helper(glue(pfx,sub16)); break; \ 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ 5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_ptr tmp; 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op2) { 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 575e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE)); 5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(s) 5775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 581e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE)); 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(u) 5835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(q); 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(sh); 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uq); 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uh); 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_test_cc(int cc, int label) 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int inv; 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (cc) { 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* eq: Z */ 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* ne: !Z */ 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* cs: C */ 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* cc: !C */ 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* mi: N */ 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(NF); 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* pl: !N */ 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(NF); 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* vs: V */ 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* vc: !V */ 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* hi: C && !Z */ 6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project inv = gen_new_label(); 6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 6475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(inv); 6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* ls: !C || Z */ 6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* ge: N == V -> N ^ V == 0 */ 6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* lt: N != V -> N ^ V != 0 */ 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* gt: !Z && N == V */ 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project inv = gen_new_label(); 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 6775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(inv); 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* le: Z || N != V */ 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "Bad condition code 0x%x\n", cc); 6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t table_logic_cc[16] = { 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* and */ 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* xor */ 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* sub */ 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* rsb */ 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* add */ 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* adc */ 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* sbc */ 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* rsc */ 7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* andl */ 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* xorl */ 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* cmp */ 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* cmn */ 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* orr */ 7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* mov */ 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* bic */ 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* mvn */ 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from an immediate address. */ 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx_im(DisasContext *s, uint32_t addr) 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb != (addr & 1)) { 7285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, addr & 1); 730e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb)); 7315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], addr & ~1); 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from var. var is marked as dead. */ 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx(DisasContext *s, TCGv var) 7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 7405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(cpu_R[15], var, ~1); 7415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(var, var, 1); 7425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(var, thumb); 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner to r15 in ARM architecture v7 and above. The source must be a temporary 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner and will be marked as dead. */ 748e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void store_reg_bx(CPUARMState *env, DisasContext *s, 7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int reg, TCGv var) 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (reg == 15 && ENABLE_ARCH_7) { 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_bx(s, var); 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, reg, var); 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing 7595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to r15 in ARM architecture v5T and above. This is used for storing 7605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the results of a LDR/LDM/POP into r15, and corresponds to the cases 7615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in the ARM ARM which use the LoadWritePC() pseudocode function. */ 762e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void store_reg_from_load(CPUARMState *env, DisasContext *s, 7635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int reg, TCGv var) 7645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 7655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (reg == 15 && ENABLE_ARCH_5) { 7665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_bx(s, var); 7675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 7685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, reg, var); 7695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 7705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 7715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 772e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void gen_smc(CPUARMState *env, DisasContext *s) 7735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 7745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], s->pc); 7755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_SMC; 7765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 7775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8s(TCGv addr, int index) 7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld8s(tmp, addr, index); 7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8u(TCGv addr, int index) 7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld8u(tmp, addr, index); 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16s(TCGv addr, int index) 7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld16s(tmp, addr, index); 7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16u(TCGv addr, int index) 7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld16u(tmp, addr, index); 8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld32(TCGv addr, int index) 8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld32u(tmp, addr, index); 8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8085285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv_i64 gen_ld64(TCGv addr, int index) 8095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 8105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp = tcg_temp_new_i64(); 8115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(tmp, addr, index); 8125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 8135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st8(TCGv val, TCGv addr, int index) 8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st8(val, addr, index); 8175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st16(TCGv val, TCGv addr, int index) 8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st16(val, addr, index); 8225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st32(TCGv val, TCGv addr, int index) 8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st32(val, addr, index); 8275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8295285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_st64(TCGv_i64 val, TCGv addr, int index) 8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(val, addr, index); 8325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(val); 8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_set_pc_im(uint32_t val) 8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], val); 8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Force a TB lookup after an instruction that changes the CPU state. */ 8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_lookup_tb(DisasContext *s) 8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], s->pc & ~1); 8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_data_offset(DisasContext *s, unsigned int insn, 8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv var) 8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int val, rm, shift, shiftop; 8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv offset; 8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 25))) { 8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xfff; 8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -val; 8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (val != 0) 8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, val); 8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* shift/register */ 8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shiftop = (insn >> 5) & 3; 8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = load_reg(s, rm); 8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_im(offset, shiftop, shift, 0); 8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(var, var, offset); 8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(var, var, offset); 8715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(offset); 8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, 8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int extra, TCGv var) 8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int val, rm; 8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv offset; 8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xf) | ((insn >> 4) & 0xf0); 8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -val; 8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += extra; 8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (val != 0) 8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, val); 8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* register */ 8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (extra) 8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, extra); 8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = load_reg(s, rm); 8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(var, var, offset); 8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(var, var, offset); 8995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(offset); 9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 90316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turnerstatic TCGv_ptr get_fpstatus_ptr(int neon) 90416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner{ 90516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr statusptr = tcg_temp_new_ptr(); 90616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner int offset; 90716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner if (neon) { 90816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner offset = offsetof(CPUARMState, vfp.standard_fp_status); 90916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } else { 91016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner offset = offsetof(CPUARMState, vfp.fp_status); 91116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 91216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_gen_addi_ptr(statusptr, cpu_env, offset); 91316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner return statusptr; 91416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner} 91516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner 9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_OP2(name) \ 9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_##name(int dp) \ 9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 91916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpst = get_fpstatus_ptr(0); \ 92016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner if (dp) { \ 92116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \ 92216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } else { \ 92316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \ 92416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } \ 92516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpst); \ 9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(add) 9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(sub) 9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(mul) 9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(div) 9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_OP2 9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9355285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_mul(int dp) 9365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 9375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Like gen_vfp_mul() but put result in F1 */ 93816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpst = get_fpstatus_ptr(0); 9395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { 94016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst); 9415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 94216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst); 9435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 9445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 9455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 9465285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_neg(int dp) 9475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 9485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Like gen_vfp_neg() but put result in F1 */ 9495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { 9505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_negd(cpu_F1d, cpu_F0d); 9515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 9525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_negs(cpu_F1s, cpu_F0s); 9535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 9545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 9555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_abs(int dp) 9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_absd(cpu_F0d, cpu_F0d); 9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_abss(cpu_F0s, cpu_F0s); 9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_neg(int dp) 9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_negd(cpu_F0d, cpu_F0d); 9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_negs(cpu_F0s, cpu_F0s); 9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_sqrt(int dp) 9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env); 9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env); 9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmp(int dp) 9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env); 9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env); 9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmpe(int dp) 9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env); 9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env); 9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_F1_ld0(int dp) 9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_F1d, 0); 10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(cpu_F1s, 0); 10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_ITOF(name) \ 10055285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \ 10065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \ 100716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr statusptr = get_fpstatus_ptr(neon); \ 10085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \ 10105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 10125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10165285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(uito) 10175285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(sito) 10185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_ITOF 10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_FTOI(name) \ 10215285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \ 10225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \ 102316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr statusptr = get_fpstatus_ptr(neon); \ 10245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \ 10265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 10285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10325285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(toui) 10335285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(touiz) 10345285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosi) 10355285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosiz) 10365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_FTOI 10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_GEN_FIX(name) \ 10395285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int shift, int neon) \ 10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 10415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp_shift = tcg_const_i32(shift); \ 104216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr statusptr = get_fpstatus_ptr(neon); \ 10435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ 10455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \ 10475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp_shift); \ 10495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosh) 10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosl) 10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(touh) 10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(toul) 10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(shto) 10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(slto) 10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(uhto) 10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(ulto) 10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_GEN_FIX 10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10615285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) 10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s)); 10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 10665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s)); 10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10695285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr) 10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s)); 10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 10745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s)); 10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long 10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvfp_reg_offset (int dp, int reg) 10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg]); 10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (reg & 1) { 10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg >> 1]) 10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project + offsetof(CPU_DoubleU, l.upper); 10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg >> 1]) 10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project + offsetof(CPU_DoubleU, l.lower); 10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the offset of a 32-bit piece of a NEON register. 10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project zero is the least significant end of the register. */ 10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long 10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectneon_reg_offset (int reg, int n) 10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int sreg; 10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sreg = reg * 2 + n; 10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return vfp_reg_offset(0, sreg); 10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv neon_load_reg(int reg, int pass) 11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); 11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void neon_store_reg(int reg, int pass, TCGv var) 11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); 11115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_load_reg64(TCGv_i64 var, int reg) 11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); 11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_store_reg64(TCGv_i64 var, int reg) 11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); 11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f32 tcg_gen_ld_i32 11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f64 tcg_gen_ld_i64 11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f32 tcg_gen_st_i32 11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f64 tcg_gen_st_i64 11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F0_vreg(int dp, int reg) 11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F1_vreg(int dp, int reg) 11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg)); 11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg)); 11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_vreg_F0(int dp, int reg) 11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARM_CP_RW_BIT (1 << 20) 11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_load_reg(TCGv_i64 var, int reg) 11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1157e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg])); 11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_store_reg(TCGv_i64 var, int reg) 11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1162e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg])); 11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv iwmmxt_load_creg(int reg) 11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv var = tcg_temp_new_i32(); 1168e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg])); 11695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return var; 11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11725285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void iwmmxt_store_creg(int reg, TCGv var) 11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1174e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg])); 11755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_wRn_M0(int rn) 11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_store_reg(cpu_M0, rn); 11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_M0_wRn(int rn) 11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_M0, rn); 11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_orq_M0_wRn(int rn) 11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1); 11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_andq_M0_wRn(int rn) 11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1); 11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_xorq_M0_wRn(int rn) 12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1); 12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IWMMXT_OP(name) \ 12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \ 12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); \ 12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \ 12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1213c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV(name) \ 1214c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turnerstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \ 1215c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner{ \ 1216c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner iwmmxt_load_reg(cpu_V1, rn); \ 1217c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \ 1218c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner} 1219c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1220c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV_SIZE(name) \ 1221c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##b) \ 1222c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##w) \ 1223c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##l) 12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1225c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV1(name) \ 12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0(void) \ 12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 1228c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \ 12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(maddsq) 12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(madduq) 12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadb) 12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadw) 12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulslw) 12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulshw) 12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mululw) 12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(muluhw) 12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macsw) 12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macuw) 12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1242c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(unpackl) 1243c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(unpackh) 1244c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1245c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklub) 1246c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackluw) 1247c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklul) 1248c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhub) 1249c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhuw) 1250c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhul) 1251c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsb) 1252c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsw) 1253c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsl) 1254c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsb) 1255c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsw) 1256c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsl) 1257c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1258c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpeq) 1259c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpgtu) 1260c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpgts) 1261c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1262c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(mins) 1263c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(minu) 1264c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(maxs) 1265c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(maxu) 1266c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1267c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subn) 1268c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(addn) 1269c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subu) 1270c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(addu) 1271c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subs) 1272c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(adds) 1273c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner 1274c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgb0) 1275c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgb1) 1276c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgw0) 1277c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgw1) 12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(msadb) 12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1281c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packuw) 1282c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packul) 1283c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packuq) 1284c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsw) 1285c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsl) 1286c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsq) 12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_mup(void) 12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, 2); 12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_cup(void) 12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, 1); 13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_setpsr_nz(void) 13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0); 13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]); 13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_addl_M0_wRn(int rn) 13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext32u_i64(cpu_V1, cpu_V1); 13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13185285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) 13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd; 13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t offset; 13225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 13255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) << ((insn >> 7) & 2); 13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Pre indexed */ 13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 13315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, offset); 13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, -offset); 13345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 13365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 13375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 13385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Post indexed */ 13415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 13435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, offset); 13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, -offset); 13465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (!(insn & (1 << 23))) 13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13525285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest) 13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd = (insn >> 0) & 0xf; 13555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 8)) { 13585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) { 13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 13605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 13615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(rd); 13625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 13635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 13645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 13655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, rd); 13665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_V0); 13675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 13685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, mask); 13695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred 13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 1376e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn) 13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, wrd; 13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rdhi, rdlo, rd0, rd1, i; 13805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 13815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2, tmp3; 13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0e000e00) == 0x0c000000) { 13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00ff0) == 0x0c400000) { 13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = insn & 0xf; 13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdlo = (insn >> 12) & 0xf; 13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdhi = (insn >> 16) & 0xf; 13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { /* TMRRC */ 13895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, wrd); 13905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 13915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 13925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* TMCRR */ 13945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 13955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_reg(cpu_V0, wrd); 13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 14025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 14035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_address(s, insn, addr)) { 14045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 28) == 0xf) { /* WLDRW wCx */ 14095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 14105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); 14115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = 1; 14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WLDRD */ 14165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s)); 14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = 0; 14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WLDRW wRd */ 14195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WLDRH */ 14235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WLDRB */ 14255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i) { 14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(cpu_M0, tmp); 14305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 28) == 0xf) { /* WSTRW wCx */ 14365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 14375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 14405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WSTRD */ 14435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 14445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s)); 14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WSTRW wRd */ 14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WSTRH */ 14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WSTRB */ 14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f000000) != 0x0e000000) 14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) { 14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x000: /* WOR */ 14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_orq_M0_wRn(rd1); 14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x011: /* TMCR */ 14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (wrd) { 14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCID: 14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCASF: 14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCon: 14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCSSF: 14925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 14935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd); 14945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 14955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 14965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR0: 14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR1: 15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR2: 15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR3: 15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 15045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x100: /* WXOR */ 15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_xorq_M0_wRn(rd1); 15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x111: /* TMRC */ 15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 15265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 15275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x300: /* WANDN */ 15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_neg_i64(cpu_M0, cpu_M0); 15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_andq_M0_wRn(rd1); 15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x200: /* WAND */ 15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_andq_M0_wRn(rd1); 15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x810: case 0xa10: /* WMADD */ 15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maddsq_M0_wRn(rd1); 15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_madduq_M0_wRn(rd1); 15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */ 15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklb_M0_wRn(rd1); 15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklw_M0_wRn(rd1); 15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackll_M0_wRn(rd1); 15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */ 15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhb_M0_wRn(rd1); 15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhw_M0_wRn(rd1); 15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhl_M0_wRn(rd1); 16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */ 16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) 16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_sadw_M0_wRn(rd1); 16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_sadb_M0_wRn(rd1); 16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 20))) 16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addl_M0_wRn(wrd); 16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */ 16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mulshw_M0_wRn(rd1); 16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mulslw_M0_wRn(rd1); 16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_muluhw_M0_wRn(rd1); 16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mululw_M0_wRn(rd1); 16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */ 16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_macsw_M0_wRn(rd1); 16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_macuw_M0_wRn(rd1); 16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 20))) { 16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, wrd); 16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */ 16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeqb_M0_wRn(rd1); 16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeqw_M0_wRn(rd1); 16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeql_M0_wRn(rd1); 16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */ 16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgw1_M0_wRn(rd1); 16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgw0_M0_wRn(rd1); 16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgb1_M0_wRn(rd1); 16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgb0_M0_wRn(rd1); 16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */ 17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 17045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3)); 17055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 7); 17065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V1, rd1); 17075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 17085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */ 17135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 6) & 3) == 3) 17145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 17175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xff); 17225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 7) << 3); 17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xffff); 17265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 3) << 4); 17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xffffffff); 17305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 1) << 5); 17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 17335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp2); 17345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp3); 17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3); 17375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp3); 17385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 17395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */ 17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 17465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd == 15 || ((insn >> 22) & 3) == 3) 17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 17495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3); 17535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & 8) { 17555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext8s_i32(tmp, tmp); 17565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 17575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xff); 17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4); 17625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & 8) { 17645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16s_i32(tmp, tmp); 17655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 17665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xffff); 17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5); 17715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */ 17775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3) 17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 17795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0); 17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4); 17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12); 17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp, tmp, 28); 17925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 17935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */ 17965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 6) & 3) == 3) 17975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 18005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstb(cpu_M0, tmp); 18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstw(cpu_M0, tmp); 18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstl(cpu_M0, tmp); 18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */ 18175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 18205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 18215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 7; i ++) { 18255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 4); 18265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 3; i ++) { 18315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 8); 18325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 18375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 18415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 18425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */ 18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0); 18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0); 18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0); 18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */ 18655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 18685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 18695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 7; i ++) { 18735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 4); 18745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 3; i ++) { 18795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 8); 18805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 18855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 18895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 18905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */ 18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 18955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3) 18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 18985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbb(tmp, cpu_M0); 19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbw(tmp, cpu_M0); 19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbl(tmp, cpu_M0); 19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */ 19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x906: case 0xb06: case 0xd06: case 0xf06: 19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1); 19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtub_M0_wRn(rd1); 19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1); 19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1); 19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1); 19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtul_M0_wRn(rd1); 19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */ 19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e: 19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsb_M0(); 19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklub_M0(); 19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsw_M0(); 19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackluw_M0(); 19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsl_M0(); 19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklul_M0(); 19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */ 19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c: 19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsb_M0(); 19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhub_M0(); 19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsw_M0(); 19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhuw_M0(); 19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsl_M0(); 19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhul_M0(); 19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */ 20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x214: case 0x614: case 0xa14: case 0xe14: 20085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 2020c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp); 20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 2023c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp); 20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 2026c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp); 20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */ 20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x014: case 0x414: case 0x814: case 0xc14: 20365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 2048c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp); 20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 2051c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp); 20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 2054c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp); 20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */ 20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x114: case 0x514: case 0x914: case 0xd14: 20645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 2076c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp); 20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 2079c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp); 20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 2082c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp); 20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */ 20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x314: case 0x714: case 0xb14: case 0xf14: 20925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xf, tmp)) { 21015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 2104c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp); 21058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0x1f, tmp)) { 21085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 2111c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp); 21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0x3f, tmp)) { 21155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 2118c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp); 21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */ 21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x916: case 0xb16: case 0xd16: case 0xf16: 21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsb_M0_wRn(rd1); 21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minub_M0_wRn(rd1); 21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsw_M0_wRn(rd1); 21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minuw_M0_wRn(rd1); 21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsl_M0_wRn(rd1); 21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minul_M0_wRn(rd1); 21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */ 21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x816: case 0xa16: case 0xc16: case 0xe16: 21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsb_M0_wRn(rd1); 21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxub_M0_wRn(rd1); 21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsw_M0_wRn(rd1); 21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxuw_M0_wRn(rd1); 21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsl_M0_wRn(rd1); 21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxul_M0_wRn(rd1); 21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */ 21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x402: case 0x502: case 0x602: case 0x702: 21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32((insn >> 20) & 3); 21955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V1, rd1); 21965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 21975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp); 21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */ 22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x41a: case 0x51a: case 0x61a: case 0x71a: 22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x81a: case 0x91a: case 0xa1a: case 0xb1a: 22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a: 22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 0xf) { 22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnb_M0_wRn(rd1); 22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subub_M0_wRn(rd1); 22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsb_M0_wRn(rd1); 22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnw_M0_wRn(rd1); 22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subuw_M0_wRn(rd1); 22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsw_M0_wRn(rd1); 22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: 22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnl_M0_wRn(rd1); 22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: 22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subul_M0_wRn(rd1); 22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsl_M0_wRn(rd1); 22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */ 22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x41e: case 0x51e: case 0x61e: case 0x71e: 22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x81e: case 0x91e: case 0xa1e: case 0xb1e: 22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e: 22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f)); 2252c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp); 22535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp); 22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */ 22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x418: case 0x518: case 0x618: case 0x718: 22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x818: case 0x918: case 0xa18: case 0xb18: 22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc18: case 0xd18: case 0xe18: case 0xf18: 22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 0xf) { 22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnb_M0_wRn(rd1); 22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addub_M0_wRn(rd1); 22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsb_M0_wRn(rd1); 22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnw_M0_wRn(rd1); 22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_adduw_M0_wRn(rd1); 22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsw_M0_wRn(rd1); 22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: 22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnl_M0_wRn(rd1); 22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: 22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addul_M0_wRn(rd1); 22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsl_M0_wRn(rd1); 22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */ 23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x408: case 0x508: case 0x608: case 0x708: 23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x808: case 0x908: case 0xa08: case 0xb08: 23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc08: case 0xd08: case 0xe08: case 0xf08: 23055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0) 23065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsw_M0_wRn(rd1); 23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packuw_M0_wRn(rd1); 23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsl_M0_wRn(rd1); 23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packul_M0_wRn(rd1); 23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsq_M0_wRn(rd1); 23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packuq_M0_wRn(rd1); 23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x201: case 0x203: case 0x205: case 0x207: 23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x209: case 0x20b: case 0x20d: case 0x20f: 23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x211: case 0x213: case 0x215: case 0x217: 23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x219: case 0x21b: case 0x21d: case 0x21f: 23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 5) & 0xf; 23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 12) & 0xf; 23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd0 == 0xf || rd1 == 0xf) 23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 23455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd0); 23465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd1); 23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 16) & 0xf) { 23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* TMIA */ 23495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* TMIAPH */ 23525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */ 23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) 23565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) 23585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp2, tmp2, 16); 23595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 23625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 23635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 23675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred 23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 2380e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn) 23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int acc, rd0, rd1, rdhi, rdlo; 23835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0ff00f10) == 0x0e200010) { 23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Multiply with Internal Accumulate Format */ 23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 12) & 0xf; 23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = insn & 0xf; 23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acc = (insn >> 5) & 7; 23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (acc != 0) 23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd0); 23955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd1); 23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 16) & 0xf) { 23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* MIA */ 23985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* MIAPH */ 24015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: /* MIABB */ 24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: /* MIABT */ 24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* MIATB */ 24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: /* MIATT */ 24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) 24085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) 24105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp2, tmp2, 16); 24115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 24175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(acc); 24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00ff8) == 0x0c400000) { 24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Internal Accumulator Access Format */ 24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdhi = (insn >> 16) & 0xf; 24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdlo = (insn >> 12) & 0xf; 24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acc = insn & 7; 24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (acc != 0) 24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { /* MRA */ 24335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, acc); 24345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 24355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 24365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 24375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1); 24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* MAR */ 24395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 24405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_reg(cpu_V0, acc); 24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor instruction. Return nonzero if 24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is not defined. */ 2450e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp_insn(CPUARMState *env, DisasContext *s, uint32_t insn) 24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 24525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd = (insn >> 12) & 0xf; 24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t cp = (insn >> 8) & 0xf; 24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!env->cp[cp].cp_read) 24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 24605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 24615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 24625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_cp(tmp, cpu_env, tmp2); 24635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 24648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 24658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!env->cp[cp].cp_write) 24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 24705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 24715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_cp(cpu_env, tmp2, tmp); 24725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 24735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2478d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turnerstatic int cp15_user_ok(CPUARMState *env, uint32_t insn) 24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpn = (insn >> 16) & 0xf; 24818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpm = insn & 0xf; 24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2484d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) { 2485d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner /* Performance monitor registers fall into three categories: 2486d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner * (a) always UNDEF in usermode 2487d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner * (b) UNDEF only if PMUSERENR.EN is 0 2488d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner * (c) always read OK and UNDEF on write (PMUSERENR only) 2489d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner */ 2490d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner if ((cpm == 12 && (op < 6)) || 2491d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner (cpm == 13 && (op < 3))) { 2492d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner return env->cp15.c9_pmuserenr; 2493d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) { 2494d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner /* PMUSERENR, read only */ 2495d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner return 1; 2496d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner } 2497d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner return 0; 2498d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner } 2499d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner 25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cpn == 13 && cpm == 0) { 25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* TLS register. */ 25028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT))) 25038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 25068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2508e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int cp15_tls_load_store(CPUARMState *env, DisasContext *s, uint32_t insn, uint32_t rd) 25095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 25105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 25115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int cpn = (insn >> 16) & 0xf; 25125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int cpm = insn & 0xf; 25135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 25145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V6K)) 25165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(cpn == 13 && cpm == 0)) 25195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & ARM_CP_RW_BIT) { 25225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 25235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 25245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls1); 25255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 25275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls2); 25285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 25305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls3); 25315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 25335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 25365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 25385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 25395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 25405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 25415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls1); 25425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 25445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls2); 25455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 25475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls3); 25485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 25505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 25515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 25555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 25565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor (cp15) instruction. Return nonzero if 25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is not defined. */ 2559e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp15_insn(CPUARMState *env, DisasContext *s, uint32_t insn) 25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd; 25625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* M profile cores use memory mapped registers instead of cp15. */ 25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_M)) 25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 25)) == 0) { 25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mrrc */ 25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mcrr. Used for block cache operations, so implement as no-op. */ 25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 4)) == 0) { 25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* cdp */ 25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 258060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner /* We special case a number of cp15 instructions which were used 258160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner * for things which are real instructions in ARMv7. This allows 258260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner * them to work in linux-user mode which doesn't provide functional 258360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner * get_cp15/set_cp15 helpers, and is more efficient anyway. 25845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 258560148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner switch ((insn & 0x0fff0fff)) { 258660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070f90: 25875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores). 25885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * In v7, this must NOP. 25895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 259060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner if (IS_USER(s)) { 259160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner return 1; 259260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner } 25935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7)) { 25945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Wait for interrupt. */ 25955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc); 25965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_WFI; 25975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 259960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070f58: 26005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI, 26015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * so this is slightly over-broad. 26025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 260360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) { 26045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Wait for interrupt. */ 26055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc); 26065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_WFI; 26075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 26085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 260960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner /* Otherwise continue to handle via helper function. 26105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * In particular, on v7 and some v6 cores this is one of 26115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the VA-PA registers. 26125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 261360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner break; 261460148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070f3d: 261560148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */ 261660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_V6)) { 261760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner return IS_USER(s) ? 1 : 0; 261860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner } 261960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner break; 262060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070f95: /* 0,c7,c5,4 : ISB */ 262160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070f9a: /* 0,c7,c10,4: DSB */ 262260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner case 0x0e070fba: /* 0,c7,c10,5: DMB */ 262360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner /* Barriers in both v6 and v7 */ 262460148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_V6)) { 262560148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner return 0; 262660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner } 262760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner break; 262860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner default: 262960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner break; 263060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner } 263160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner 263260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner if (IS_USER(s) && !cp15_user_ok(env, insn)) { 263360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner return 1; 26345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 26355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 26375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (cp15_tls_load_store(env, s, insn, rd)) 26395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 26405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 26435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 26445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_cp15(tmp, cpu_env, tmp2); 26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If the destination register is r15 then sets condition codes. */ 26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) 26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 26495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 26525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_cp15(cpu_env, tmp2, tmp); 26535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Normally we would always end the TB here, but Linux 26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * arch/arm/mach-pxa/sleep.S expects two instructions following 26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * an MMU enable to execute from cache. Imitate this behaviour. */ 26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_XSCALE) || 26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (insn & 0x0fff0fff) != 0x0e010f10) 26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 26615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n)) 26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG(insn, bigbit, smallbit) \ 26678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1)) 26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG(reg, insn, bigbit, smallbit) do { \ 26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_VFP3)) { \ 26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project reg = (((insn) >> (bigbit)) & 0x0f) \ 26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (((insn) >> ((smallbit) - 4)) & 0x10); \ 26728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { \ 26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << (smallbit))) \ 26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; \ 26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project reg = ((insn) >> (bigbit)) & 0x0f; \ 26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }} while (0) 26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22) 26798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22) 26808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7) 26818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7) 26828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) 26838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) 26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Move between integer and VFP cores. */ 26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv gen_vfp_mrs(void) 26878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 26898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(tmp, cpu_F0s); 26908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 26918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_vfp_msr(TCGv tmp) 26948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(cpu_F0s, tmp); 26965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_u8(TCGv var, int shift) 27008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 27015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 27028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 27038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 27048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext8u_i32(var, var); 27058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 8); 27068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 27078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 16); 27088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 27095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 27108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 27118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_low16(TCGv var) 27138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 27145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 27158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(var, var); 27168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 16); 27178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 27185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 27198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 27208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_high16(TCGv var) 27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 27235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 27248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, 0xffff0000); 27258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 16); 27268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 27275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 27285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 27295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 27305285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size) 27315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 27325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Load a single Neon element and replicate into a 32 bit TCG reg */ 27335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 27345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 27355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 27365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 27375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_u8(tmp, 0); 27385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 27405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 27415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 27425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 27445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 27455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: /* Avoid compiler warnings. */ 27475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 27485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 27495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 27518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble a VFP instruction. Returns nonzero if an error occurred 27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 2754e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn) 27558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; 27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int dp, veclen; 27585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP)) 27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) { 27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */ 27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00fff) != 0x0ee00a10) 27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC 27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) 27728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dp = ((insn & 0xf00) == 0xb00); 27758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 24) & 0xf) { 27768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 27778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 27788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* single register transfer */ 27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 27818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 27828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 27838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 27858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 27868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x00c00060 27888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && !arm_feature(env, ARM_FEATURE_NEON)) 27898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pass = (insn >> 21) & 1; 27928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 27938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 0; 27948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn >> 5) & 3) * 8; 27958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 5)) { 27968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 1; 27978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & (1 << 6)) ? 16 : 0; 27988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 2; 28008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 28018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 28038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 28048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, pass); 28058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 28068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 28078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 28088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, offset); 28098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 28108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_uxtb(tmp); 28118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 28128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxtb(tmp); 28138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 28158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 28168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 28178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, 16); 28188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_uxth(tmp); 28208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 28238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, 16); 28248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp); 28268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 28308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 28338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 28358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 28368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 28378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VDUP */ 28388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 28398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_dup_u8(tmp, 0); 28408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (size == 1) { 28418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_dup_low16(tmp); 28428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (n = 0; n <= pass * 2; n++) { 28445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 28455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 28465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rn, n, tmp2); 28475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 28485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rn, n, tmp); 28498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMOV */ 28518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 28528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 28538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rn, pass); 28548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, offset, 0xff); 28555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 28568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 28588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rn, pass); 28598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, offset, 0xffff); 28605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 28618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 28638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rn, pass, tmp); 28668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* !dp */ 28698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x6f) != 0x00) 28708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = VFP_SREG_N(insn); 28728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 28738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 28748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 28758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* system register */ 28768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn >>= 1; 28778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 28798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSID: 28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VFP2 allows access to FSID from userspace. 28818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP3 restricts all id registers to privileged 28828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project accesses. */ 28838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) 28848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && arm_feature(env, ARM_FEATURE_VFP3)) 28858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 28878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPEXC: 28898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST: 28948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST2: 28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not present in VFP3. */ 28968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) 28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || arm_feature(env, ARM_FEATURE_VFP3)) 28988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 29008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSCR: 29028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == 15) { 29038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]); 29048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xf0000000); 29058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 29078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_get_fpscr(tmp, cpu_env); 29088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR0: 29118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR1: 29128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) 29138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || !arm_feature(env, ARM_FEATURE_VFP3)) 29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 29168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 29188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rn); 29228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 29238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == 15) { 29258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Set the 4 flag bits in the CPSR. */ 29268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_nzcv(tmp); 29275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 29288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 29308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 29338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 29348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 29358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn >>= 1; 29368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* system register */ 29378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 29388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSID: 29398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR0: 29408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR1: 29418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Writes are ignored. */ 29428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSCR: 29448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_set_fpscr(cpu_env, tmp); 29455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 29468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 29478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPEXC: 29498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 29508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* TODO: VFP subarchitecture support. 29525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * For now, keep the EN bit only */ 29535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 1 << 30); 29548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, vfp.xregs[rn]); 29558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 29568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST: 29588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST2: 29598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, vfp.xregs[rn]); 29608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 29628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 29668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rn); 29678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing */ 29728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The opcode is in bits 23, 21, 20 and 6. */ 29738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1); 29748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 29758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 29768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rn is opcode */ 29778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 29788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rn is register number */ 29808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 29818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) { 29848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Integer or single precision destination. */ 29858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 29868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 29888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 15 && 29905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) { 29915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VCVT from int is always from S reg regardless of dp bit. 29925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * VCVT with immediate frac_bits has same format as SREG_M 29935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 29945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rm = VFP_SREG_M(insn); 29958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 29978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = VFP_SREG_N(insn); 30008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && rn == 15) { 30018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Double precision destination. */ 30028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 30038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 30058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* NB that we implicitly rely on the encoding for the frac_bits 30075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in VCVT of fixed to float being the same as that of an SREG_M 30085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 30098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = VFP_SREG_M(insn); 30108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner veclen = s->vec_len; 30138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && rn > 3) 30148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen = 0; 30158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shut up compiler warnings. */ 30178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = 0; 30188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_d = 0; 30198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0; 30208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (veclen > 0) { 30228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 30238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0xc; 30248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 30258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0x18; 30268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Figure out what type of vector operation this is. */ 30288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((rd & bank_mask) == 0) { 30298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* scalar */ 30308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen = 0; 30318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 30335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner delta_d = (s->vec_stride >> 1) + 1; 30348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 30355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner delta_d = s->vec_stride + 1; 30368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((rm & bank_mask) == 0) { 30388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mixed scalar/vector */ 30398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = 0; 30408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vector */ 30428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = delta_d; 30438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load the initial operands. */ 30488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 30498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 30508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 16: 30518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 17: 30528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Integer source */ 30538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm); 30548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: 30568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: 30578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Compare */ 30588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 30608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 30628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 30638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Compare with zero */ 30648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_F1_ld0(dp); 30668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 20: 30688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 21: 30698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 22: 30708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 23: 30715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 28: 30725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 29: 30735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 30: 30745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 31: 30758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Source and destination the same. */ 30768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 3078cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner case 4: 3079cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner case 5: 3080cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner case 6: 3081cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner case 7: 3082cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner /* VCVTB, VCVTT: only present with the halfprec extension, 3083cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner * UNPREDICTABLE if bit 8 is set (we choose to UNDEF) 3084cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner */ 3085cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) { 3086cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner return 1; 3087cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner } 3088cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner /* Otherwise fall through */ 30898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 30908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One source operand. */ 30918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rm); 30928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two source operands. */ 30968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rn); 30978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 30988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 31008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (;;) { 31018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Perform the calculation. */ 31028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 31035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: /* VMLA: fd + (fn * fm) */ 31045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that order of inputs to the add matters for NaNs */ 31055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_mul(dp); 31065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 31078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 31088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: /* VMLS: fd + -(fn * fm) */ 31108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 31115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_neg(dp); 31125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 31138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 31148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* VNMLS: -fd + (fn * fm) */ 31165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that it isn't valid to replace (-A + B) with (B - A) 31175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * or similar plausible looking simplifications 31185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * because this will give wrong results for NaNs. 31195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 31205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_mul(dp); 31215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 31225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_neg(dp); 31235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_add(dp); 31248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: /* VNMLA: -fd + -(fn * fm) */ 31268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 31275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_neg(dp); 31285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 31298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 31305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_add(dp); 31318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* mul: fn * fm */ 31338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 31348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* nmul: -(fn * fm) */ 31368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 31378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 31388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* add: fn + fm */ 31408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 31418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* sub: fn - fm */ 31438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_sub(dp); 31448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* div: fn / fm */ 31468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_div(dp); 31478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* fconst */ 31498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 31508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 31518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 31528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (insn << 12) & 0x80000000; 31538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn >> 12) & 0x70) | (insn & 0xf); 31548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 31558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i & 0x40) 31568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x3f80; 31578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 31588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x4000; 31598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n |= i << 16; 31608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32); 31618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 31628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i & 0x40) 31638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x780; 31648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 31658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x800; 31668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n |= i << 19; 31678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(cpu_F0s, n); 31688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 31698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* extension space */ 31718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 31728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* cpy */ 31738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 31748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* abs */ 31768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_abs(dp); 31778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* neg */ 31798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 31808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* sqrt */ 31828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_sqrt(dp); 31838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: /* vcvtb.f32.f16 */ 31855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_vfp_mrs(); 31865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp, tmp); 31875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 31885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 31895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: /* vcvtt.f32.f16 */ 31915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_vfp_mrs(); 31925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 31935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 31945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 31955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* vcvtb.f16.f32 */ 31975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 31985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 31995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(0, rd); 32005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = gen_vfp_mrs(); 32015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 32025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 32035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 32045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_msr(tmp); 32055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 32065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* vcvtt.f16.f32 */ 32075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 32085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 32095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp, tmp, 16); 32105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(0, rd); 32115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = gen_vfp_mrs(); 32125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp2, tmp2); 32135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 32145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 32155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_msr(tmp); 32165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 32178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* cmp */ 32188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmp(dp); 32198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* cmpe */ 32218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmpe(dp); 32228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* cmpz */ 32248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmp(dp); 32258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* cmpez */ 32278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_F1_ld0(dp); 32288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmpe(dp); 32298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* single<->double conversion */ 32318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 32328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env); 32338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 32348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env); 32358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 16: /* fuito */ 32375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uito(dp, 0); 32388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 17: /* fsito */ 32405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_sito(dp, 0); 32418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 20: /* fshto */ 32438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_shto(dp, 16 - rm, 0); 32468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 21: /* fslto */ 32488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_slto(dp, 32 - rm, 0); 32518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 22: /* fuhto */ 32538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uhto(dp, 16 - rm, 0); 32568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 23: /* fulto */ 32588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ulto(dp, 32 - rm, 0); 32618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 24: /* ftoui */ 32635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toui(dp, 0); 32648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 25: /* ftouiz */ 32665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touiz(dp, 0); 32678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 26: /* ftosi */ 32695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosi(dp, 0); 32708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 27: /* ftosiz */ 32725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosiz(dp, 0); 32738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 28: /* ftosh */ 32758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosh(dp, 16 - rm, 0); 32788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 29: /* ftosl */ 32808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosl(dp, 32 - rm, 0); 32838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 30: /* ftouh */ 32858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touh(dp, 16 - rm, 0); 32888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 31: /* ftoul */ 32908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toul(dp, 32 - rm, 0); 32938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* undefined */ 32958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project printf ("rn:%d\n", rn); 32968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* undefined */ 33008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project printf ("op:%d\n", op); 33018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 33028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Write back the result. */ 33058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && (rn >= 8 && rn <= 11)) 33068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ; /* Comparison, do nothing. */ 33075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else if (op == 15 && dp && ((rn & 0x1c) == 0x18)) 33085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VCVT double to int: always integer result. */ 33098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rd); 33108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (op == 15 && rn == 15) 33118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* conversion */ 33128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(!dp, rd); 33138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 33148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 33158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* break out of the loop if we have finished */ 33178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (veclen == 0) 33188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 33198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && delta_m == 0) { 33218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* single source one-many */ 33228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (veclen--) { 33238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = ((rd + delta_d) & (bank_mask - 1)) 33248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rd & bank_mask); 33258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 33268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 33288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Setup the next operands. */ 33308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen--; 33318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = ((rd + delta_d) & (bank_mask - 1)) 33328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rd & bank_mask); 33338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 33358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One source operand. */ 33368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = ((rm + delta_m) & (bank_mask - 1)) 33378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rm & bank_mask); 33388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rm); 33398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two source operands. */ 33418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = ((rn + delta_d) & (bank_mask - 1)) 33428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rn & bank_mask); 33438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rn); 33448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (delta_m) { 33458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = ((rm + delta_m) & (bank_mask - 1)) 33468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rm & bank_mask); 33478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 33488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 33538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 33548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: 33555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x03e00000) == 0x00400000) { 33568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* two-register transfer */ 33578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 33588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 33598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 33618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = VFP_SREG_M(insn); 33638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 33668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 33678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm * 2); 33698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 33718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm * 2 + 1); 33728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp); 33748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm); 33768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 33788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm + 1); 33798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, tmp); 33818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 33848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 33868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm * 2); 33888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 33898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm * 2 + 1); 33918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 33938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm); 33955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 33968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm + 1); 33988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store */ 34028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 34038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 34048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 34058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 34078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x01200000) == 0x01000000) { 34088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Single load/store */ 34098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) << 2; 34108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) 34118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset; 341297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (s->thumb && rn == 15) { 341397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner /* This is actually UNPREDICTABLE */ 341497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner addr = tcg_temp_new_i32(); 341597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner tcg_gen_movi_i32(addr, s->pc & ~2); 341697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } else { 341797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner addr = load_reg(s, rn); 341897c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } 34195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 34208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 34215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ld(s, dp, addr); 34228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 34238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 34255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_st(s, dp, addr); 34268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 34288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple */ 343097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner int w = insn & (1 << 21); 34318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 34328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (insn >> 1) & 0x7f; 34338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = insn & 0xff; 34358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 343697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) { 343797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner /* P == U , W == 1 => UNDEF */ 343897c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner return 1; 343997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } 344097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (n == 0 || (rd + n) > 32 || (dp && n > 16)) { 344197c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner /* UNPREDICTABLE cases for bad immediates: we choose to 344297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner * UNDEF to avoid generating huge numbers of TCG ops 344397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner */ 344497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner return 1; 344597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } 344697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (rn == 15 && w) { 344797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */ 344897c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner return 1; 344997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } 345097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner 345197c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (s->thumb && rn == 15) { 345297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner /* This is actually UNPREDICTABLE */ 345397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner addr = tcg_temp_new_i32(); 345497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner tcg_gen_movi_i32(addr, s->pc & ~2); 345597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } else { 345697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner addr = load_reg(s, rn); 345797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner } 34588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) /* pre-decrement */ 34595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); 34608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 34628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 8; 34638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 34655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(offset); 34668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < n; i++) { 34678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 34688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 34695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ld(s, dp, addr); 34708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd + i); 34718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 34738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd + i); 34745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_st(s, dp, addr); 34758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp); 34778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 347997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner if (w) { 34808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* writeback */ 34818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 34828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset * n; 34838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (dp && (insn & 1)) 34848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 34858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 34878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset != 0) 34895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 34905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, addr); 34915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 34925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 34938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 34978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 34988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never happen. */ 34998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 35008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 35018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 35028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) 35058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TranslationBlock *tb; 35078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb = s->tb; 35098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { 35108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_goto_tb(n); 35118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dest); 35125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_exit_tb((tcg_target_long)tb + n); 35138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 35148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dest); 35158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_exit_tb(0); 35168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 35178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_jmp (DisasContext *s, uint32_t dest) 35208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(s->singlestep_enabled)) { 35228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* An indirect jump so that we still trigger the debug exception. */ 35238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb) 35248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dest |= 1; 35258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, dest); 35268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 35278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(s, 0, dest); 35288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_TB_JUMP; 35298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 35308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y) 35338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (x) 35358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(t0, t0, 16); 35368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 35378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(t0); 35388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (y) 35398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(t1, t1, 16); 35408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 35418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(t1); 35428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(t0, t0, t1); 35438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the mask of PSR bits set by a MSR instruction. */ 3546e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) { 35478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t mask; 35488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask = 0; 35508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 0)) 35518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff; 35528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 1)) 35538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff00; 35548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 2)) 35558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff0000; 35568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 3)) 35578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff000000; 35588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out undefined bits. */ 35608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_RESERVED; 35615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V4T)) 35625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask &= ~CPSR_T; 35635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V5)) 35645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask &= ~CPSR_Q; /* V5TE in reality*/ 35658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_V6)) 35668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~(CPSR_E | CPSR_GE); 35678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_THUMB2)) 35688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_IT; 35698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out execution state bits. */ 35708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!spsr) 35718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_EXEC; 35728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out privileged bits. */ 35738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 35748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= CPSR_USER; 35758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return mask; 35768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ 35795285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) 35808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 35828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (spsr) { 35838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This is also undefined in system mode. */ 35848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 35858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 35868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 35888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, ~mask); 35895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(t0, t0, mask); 35905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, t0); 35918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, spsr); 35928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 35935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_cpsr(t0, mask); 35948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 35955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(t0); 35968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 35978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 35988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. */ 36015285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val) 36025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 36035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 36045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 36055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, val); 36065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return gen_set_psr(s, mask, spsr, tmp); 36075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 36085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 36095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Generate an old-style exception return. Marks pc as dead. */ 36105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_exception_return(DisasContext *s, TCGv pc) 36118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 36135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, 15, pc); 36148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 36158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(tmp, 0xffffffff); 36165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 36178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 36188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate a v6 exception return. Marks both values as dead. */ 36218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) 36228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(cpsr, 0xffffffff); 36245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(cpsr); 36258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 15, pc); 36268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 36278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void 36308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgen_set_condexec (DisasContext *s) 36318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3632a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (s->condexec_mask) { 3633a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); 36345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3635a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine tcg_gen_movi_i32(tmp, val); 3636a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine store_cpu_field(tmp, condexec_bits); 3637a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine } 36385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 36395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 36405285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_exception_insn(DisasContext *s, int offset, int excp) 36415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 36425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_condexec(s); 36435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc - offset); 36445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(excp); 36455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_JUMP; 36468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_nop_hint(DisasContext *s, int val) 36498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (val) { 36518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* wfi */ 36528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 36538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_WFI; 36548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 36558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* wfe */ 36568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* sev */ 36578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* TODO: Implement SEV and WFE. May help SMP performance. */ 36588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* nop */ 36598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 36608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_V001 cpu_V0, cpu_V0, cpu_V1 36648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_add(int size, TCGv t0, TCGv t1) 36668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 36685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_add_u8(t0, t0, t1); break; 36695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_add_u16(t0, t0, t1); break; 36705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_add_i32(t0, t0, t1); break; 36715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 36728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36755285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) 36768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 36785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; 36795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_sub_u16(t0, t1, t0); break; 36805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_sub_i32(t0, t1, t0); break; 36818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: return; 36828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32-bit pairwise ops end up the same as the elementwise versions. */ 36868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32 36878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32 36888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32 36898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32 36908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36913d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner#define GEN_NEON_INTEGER_OP_ENV(name) do { \ 36923d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner switch ((size << 1) | u) { \ 36933d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: \ 36943d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \ 36953d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 36963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: \ 36973d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \ 36983d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 36993d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: \ 37003d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \ 37013d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 37023d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 3: \ 37033d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \ 37043d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 37053d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 4: \ 37063d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \ 37073d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 37083d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 5: \ 37093d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \ 37103d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; \ 37113d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner default: return 1; \ 37123d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner }} while (0) 37133d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner 37148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_NEON_INTEGER_OP(name) do { \ 37158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { \ 37168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: \ 37175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \ 37188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: \ 37205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \ 37218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: \ 37235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \ 37248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: \ 37265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \ 37278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: \ 37295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \ 37308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: \ 37325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \ 37338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 37348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: return 1; \ 37358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }} while (0) 37368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37375285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv neon_load_scratch(int scratch) 37388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 37405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 37415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 37428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37445285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void neon_store_scratch(int scratch, TCGv var) 37458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 37475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 37488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37505285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv neon_get_scalar(int size, int reg) 37518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 37535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 37545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(reg & 7, reg >> 4); 37555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (reg & 8) { 37565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_high16(tmp); 37575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 37585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 37595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 37615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(reg & 15, reg >> 4); 37625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 37648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37665285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_unzip(int rd, int rm, int size, int q) 37678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 37695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!q && size == 2) { 37705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 37715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(rd); 37735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(rm); 37745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q) { 37755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 37765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 37773d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qunzip8(cpu_env, tmp, tmp2); 37785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37803d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qunzip16(cpu_env, tmp, tmp2); 37815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 37833d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qunzip32(cpu_env, tmp, tmp2); 37845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 37895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 37905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 37913d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_unzip8(cpu_env, tmp, tmp2); 37925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37943d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_unzip16(cpu_env, tmp, tmp2); 37955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 38015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 38025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 38038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 38048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38055285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_zip(int rd, int rm, int size, int q) 38068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 38075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 38085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!q && size == 2) { 38095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 38105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(rd); 38125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(rm); 38135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q) { 38145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 38155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 38163d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qzip8(cpu_env, tmp, tmp2); 38175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 38193d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qzip16(cpu_env, tmp, tmp2); 38205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 38223d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qzip32(cpu_env, tmp, tmp2); 38235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 38255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 38265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 38285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 38295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 38303d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_zip8(cpu_env, tmp, tmp2); 38315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 38333d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_zip16(cpu_env, tmp, tmp2); 38345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 38365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 38375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 38395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 38405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 38415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 38428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 38438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38445285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u8(TCGv t0, TCGv t1) 38458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 38465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv rd, tmp; 38478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd = tcg_temp_new_i32(); 38495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 38505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(rd, t0, 8); 38525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(rd, rd, 0xff00ff00); 38535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); 38545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(rd, rd, tmp); 38555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(t1, t1, 8); 38575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(t1, t1, 0x00ff00ff); 38585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t0, 0xff00ff00); 38595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t1, t1, tmp); 38605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(t0, rd); 38615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 38635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(rd); 38648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 38658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38665285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u16(TCGv t0, TCGv t1) 38675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 38685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv rd, tmp; 38695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd = tcg_temp_new_i32(); 38715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 38725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(rd, t0, 16); 38745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t1, 0xffff); 38755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(rd, rd, tmp); 38765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(t1, t1, 16); 38775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t0, 0xffff0000); 38785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t1, t1, tmp); 38795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(t0, rd); 38805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 38825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(rd); 38835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 38845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38865285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic struct { 38875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int nregs; 38885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int interleave; 38895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int spacing; 38905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} neon_ls_element_type[11] = { 38915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {4, 4, 1}, 38925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {4, 4, 2}, 38938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {4, 1, 1}, 38948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {4, 2, 1}, 38958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 3, 1}, 38968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 3, 2}, 38978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 1, 1}, 38988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {1, 1, 1}, 38998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 2, 1}, 39008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 2, 2}, 39018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 1, 1} 39028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 39038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 39048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON load/store element instruction. Return nonzero if the 39058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is invalid. */ 3906e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) 39078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 39088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, rn, rm; 39098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 39108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int nregs; 39118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int interleave; 39125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int spacing; 39138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int stride; 39148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 39158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int reg; 39168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 39178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int load; 39188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shift; 39195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 39208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 39218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 39228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 39235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) 39248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 39258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 39268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 39278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 39288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = (insn & (1 << 21)) != 0; 39298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) { 39308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load store all elements. */ 39318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 39328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 6) & 3; 39335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op > 10) 39348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 39355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch UNDEF cases for bad values of align field */ 39365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op & 0xc) { 39375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 39385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 5) & 1) == 1) { 39395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: 39435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 4) & 3) == 3) { 39445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 39485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = neon_ls_element_type[op].nregs; 39518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project interleave = neon_ls_element_type[op].interleave; 39525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner spacing = neon_ls_element_type[op].spacing; 39535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3 && (interleave | spacing) != 1) { 39545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 39565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_const_i32(insn); 39570b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_neon_vldst_all(cpu_env, addr); 39585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 39598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = nregs * 8; 39608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 39618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 10) & 3; 39628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 39638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load single element to all lanes. */ 39645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int a = (insn >> 4) & 1; 39655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!load) { 39668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 39675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 6) & 3; 39698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = ((insn >> 8) & 3) + 1; 39705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 39715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 39725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs != 4 || a == 0) { 39738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 39748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 39755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */ 39765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner size = 2; 39775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 1 && a == 1 && size == 0) { 39795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 3 && a == 1) { 39825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 39855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 39865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 1) { 39875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */ 39885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_load_and_replicate(s, addr, size); 39895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 39905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 39915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 39925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0)); 39935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1)); 39945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 39965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 39975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VLD2/3/4 to all lanes: bit 5 indicates register stride */ 39985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner stride = (insn & (1 << 5)) ? 2 : 1; 39995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (reg = 0; reg < nregs; reg++) { 40005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_load_and_replicate(s, addr, size); 40015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 40025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 40035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 40045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 1 << size); 40055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd += stride; 40065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 40098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (1 << size) * nregs; 40108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 40118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Single element. */ 40125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int idx = (insn >> 4) & 0xf; 40138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pass = (insn >> 7) & 1; 40148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 40168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 5) & 3) * 8; 40178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = 1; 40188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 40208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 6) & 1) * 16; 40218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (insn & (1 << 5)) ? 2 : 1; 40228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 40248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 0; 40258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (insn & (1 << 6)) ? 2 : 1; 40268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 40288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 40298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = ((insn >> 8) & 3) + 1; 40315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch the UNDEF cases. This is unavoidably a bit messy. */ 40325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (nregs) { 40335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 40345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((idx & (1 << size)) != 0) || 40355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) { 40365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 40375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 40395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 40405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((idx & 1) != 0) { 40415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 40425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 40445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 40455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 2 && (idx & 2) != 0) { 40465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 40475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 40495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 40505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((size == 2) && ((idx & 3) == 3)) { 40515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 40525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 40545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 40555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 40565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((rd + stride * (nregs - 1)) > 31) { 40585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Attempts to write off the end of the register file 40595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * are UNPREDICTABLE; we choose to UNDEF because otherwise 40605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the neon_load_reg() would write off the end of the array. 40615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 40625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 40635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 40655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 40668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (reg = 0; reg < nregs; reg++) { 40678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (load) { 40688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 40705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 40718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 40735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 40748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 40765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 40778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Avoid compiler warnings. */ 40798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 40808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size != 2) { 40828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rd, pass); 40838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff); 40845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 40858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, pass, tmp); 40878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* Store */ 40888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, pass); 40898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 40908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, shift); 40918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 40935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 40948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 40965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 40978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 40995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 41008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 41018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd += stride; 41045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 1 << size); 41058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 41078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = nregs * (1 << size); 41088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm != 15) { 41118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv base; 41128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project base = load_reg(s, rn); 41148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm == 13) { 41158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(base, base, stride); 41168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv index; 41188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project index = load_reg(s, rm); 41198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(base, base, index); 41205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(index); 41218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, base); 41238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 41258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitwise select. dest = c ? t : f. Clobbers T and F. */ 41288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c) 41298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_and_i32(t, t, c); 41315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(f, f, c); 41328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(dest, t, f); 41338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src) 41368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_narrow_u8(dest, src); break; 41398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_narrow_u16(dest, src); break; 41408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_trunc_i64_i32(dest, src); break; 41418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src) 41468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41483d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break; 41493d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break; 41503d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break; 41518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) 41568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41583d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break; 41593d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break; 41603d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break; 41615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 41625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 41635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 41645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 41655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) 41665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 41675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 41683d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break; 41693d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break; 41703d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break; 41718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, 41768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int q, int u) 41778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 41798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 41808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_rshl_u16(var, var, shift); break; 41828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_rshl_u32(var, var, shift); break; 41838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_rshl_s16(var, var, shift); break; 41888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_rshl_s32(var, var, shift); break; 41898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 41948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_shl_u16(var, var, shift); break; 41965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_shl_u32(var, var, shift); break; 41978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 42008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_shl_s16(var, var, shift); break; 42028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_shl_s32(var, var, shift); break; 42038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u) 42108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 42128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_widen_u8(dest, src); break; 42148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_widen_u16(dest, src); break; 42158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_extu_i32_i64(dest, src); break; 42168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 42198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_widen_s8(dest, src); break; 42218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_widen_s16(dest, src); break; 42228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_ext_i32_i64(dest, src); break; 42238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(src); 42278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_addl(int size) 42308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_addl_u16(CPU_V001); break; 42338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_addl_u32(CPU_V001); break; 42348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_add_i64(CPU_V001); break; 42358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_subl(int size) 42408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_subl_u16(CPU_V001); break; 42438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_subl_u32(CPU_V001); break; 42448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_sub_i64(CPU_V001); break; 42458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_negl(TCGv_i64 var, int size) 42508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_negl_u16(var, var); break; 42538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_negl_u32(var, var); break; 42548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_negl_u64(var, var); break; 42558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size) 42608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 42623d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break; 42633d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break; 42648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) 42698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 42705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 42718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { 42738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_mull_s8(dest, a, b); break; 42748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_mull_u8(dest, a, b); break; 42758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_mull_s16(dest, a, b); break; 42768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_helper_neon_mull_u16(dest, a, b); break; 42778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 42788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_muls_i64_i32(a, b); 42798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i64(dest, tmp); 42805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 42818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 42828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 42838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_mulu_i64_i32(a, b); 42848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i64(dest, tmp); 42855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 42868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 42878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 42905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* gen_helper_neon_mull_[su]{8|16} do not free their parameters. 42915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner Don't forget to clean them now. */ 42928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size < 2) { 42935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 42945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 42958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42985285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src) 42995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 43005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op) { 43015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 43025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_unarrow_sats(size, dest, src); 43035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 43045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow(size, dest, src); 43055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 43065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 43075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 43085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_satu(size, dest, src); 43095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 43105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_sats(size, dest, src); 43115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 43125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 43135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 43145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 3-register same-length. 43165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B 43175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-9. 43185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 43195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHADD 0 43205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQADD 1 43215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRHADD 2 43225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */ 43235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHSUB 4 43245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSUB 5 43255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGT 6 43265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGE 7 43275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VSHL 8 43285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSHL 9 43295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRSHL 10 43305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQRSHL 11 43315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMAX 12 43325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMIN 13 43335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABD 14 43345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABA 15 43355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VADD_VSUB 16 43365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VTST_VCEQ 17 43375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */ 43385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMUL 19 43395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMAX 20 43405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMIN 21 43415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQDMULH_VQRDMULH 22 43425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPADD 23 43435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */ 43445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */ 43455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */ 43465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */ 43475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */ 43485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */ 43495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43505285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_3r_sizes[] = { 43515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VHADD] = 0x7, 43525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQADD] = 0xf, 43535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRHADD] = 0x7, 43545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */ 43555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VHSUB] = 0x7, 43565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQSUB] = 0xf, 43575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VCGT] = 0x7, 43585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VCGE] = 0x7, 43595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VSHL] = 0xf, 43605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQSHL] = 0xf, 43615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRSHL] = 0xf, 43625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQRSHL] = 0xf, 43635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMAX] = 0x7, 43645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMIN] = 0x7, 43655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VABD] = 0x7, 43665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VABA] = 0x7, 43675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VADD_VSUB] = 0xf, 43685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VTST_VCEQ] = 0x7, 43695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VML] = 0x7, 43705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMUL] = 0x7, 43715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPMAX] = 0x7, 43725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPMIN] = 0x7, 43735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQDMULH_VQRDMULH] = 0x6, 43745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPADD] = 0x7, 43755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */ 43765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */ 43775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */ 43785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */ 43795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */ 43805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */ 43815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}; 43825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 2-register miscellaneous. 43845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B 43855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-13. 43865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 43875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV64 0 43885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV32 1 43895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV16 2 43905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL 4 43915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL_U 5 43925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLS 8 43935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLZ 9 43945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCNT 10 43955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMVN 11 43965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL 12 43975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL_U 13 43985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQABS 14 43995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQNEG 15 44005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0 16 44015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0 17 44025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0 18 44035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0 19 44045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0 20 44055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS 22 44065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG 23 44075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0_F 24 44085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0_F 25 44095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0_F 26 44105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0_F 27 44115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0_F 28 44125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS_F 30 44135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG_F 31 44145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSWP 32 44155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VTRN 33 44165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VUZP 34 44175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VZIP 35 44185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */ 44195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */ 44205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSHLL 38 44215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F16_F32 44 44225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F32_F16 46 44235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE 56 44245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE 57 44255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE_F 58 44265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE_F 59 44275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FS 60 44285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FU 61 44295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_SF 62 44305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_UF 63 44315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 44325285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int neon_2rm_is_float_op(int op) 44335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 44345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Return true if this neon 2reg-misc op is float-to-float */ 44355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F || 44365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op >= NEON_2RM_VRECPE_F); 44375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 44385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 44395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Each entry in this array has bit n set if the insn allows 44405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * size value n (otherwise it will UNDEF). Since unallocated 44415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * op values will have no bits set they always UNDEF. 44425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 44435285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_2rm_sizes[] = { 44445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV64] = 0x7, 44455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV32] = 0x3, 44465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV16] = 0x1, 44475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADDL] = 0x7, 44485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADDL_U] = 0x7, 44495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLS] = 0x7, 44505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLZ] = 0x7, 44515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCNT] = 0x1, 44525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VMVN] = 0x1, 44535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADAL] = 0x7, 44545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADAL_U] = 0x7, 44555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQABS] = 0x7, 44565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQNEG] = 0x7, 44575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGT0] = 0x7, 44585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGE0] = 0x7, 44595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCEQ0] = 0x7, 44605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLE0] = 0x7, 44615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLT0] = 0x7, 44625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VABS] = 0x7, 44635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VNEG] = 0x7, 44645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGT0_F] = 0x4, 44655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGE0_F] = 0x4, 44665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCEQ0_F] = 0x4, 44675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLE0_F] = 0x4, 44685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLT0_F] = 0x4, 44695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VABS_F] = 0x4, 44705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VNEG_F] = 0x4, 44715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VSWP] = 0x1, 44725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VTRN] = 0x7, 44735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VUZP] = 0x7, 44745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VZIP] = 0x7, 44755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VMOVN] = 0x7, 44765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQMOVN] = 0x7, 44775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VSHLL] = 0x7, 44785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_F16_F32] = 0x2, 44795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_F32_F16] = 0x2, 44805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRECPE] = 0x4, 44815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRSQRTE] = 0x4, 44825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRECPE_F] = 0x4, 44835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRSQRTE_F] = 0x4, 44845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_FS] = 0x4, 44855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_FU] = 0x4, 44865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_SF] = 0x4, 44875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_UF] = 0x4, 44885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}; 44895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 44908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON data processing instruction. Return nonzero if the 44918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is invalid. 44928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project We process data in a mixture of 32-bit and 64-bit chunks. 44938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Mostly we use 32-bit chunks so we can use normal scalar instructions. */ 44948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4495e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn) 44968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 44978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 44988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int q; 44998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, rn, rm; 45008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 45018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shift; 45028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 45038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int count; 45048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pairwise; 45058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int u; 45065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner uint32_t imm, mask; 45075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2, tmp3, tmp4, tmp5; 45085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 45098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 45105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) 45118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 45128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (insn & (1 << 6)) != 0; 45138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u = (insn >> 24) & 1; 45148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 45158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 45168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 45178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 20) & 3; 45188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) { 45198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Three register same length. */ 45208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1); 45215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch invalid op and bad size combinations: UNDEF */ 45225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((neon_3r_sizes[op] & (1 << size)) == 0) { 45235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* All insns of this form UNDEF for either this condition or the 45265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * superset of cases "Q==1"; we catch the latter later. 45275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 45285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rn | rm) & 1)) { 45295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3 && op != NEON_3R_LOGIC) { 45325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64-bit element instructions. */ 45338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 2 : 1); pass++) { 45348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + pass); 45358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + pass); 45368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 45375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQADD: 45388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45393d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qadd_u64(cpu_V0, cpu_env, 45403d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V0, cpu_V1); 45418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45423d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qadd_s64(cpu_V0, cpu_env, 45433d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V0, cpu_V1); 45448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSUB: 45478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45483d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qsub_u64(cpu_V0, cpu_env, 45493d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V0, cpu_V1); 45508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45513d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qsub_s64(cpu_V0, cpu_env, 45523d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V0, cpu_V1); 45538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 45568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0); 45588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0); 45608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 45638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45643d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshl_u64(cpu_V0, cpu_env, 45653d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V1, cpu_V0); 45668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45673d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshl_s64(cpu_V0, cpu_env, 45683d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V1, cpu_V0); 45698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 45728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0); 45748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0); 45768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 45798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45803d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrshl_u64(cpu_V0, cpu_env, 45813d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V1, cpu_V0); 45828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45833d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrshl_s64(cpu_V0, cpu_env, 45843d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V1, cpu_V0); 45858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VADD_VSUB: 45888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i64(CPU_V001); 45908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(CPU_V001); 45928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 45958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 45968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 45988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 46008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = 0; 46028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 46035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 46045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 46055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 46065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 46078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 46088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rtmp; 46098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift instruction operands are reversed. */ 46108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rtmp = rn; 46118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = rm; 46128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rtmp; 46138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPADD: 46165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 46175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 46205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMAX: 46215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMIN: 46228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pairwise = 1; 46238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ARITH: 46255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = (u && size < 2); /* if VPADD (float) */ 46268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MINMAX: 46285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = u; /* if VPMIN/VPMAX (float) */ 46295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 46305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_CMP: 46315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u && size) { 46325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* no encoding for U=0 C=1x */ 46335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 46365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ACMP: 46375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u) { 46385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 46415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRECPS_VRSQRTS: 46425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 46435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 46465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMUL: 46475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u && (size != 0)) { 46485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF on invalid size for polynomial subcase */ 46495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 46538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 46565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pairwise && q) { 46575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* All the pairwise insns UNDEF if Q is set */ 46585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 46595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 46605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 46618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 46628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 46638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise) { 46648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Pairwise. */ 46655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass < 1) { 46665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, 0); 46675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rn, 1); 46688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 46695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 46705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, 1); 46718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 46738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Elementwise. */ 46745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, pass); 46755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, pass); 46768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 46785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VHADD: 46798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(hadd); 46808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQADD: 46823d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner GEN_NEON_INTEGER_OP_ENV(qadd); 46838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRHADD: 46858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rhadd); 46868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_LOGIC: /* Logic ops. */ 46888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((u << 2) | size) { 46898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VAND */ 46905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 46918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* BIC */ 46935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 46948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VORR */ 46965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 46978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VORN */ 46995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_orc_i32(tmp, tmp, tmp2); 47008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VEOR */ 47025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 47038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VBSL */ 47055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 47065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp, tmp2, tmp3); 47075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 47088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* VBIT */ 47105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 47115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp, tmp3, tmp2); 47125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 47138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* VBIF */ 47155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 47165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp3, tmp, tmp2); 47175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 47188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VHSUB: 47228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(hsub); 47238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSUB: 47253d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner GEN_NEON_INTEGER_OP_ENV(qsub); 47268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VCGT: 47288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(cgt); 47298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VCGE: 47318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(cge); 47328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 47348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(shl); 47358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 47373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner GEN_NEON_INTEGER_OP_ENV(qshl); 47388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 47408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rshl); 47418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 47433d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner GEN_NEON_INTEGER_OP_ENV(qrshl); 47448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMAX: 47468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(max); 47478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMIN: 47498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(min); 47508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VABD: 47528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(abd); 47538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VABA: 47558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(abd); 47565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 47575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 47585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 47598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VADD_VSUB: 47618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VADD */ 47625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 47638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VSUB */ 47648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break; 47665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break; 47675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break; 47685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VTST_VCEQ: 47738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VTST */ 47748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break; 47765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break; 47775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break; 47785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VCEQ */ 47818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; 47835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; 47845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; 47855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */ 47908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 47925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 47935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 47945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 47975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 47988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { /* VMLS */ 47995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 48008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VMLA */ 48015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 48028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMUL: 48058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { /* polynomial */ 48065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mul_p8(tmp, tmp, tmp2); 48078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* Integer */ 48088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 48095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 48105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 48115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 48125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 48138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMAX: 48178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(pmax); 48188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMIN: 48208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(pmin); 48218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */ 48238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VQDMULH */ 48248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 48253d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: 48263d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); 48273d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 48283d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: 48293d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); 48303d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 48315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 48328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { /* VQRDMULH */ 48348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 48353d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: 48363d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); 48373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 48383d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: 48393d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); 48403d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 48415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 48428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPADD: 48468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 48475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break; 48485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break; 48495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break; 48505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 48518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ 485416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 485516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 48568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((u << 2) | size) { 48578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VADD */ 485816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner case 4: /* VPADD */ 485916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); 48608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VSUB */ 486216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus); 48638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* VABD */ 486516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus); 48668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 48685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 48698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 487016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 48718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 487216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 48735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MULTIPLY: 487416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 487516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 487616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); 48778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 48785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 48795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 48808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 488116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); 48828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 488316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); 48848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 488616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 48878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 488816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 48895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_CMP: 489016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 489116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 48928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 489316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); 48948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 489516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner if (size == 0) { 489616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); 489716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } else { 489816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); 489916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 49008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 490116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 49028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 490316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 49045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ACMP: 490516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 490616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 490716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner if (size == 0) { 490816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus); 490916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } else { 491016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus); 491116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 491216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 49138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 491416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 49155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MINMAX: 491616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 491716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 491816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner if (size == 0) { 491916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus); 492016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } else { 492116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus); 492216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 492316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 49248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 492516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 49265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRECPS_VRSQRTS: 49278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) 49285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env); 49298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 49305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env); 49318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 49338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 49348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 49365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 49378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Save the result. For elementwise operations we can put it 49388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project straight into the destination register. For pairwise operations 49398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project we have to be careful to avoid clobbering the source operands. */ 49408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise && rd == rm) { 49415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(pass, tmp); 49428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 49435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 49448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 49468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* for pass */ 49478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise && rd == rm) { 49488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 49495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(pass); 49505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 49518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* End of 3 register same size operations. */ 49548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 4)) { 49558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x00380080) != 0) { 49568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two registers and shift. */ 49578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 49588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 49595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64-bit shift. */ 49605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op > 7) { 49615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 49625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 3; 49648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 49658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 2; 49668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((insn & (1 << (size + 19))) == 0) 49678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size--; 49688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 16) & ((1 << (3 + size)) - 1); 49708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* To avoid excessive dumplication of ops we implement shift 49718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project by immediate using the variable shift operations. */ 49728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 8) { 49738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift by immediate: 49748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */ 49755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rm) & 1)) { 49765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 49775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u && (op == 4 || op == 6)) { 49795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 49805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Right shifts are encoded as N - shift, where N is the 49828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project element size in bits. */ 49838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op <= 4) 49848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = shift - (1 << (size + 3)); 49858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 49868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project count = q + 1; 49878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 49888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project count = q ? 4: 2; 49898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 49918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 49928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (uint8_t) shift; 49938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 8; 49948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 49958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 49978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (uint16_t) shift; 49988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 49998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 50018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 50028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = shift; 50038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 50058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 50068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 50088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < count; pass++) { 50098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 50108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rm + pass); 50118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_V1, imm); 50128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 50138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VSHR */ 50148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* VSRA */ 50158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 50168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); 50178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 50188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1); 50198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VRSHR */ 50218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VRSRA */ 50228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 50238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1); 50248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 50258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1); 50268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VSRI */ 50288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VSHL, VSLI */ 50298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); 50308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VQSHLU */ 50323d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshlu_s64(cpu_V0, cpu_env, 50333d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner cpu_V0, cpu_V1); 50348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* VQSHL */ 50365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 50373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshl_u64(cpu_V0, cpu_env, 50385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_V0, cpu_V1); 50395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50403d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshl_s64(cpu_V0, cpu_env, 50415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_V0, cpu_V1); 50425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 1 || op == 3) { 50468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 50475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 50488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1); 50498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || (op == 5 && u)) { 50508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Insert */ 50515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 50525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner uint64_t mask; 50535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift < -63 || shift > 63) { 50545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0; 50555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 4) { 50575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffffffffffull >> -shift; 50585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffffffffffull << shift; 50605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask); 50635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 50648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 50668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* size < 3 */ 50678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Operands in T0 and T1. */ 50685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass); 50695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(imm); 50708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 50718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VSHR */ 50728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* VSRA */ 50738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(shl); 50748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VRSHR */ 50768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VRSRA */ 50778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rshl); 50788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VSRI */ 50808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VSHL, VSLI */ 50818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 50825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break; 50835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break; 50845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break; 50855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 50868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VQSHLU */ 50898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 50905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 50913d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshlu_s8(tmp, cpu_env, 50923d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner tmp, tmp2); 50935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 50945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 50953d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshlu_s16(tmp, cpu_env, 50963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner tmp, tmp2); 50975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 50985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 50993d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qshlu_s32(tmp, cpu_env, 51003d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner tmp, tmp2); 51015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 51025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 51035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 51048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* VQSHL */ 51073d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner GEN_NEON_INTEGER_OP_ENV(qshl); 51085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 51098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 51118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 51128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 1 || op == 3) { 51138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 51145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 51155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 51165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 51178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || (op == 5 && u)) { 51188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Insert */ 51198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 51208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 51218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 4) 51225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xff >> -shift; 51238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 51245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = (uint8_t)(0xff << shift); 51255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 8; 51265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 16; 51278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 51298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 4) 51305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffff >> -shift; 51318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 51325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = (uint16_t)(0xffff << shift); 51335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 16; 51348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 51365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift < -31 || shift > 31) { 51375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0; 51385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 4) 51405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffu >> -shift; 51415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 51425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffu << shift; 51435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 51468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 51478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 51495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, mask); 51505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, ~mask); 51515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 51525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 51538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 51558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* for pass */ 51578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op < 10) { 51588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift by immediate and narrow: 51598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VSHRN, VRSHRN, VQSHRN, VQRSHRN. */ 51605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int input_unsigned = (op == 8) ? !u : u; 51615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rm & 1) { 51625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 51635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = shift - (1 << (size + 3)); 51658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size++; 51665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 51675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_const_i64(shift); 51685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V0, rm); 51695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rm + 1); 51705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 51715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 in; 51725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 51735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner in = cpu_V0; 51745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner in = cpu_V1; 51765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 51785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (input_unsigned) { 51795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_rshl_u64(cpu_V0, in, tmp64); 51805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_rshl_s64(cpu_V0, in, tmp64); 51825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 51845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (input_unsigned) { 51855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_shl_u64(cpu_V0, in, tmp64); 51865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_shl_s64(cpu_V0, in, tmp64); 51885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 51915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); 51925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 51935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } /* for pass */ 51945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 51955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 51975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (uint16_t)shift; 51985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm |= imm << 16; 51998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* size == 2 */ 52015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (uint32_t)shift; 52028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(imm); 52045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = neon_load_reg(rm + 1, 0); 52055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp5 = neon_load_reg(rm + 1, 1); 52065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 52075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 52085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 52095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 52105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tmp4; 52115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_shift_narrow(size, tmp, tmp2, q, 52135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner input_unsigned); 52145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 52155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rm, 1); 52165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 52175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tmp5; 52185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_shift_narrow(size, tmp3, tmp2, q, 52205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner input_unsigned); 52215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3); 52225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 52235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 52245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 52255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); 52265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 52275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } /* for pass */ 52285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 52295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 10) { 52315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VSHLL, VMOVL */ 52325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q || (rd & 1)) { 52338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 52345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, 0); 52368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 1); 52378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 52388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1) 52398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tmp2; 52408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, u); 52428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 52448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The shift is less than the width of the source 52458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type, so we can just shift the whole register. */ 52468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i64(cpu_V0, cpu_V0, shift); 52475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Widen the result of shift: we need to clear 52485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the potential overflow bits resulting from 52495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * left bits of the narrow input appearing as 52505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * right bits of left the neighbour narrow 52515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * input. */ 52528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size < 2 || !u) { 52538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t imm64; 52548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 52558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (0xffu >> (8 - shift)); 52568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 52575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (size == 1) { 52588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = 0xffff >> (16 - shift); 52595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 52605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* size == 2 */ 52615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = 0xffffffff >> (32 - shift); 52628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size < 2) { 52645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm64 = imm | (((uint64_t)imm) << 32); 52655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 52665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm64 = imm; 52675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64); 52698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 52728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op >= 14) { 52748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VCVT fixed-point. */ 52755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) { 52765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 52775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* We have already masked out the must-be-1 top bit of imm6, 52795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * hence this 32-shift where the ARM ARM has 64-imm6. 52805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 52815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = 32 - shift; 52828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 52838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); 52845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(op & 1)) { 52858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 52865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ulto(0, shift, 1); 52878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 52885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_slto(0, shift, 1); 52898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 52915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toul(0, shift, 1); 52928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 52935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosl(0, shift, 1); 52948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); 52968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 52998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* (insn & 0x00380080) == 0 */ 53018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int invert; 53025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && (rd & 1)) { 53035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 53045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 53058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 53068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 53078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One register and immediate. */ 53088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf); 53098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project invert = (insn & (1 << 5)) != 0; 53105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE. 53115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * We choose to not special-case this and will behave as if a 53125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * valid constant encoding of 0 had been given. 53135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 53148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 53158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: 53168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 53178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: case 3: 53198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 8; 53208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: 53228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 16; 53238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: 53258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 24; 53268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: 53288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 53298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: case 11: 53318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (imm << 8) | (imm << 24); 53328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: 53345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (imm << 8) | 0xff; 53358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: 53378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (imm << 16) | 0xffff; 53388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: 53408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (imm << 8) | (imm << 16) | (imm << 24); 53418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) 53428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ~imm; 53438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 53455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (invert) { 53465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 53475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 53488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19) 53498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | ((imm & 0x40) ? (0x1f << 25) : (1 << 30)); 53508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) 53538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ~imm; 53548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 53558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 53568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1 && op < 12) { 53578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, pass); 53588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) { 53598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The immediate value has already been inverted, so 53608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BIC becomes AND. */ 53618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, imm); 53628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, imm); 53648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMOV, VMVN. */ 53675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 53688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 14 && invert) { 53695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n; 53708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val; 53718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 0; 53728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (n = 0; n < 4; n++) { 53738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm & (1 << (n + (pass & 1) * 4))) 53748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= 0xff << (n * 8); 53758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 53778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, imm); 53798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, pass, tmp); 53828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { /* (insn & 0x00800010 == 0x00800000) */ 53858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size != 3) { 53868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 53878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 6)) == 0) { 53888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Three registers of different lengths. */ 53898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int src1_wide; 53908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int src2_wide; 53918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int prewiden; 53925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* undefreq: bit 0 : UNDEF if size != 0 53935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bit 1 : UNDEF if size == 0 53945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bit 2 : UNDEF if U == 1 53955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Note that [1:0] set implies 'always UNDEF' 53965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 53975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int undefreq; 53985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* prewiden, src1_wide, src2_wide, undefreq */ 53995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner static const int neon_3reg_wide[16][4] = { 54005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 0, 0, 0}, /* VADDL */ 54015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 1, 0, 0}, /* VADDW */ 54025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 0, 0, 0}, /* VSUBL */ 54035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 1, 0, 0}, /* VSUBW */ 54045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 1, 1, 0}, /* VADDHN */ 54055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VABAL */ 54065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 1, 1, 0}, /* VSUBHN */ 54075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VABDL */ 54085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VMLAL */ 54095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 6}, /* VQDMLAL */ 54105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VMLSL */ 54115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 6}, /* VQDMLSL */ 54125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* Integer VMULL */ 54135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 2}, /* VQDMULL */ 54145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 5}, /* Polynomial VMULL */ 54155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 3}, /* Reserved: always UNDEF */ 54168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }; 54178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 54188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project prewiden = neon_3reg_wide[op][0]; 54198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project src1_wide = neon_3reg_wide[op][1]; 54208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project src2_wide = neon_3reg_wide[op][2]; 54215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner undefreq = neon_3reg_wide[op][3]; 54228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 54235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((undefreq & 1) && (size != 0)) || 54245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((undefreq & 2) && (size == 0)) || 54255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((undefreq & 4) && u)) { 54265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 54275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((src1_wide && (rn & 1)) || 54295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (src2_wide && (rm & 1)) || 54305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (!src2_wide && (rd & 1))) { 54318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 54325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 54348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Avoid overlapping operands. Wide source operands are 54358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project always aligned so will never overlap with wide 54368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project destinations in problematic ways. */ 54378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == rm && !src2_wide) { 54385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 1); 54395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(2, tmp); 54408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (rd == rn && !src1_wide) { 54415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, 1); 54425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(2, tmp); 54438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp3); 54458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 54468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (src1_wide) { 54478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + pass); 54488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp); 54498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1 && rd == rn) { 54515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(2); 54528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, pass); 54548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (prewiden) { 54568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, u); 54578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (src2_wide) { 54608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + pass); 54618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp2); 54628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1 && rd == rm) { 54645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_scratch(2); 54658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, pass); 54678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (prewiden) { 54698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V1, tmp2, size, u); 54708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 54738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */ 54748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 54758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */ 54778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_subl(size); 54788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: case 7: /* VABAL, VABDL */ 54808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { 54818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 54828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2); 54838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 54858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2); 54868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 54888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2); 54898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 54918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2); 54928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 54948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2); 54958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 54978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2); 54988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 55008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 55025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 55038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: case 10: case 11: case 12: case 13: 55058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */ 55068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_mull(cpu_V0, tmp, tmp2, size, u); 55078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* Polynomial VMULL */ 55095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2); 55105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 55115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 55125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 55135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: /* 15 is RESERVED: caught earlier */ 55145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 55155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 13) { 55175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VQDMULL */ 55185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 55195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg64(cpu_V0, rd + pass); 55205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op == 5 || (op >= 8 && op <= 11)) { 55215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Accumulate. */ 55225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 55238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 55245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 10: /* VMLSL */ 55255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 55265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 55275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: case 8: /* VABAL, VMLAL */ 55288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 55298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: case 11: /* VQDMLAL, VQDMLSL */ 55318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 55325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 11) { 55335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 55345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V1, size); 55368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 55388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 55398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 55418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || op == 6) { 55428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Narrowing operation. */ 55435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 55445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u) { 55458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 55468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 55478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_high_u8(tmp, cpu_V0); 55488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 55508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_high_u16(tmp, cpu_V0); 55518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 55538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 55548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_V0); 55558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 55578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 55608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 55618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0); 55628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 55648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0); 55658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 55678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31); 55688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 55698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_V0); 55708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 55728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 55758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp3 = tmp; 55768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp3); 55788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 1, tmp); 55798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Write back the result. */ 55828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 55838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Two registers and a scalar. NB that for ops of this form 55875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the ARM ARM labels bit 24 as Q, but it is in our variable 55885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 'u', not 'q'. 55895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 55905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 0) { 55915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 55925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 55948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* Float VMLA scalar */ 55958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* Floating point VMLS scalar */ 55968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* Floating point VMUL scalar */ 55975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 55985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 55995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 56015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: /* Integer VMLA scalar */ 56025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: /* Integer VMLS scalar */ 56035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: /* Integer VMUL scalar */ 56048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* VQDMULH scalar */ 56058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* VQRDMULH scalar */ 56065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u && ((rd | rn) & 1)) { 56075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 56085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_get_scalar(size, rm); 56105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(0, tmp); 56118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (u ? 4 : 2); pass++) { 56125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(0); 56135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rn, pass); 56148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 12) { 56158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 1) { 56163d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); 56178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56183d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); 56198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 13) { 56218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 1) { 56223d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); 56238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56243d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); 56258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op & 1) { 562716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 562816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus); 562916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 56308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 56325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 56335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 56345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 56355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 56368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 56398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 8) { 56408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 56415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 56428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 56438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 56445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 56458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 56468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 564716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 564816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 564916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus); 565016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 56518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 565216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 56538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 56545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 56558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 56568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 565716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 565816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 565916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus); 566016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 56618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 566216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 56638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 56648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 56658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 56678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 56698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 56718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VQDMLAL scalar */ 56728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* VQDMLSL scalar */ 56738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* VQDMULL scalar */ 56745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u == 1) { 56758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 56765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 56785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* VMLAL sclar */ 56795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VMLSL scalar */ 56805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 10: /* VMULL scalar */ 56815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd & 1) { 56825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 56835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_get_scalar(size, rm); 56855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* We need a copy of tmp2 because gen_neon_mull 56865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * deletes it during pass 0. */ 56875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = tcg_temp_new_i32(); 56885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp4, tmp2); 56895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rn, 1); 56908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 56918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 56928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 56938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, 0); 56948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tmp3; 56965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tmp4; 56978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_mull(cpu_V0, tmp, tmp2, size, u); 56998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op != 11) { 57008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rd + pass); 57018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 57035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: 57045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 57055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 57065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 57078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 57088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: case 7: 57108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 57115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 7) { 57125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 57135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V1, size); 57158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 57178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 57188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 57208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 57218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 57238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 57248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 57268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 57285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 57298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* 14 and 15 are RESERVED */ 57318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* size == 3 */ 57358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 57368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Extract. */ 57378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (insn >> 8) & 0xf; 57388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 57398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm > 7 && !q) 57408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 57425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rn | rm) & 1)) { 57435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 57445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 57468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm == 0) { 57478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 57488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 57498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rn + 1); 57508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (imm == 8) { 57528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + 1); 57538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 57548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 57558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (q) { 57575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 57588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 8) { 57598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 57605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_load_reg64(tmp64, rn + 1); 57618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 57628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + 1); 57635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_load_reg64(tmp64, rm); 57648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8); 57665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8)); 57678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 57688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 8) { 57698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 57708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 57718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + 1); 57728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm -= 8; 57738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); 57755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, imm * 8); 57765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64); 57775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 57788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 57795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* BUGFIX */ 57808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 57815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8); 57828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 57835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); 57848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 57858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd); 57878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 57888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V1, rd + 1); 57898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 11)) == 0) { 57918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two register misc. */ 57928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf); 57938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 18) & 3; 57945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF for unknown op values and bad op-size combinations */ 57955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((neon_2rm_sizes[op] & (1 << size)) == 0) { 57965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 57975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) && 57995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q && ((rm | rd) & 1)) { 58005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 58015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 58028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 58035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV64: 58048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 2 : 1); pass++) { 58055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass * 2); 58065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, pass * 2 + 1); 58078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 58095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp); break; 58108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* no-op */ break; 58118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 58128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2 + 1, tmp); 58148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 2) { 58155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2, tmp2); 58168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 58178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break; 58195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp2); break; 58208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 58218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2, tmp2); 58238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U: 58275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U: 58288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < q + 1; pass++) { 58298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, pass * 2); 58308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, op & 1); 58318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, pass * 2 + 1); 58328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V1, tmp, size, op & 1); 58338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_paddl_u16(CPU_V001); break; 58358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_paddl_u32(CPU_V001); break; 58368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_add_i64(CPU_V001); break; 58378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 58388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op >= NEON_2RM_VPADAL) { 58408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 58418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rd + pass); 58428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 58438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 58458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VTRN: 58488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 2) { 58495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n; 58508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (n = 0; n < (q ? 4 : 2); n += 2) { 58515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, n); 58525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, n + 1); 58535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, n, tmp2); 58545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, n + 1, tmp); 58558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 58578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto elementwise; 58588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VUZP: 58615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_neon_unzip(rd, rm, size, q)) { 58628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 58638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VZIP: 58665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_neon_zip(rd, rm, size, q)) { 58678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 58688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN: 58715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* also VQMOVUN; op field and mnemonics don't line up */ 58725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rm & 1) { 58738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 58745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 58758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp2); 58768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 58778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rm + pass); 58785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 58795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size, 58805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp, cpu_V0); 58818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 58828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = tmp; 58838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 58848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp2); 58858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 1, tmp); 58868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VSHLL: 58905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q || (rd & 1)) { 58918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 58925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 58938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, 0); 58948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 1); 58958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 58968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1) 58978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tmp2; 58988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, 1); 58995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size); 59008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 59018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_F16_F32: 59045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16) || 59055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q || (rm & 1)) { 59065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 59075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 59085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 59095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 59105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0)); 59115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 59125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1)); 59135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); 59145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 59155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp2, tmp2, tmp); 59165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2)); 59175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 59185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3)); 59195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, 0, tmp2); 59205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 59215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); 59225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 59235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp2, tmp2, tmp); 59245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, 1, tmp2); 59255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 59265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 59275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_F32_F16: 59285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16) || 59295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q || (rd & 1)) { 59305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 59315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 59325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 59335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 59345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, 1); 59355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp3, tmp); 59365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 59375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0)); 59385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp3, tmp, 16); 59395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 59405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1)); 59415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 59425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp3, tmp2); 59435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 59445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2)); 59455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp3, tmp2, 16); 59465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 59475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3)); 59485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 59495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 59505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 59518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 59528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project elementwise: 59538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 59545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon_2rm_is_float_op(op)) { 59558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, 59568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_reg_offset(rm, pass)); 59575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp); 59588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 59595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass); 59608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 59625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV32: 59638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 59645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 59655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp); break; 59665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV16: 59705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_rev16(tmp); 59718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLS: 59738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 59745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cls_s8(tmp, tmp); break; 59755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cls_s16(tmp, tmp); break; 59765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cls_s32(tmp, tmp); break; 59775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLZ: 59818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 59825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_clz_u8(tmp, tmp); break; 59835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_clz_u16(tmp, tmp); break; 59845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_clz(tmp, tmp); break; 59855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCNT: 59895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cnt_u8(tmp, tmp); 59908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VMVN: 59925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 59938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VQABS: 59958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 59963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: 59973d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); 59983d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 59993d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: 60003d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); 60013d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 60023d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: 60033d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); 60043d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 60055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VQNEG: 60098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 60103d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 0: 60113d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); 60123d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 60133d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 1: 60143d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); 60153d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 60163d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner case 2: 60173d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); 60183d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner break; 60195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGT0: case NEON_2RM_VCLE0: 60235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 60248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 60255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; 60265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; 60275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; 60285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 60305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 60315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == NEON_2RM_VCLE0) { 60325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 60338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGE0: case NEON_2RM_VCLT0: 60365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 60378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 60385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; 60395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; 60405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; 60415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 60435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 60445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == NEON_2RM_VCLT0) { 60455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 60468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCEQ0: 60495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 60508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 60515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; 60525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; 60535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; 60545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 60578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VABS: 60598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 60605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_abs_s8(tmp, tmp); break; 60615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_abs_s16(tmp, tmp); break; 60625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_abs_i32(tmp, tmp); break; 60635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 60648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VNEG: 60675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 60685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 60695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 60708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGT0_F: 607216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 607316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 60745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 607516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus); 60765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 60778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 607816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 60795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGE0_F: 608016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 608116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 60825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 608316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus); 60845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 608516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 60868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 608716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 60885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCEQ0_F: 608916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 609016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 60915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 609216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus); 60935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 609416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 60958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 609616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 60975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLE0_F: 609816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 609916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 61005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 610116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus); 61025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 610316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 61045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 610516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 61065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLT0_F: 610716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner { 610816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner TCGv_ptr fpstatus = get_fpstatus_ptr(1); 61095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 611016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus); 61115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 611216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner tcg_temp_free_ptr(fpstatus); 61135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 611416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner } 61155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VABS_F: 61168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_abs(0); 61178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VNEG_F: 61198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(0); 61208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VSWP: 61225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 61235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, pass, tmp2); 61248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VTRN: 61265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 61278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 61285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_neon_trn_u8(tmp, tmp2); break; 61295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_neon_trn_u16(tmp, tmp2); break; 61305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 61318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, pass, tmp2); 61338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRECPE: 61355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_recpe_u32(tmp, tmp, cpu_env); 61368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRSQRTE: 61385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_rsqrte_u32(tmp, tmp, cpu_env); 61398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRECPE_F: 61418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env); 61428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRSQRTE_F: 61448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env); 61458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */ 61475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_sito(0, 1); 61488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */ 61505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uito(0, 1); 61518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */ 61535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosiz(0, 1); 61548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */ 61565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touiz(0, 1); 61578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 61595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Reserved op values were caught by the 61605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * neon_2rm_sizes[] check earlier. 61615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 61625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 61638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon_2rm_is_float_op(op)) { 61658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, 61668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_reg_offset(rd, pass)); 61678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 61685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 61698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 61728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 10)) == 0) { 61748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VTBL, VTBX. */ 61755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n = ((insn >> 8) & 3) + 1; 61765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((rn + n) > 32) { 61775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This is UNPREDICTABLE; we choose to UNDEF to avoid the 61785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * helper function running off the end of the register file. 61795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 61805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 61815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner n <<= 3; 61838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 61848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, 0); 61858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 61865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 61878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 61888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 61898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 0); 61905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = tcg_const_i32(rn); 61915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp5 = tcg_const_i32(n); 61920b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5); 61935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 61948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 61958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, 1); 61968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 61975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 61988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 61998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp3 = neon_load_reg(rm, 1); 62010b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5); 62025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp5); 62035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp4); 62048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp2); 62055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rd, 1, tmp3); 62065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 62078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x380) == 0) { 62088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VDUP */ 62095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) { 62105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 62115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 62128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 19)) { 62135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 1); 62148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 62155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 62168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) { 62185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8); 62198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 17)) { 62208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 18) & 1) 62215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_high16(tmp); 62228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 62235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 62248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 62265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 62275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 62285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp2); 62298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 62318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 62328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 62338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 62378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 62388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6239e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp14_read(CPUARMState * env, DisasContext *s, uint32_t insn) 62405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 62415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crn = (insn >> 16) & 0xf; 62425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crm = insn & 0xf; 62435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op1 = (insn >> 21) & 7; 62445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op2 = (insn >> 5) & 7; 62455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int rt = (insn >> 12) & 0xf; 62465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 62475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 62485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Minimal set of debug registers, since we don't support debug */ 62495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 0 && crn == 0 && op2 == 0) { 62505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (crm) { 62515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 62525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDIDR: just RAZ. In particular this means the 62535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * "debug architecture version" bits will read as 62545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * a reserved value, which should cause Linux to 62555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * not try to use the debug hardware. 62565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 62575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 62585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 62595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 62605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 62615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 62625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we 62635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * don't implement memory mapped debug components 62645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 62655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (ENABLE_ARCH_7) { 62665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 62675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 62685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 62695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 62705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 62715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 62725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 62735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 62745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 62755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 62765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { 62775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { 62785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEECR */ 62795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) 62805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 62815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(teecr); 62825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rt, tmp); 62835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 62845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 62855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { 62865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEEHBR */ 62875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s) && (env->teecr & 1)) 62885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 62895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(teehbr); 62905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rt, tmp); 62915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 62925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 62935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 62945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n", 62955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1, crn, crm, op2); 62965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 62975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 62985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6299e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp14_write(CPUARMState * env, DisasContext *s, uint32_t insn) 63005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 63015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crn = (insn >> 16) & 0xf; 63025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crm = insn & 0xf; 63035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op1 = (insn >> 21) & 7; 63045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op2 = (insn >> 5) & 7; 63055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int rt = (insn >> 12) & 0xf; 63065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 63075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 63085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Minimal set of debug registers, since we don't support debug */ 63095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 0 && crn == 0 && op2 == 0) { 63105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (crm) { 63115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 63125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDIDR */ 63135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp14_dbgdidr); 63145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 63155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 63165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 63175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 63185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we 63195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * don't implement memory mapped debug components 63205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 63215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (ENABLE_ARCH_7) { 63225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 63235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 63245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 63255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 63285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 63325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { 63335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { 63345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEECR */ 63355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) 63365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 63375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rt); 63385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_set_teecr(cpu_env, tmp); 63395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 63405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 63415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 63425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { 63435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEEHBR */ 63445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s) && (env->teecr & 1)) 63455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 63465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rt); 63475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_cpu_field(tmp, teehbr); 63485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 63495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 63505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 63515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n", 63525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1, crn, crm, op2); 63535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 63545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 63555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6356e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) 63578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 63588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpnum; 63598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 63608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpnum = (insn >> 8) & 0xf; 63618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_XSCALE) 63628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum))) 63638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 63648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 63658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (cpnum) { 63668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 63678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 63688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_IWMMXT)) { 63698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_iwmmxt_insn(env, s, insn); 63708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { 63718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_dsp_insn(env, s, insn); 63728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 63735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto board; 63748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 63758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 63768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_vfp_insn (env, s, insn); 63775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 14: 63785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Coprocessors 7-15 are architecturally reserved by ARM. 63795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner Unfortunately Intel decided to ignore this. */ 63805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_XSCALE)) 63815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto board; 63825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (insn & (1 << 20)) 63835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return disas_cp14_read(env, s, insn); 63845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 63855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return disas_cp14_write(env, s, insn); 63868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 63878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_cp15_insn (env, s, insn); 63888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 63895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner board: 63908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unknown coprocessor. See if the board has hooked it. */ 63918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_cp_insn (env, s, insn); 63928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 63938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 63948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 63958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 63968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Store a 64-bit value to a register pair. Clobbers val. */ 63975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) 63988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 63998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 64005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 64018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, val); 64028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rlow, tmp); 64035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 64048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(val, val, 32); 64058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, val); 64068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rhigh, tmp); 64078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 64088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load a 32-bit value from a register and perform a 64-bit accumulate. */ 64105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow) 64118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 64125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 64138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 64148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Load value and extend to 64 bits. */ 64165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_i64(); 64178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rlow); 64188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp, tmp2); 64195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 64208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(val, val, tmp); 64215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 64228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 64238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load and add a 64-bit value from a register pair. */ 64255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) 64268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 64275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 64285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmpl; 64295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmph; 64308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load 64-bit value rd:rn. */ 64325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmpl = load_reg(s, rlow); 64335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmph = load_reg(s, rhigh); 64345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_i64(); 64355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_concat_i32_i64(tmp, tmpl, tmph); 64365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmpl); 64375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmph); 64388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(val, val, tmp); 64395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 64408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 64418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from a 64-bit value. */ 64435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_logicq_cc(TCGv_i64 val) 64448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 64455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 64468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_logicq_cc(tmp, val); 64478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 64485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 64495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 64505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Load/Store exclusive instructions are implemented by remembering 64525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner the value/address loaded, and seeing if these are the same 64535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner when the store is performed. This should be is sufficient to implement 64545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner the architecturally mandated semantics, and avoids having to monitor 64555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner regular stores. 64565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner In system emulation mode only one CPU will be running at once, so 64585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner this sequence is effectively atomic. In user emulation mode we 64595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner throw an exception and handle the atomic operation elsewhere. */ 64605285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_load_exclusive(DisasContext *s, int rt, int rt2, 64615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 64625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 64635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 64645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 64665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 64675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 64685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 64695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 64705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 64715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 64725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 64735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 64745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 64755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 64765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 64775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 64785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_val, tmp); 64805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 64815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 64825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 64835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp2, addr, 4); 64845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(tmp2, IS_USER(s)); 64855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 64865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_high, tmp); 64875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt2, tmp); 64885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_addr, addr); 64905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 64915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64925285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_clrex(DisasContext *s) 64935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 64945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_addr, -1); 64958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 64968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 64985285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, 64995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 65005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 65015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_test, addr); 65025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_info, 65035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner size | (rd << 4) | (rt << 8) | (rt2 << 12)); 65045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_STREX); 65055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 65065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else 65075285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, 65085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 65095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 65105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 65115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int done_label; 65125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int fail_label; 65135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 65145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) { 65155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [addr] = {Rt}; 65165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {Rd} = 0; 65175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 65185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {Rd} = 1; 65195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } */ 65205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner fail_label = gen_new_label(); 65215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner done_label = gen_new_label(); 65225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); 65235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 65245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 65255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 65265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 65285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 65295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 65315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 65325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 65335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 65355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 65365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 65375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label); 65385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 65395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 65405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 65415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp2, addr, 4); 65425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(tmp2, IS_USER(s)); 65435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 65445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label); 65455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 65465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 65475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rt); 65485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 65495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 65505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 65515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 65535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 65545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 65565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 65575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 65585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 65595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 65605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 65615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 65625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 65635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 4); 65645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rt2); 65655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 65665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 65675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[rd], 0); 65685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_br(done_label); 65695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_label(fail_label); 65705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[rd], 1); 65715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_label(done_label); 65725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_addr, -1); 65735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 65745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 6575a577fcadc0b365ee629aec313f57a65d54fe5d89David 'Digit' Turner 6576e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void disas_arm_insn(CPUARMState * env, DisasContext *s) 65778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 65788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; 65798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 65808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 65818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp3; 65828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 65835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 65845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 6585eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner insn = cpu_ldl_code(env, s->pc); 65865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6587288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_WATCH_CALLSTACK_ARM(s); 65885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 65898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->pc += 4; 65908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 65918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* M variants do not implement ARM mode. */ 65928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) 65938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 65948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cond = insn >> 28; 65958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xf){ 65965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we 65975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * choose to UNDEF. In ARMv5 and above the space is used 65985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * for miscellaneous unconditional instructions. 65995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 66005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 66015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 66028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unconditional instructions. */ 66038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 25) & 7) == 1) { 66048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* NEON Data processing. */ 66058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_NEON)) 66068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 66088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_data_insn(env, s, insn)) 66098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f100000) == 0x04000000) { 66138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* NEON load/store. */ 66148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_NEON)) 66158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 66178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_ls_insn(env, s, insn)) 66188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f30f000) == 0x0510f000) || 66225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f30f010) == 0x0710f000)) { 66235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & (1 << 22)) == 0) { 66245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* PLDW; v7MP */ 66255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7MP)) { 66265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 66275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Otherwise PLD; v5TE+ */ 66305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 66315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 66325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f70f000) == 0x0450f000) || 66345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f70f010) == 0x0650f000)) { 66355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 66365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; /* PLI; V7 */ 66375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f700000) == 0x04100000) || 66395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f700010) == 0x06100000)) { 66405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7MP)) { 66415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 66425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; /* v7MP: Unallocated memory hint: must NOP */ 66445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 66465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0ffffdff) == 0x01010000) { 66478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 66488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* setend */ 66498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) { 66508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* BE8 mode not implemented. */ 66518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0fffff00) == 0x057ff000) { 66558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 4) & 0xf) { 66568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* clrex */ 66578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6K); 66585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_clrex(s); 66598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* dsb */ 66618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* dmb */ 66628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* isb */ 66638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(7); 66648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We don't emulate caches so these are a no-op. */ 66658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 66678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e5fffe0) == 0x084d0500) { 66708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* srs */ 66715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int32_t offset; 66728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 66738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 66758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn & 0x1f); 66765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 66775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op1); 66785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_r13_banked(addr, cpu_env, tmp); 66795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 66808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 23) & 3; 66818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 66828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -4; break; /* DA */ 66835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 0; break; /* IA */ 66845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -8; break; /* DB */ 66858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 4; break; /* IB */ 66868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 66878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 66898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 66908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 66918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 66925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(spsr); 66938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 66948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 66958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 66968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 66978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 66988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -8; break; 66995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 4; break; 67005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -4; break; 67018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 0; break; 67028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 67038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 67055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 67065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op1); 67075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_r13_banked(cpu_env, tmp, addr); 67085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 67095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 67108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 67128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 67145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if ((insn & 0x0e50ffe0) == 0x08100a00) { 67158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rfe */ 67165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int32_t offset; 67178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 67188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 67208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 67218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 67228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 23) & 3; 67238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 67248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -4; break; /* DA */ 67255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 0; break; /* IA */ 67265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -8; break; /* DB */ 67278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 4; break; /* IB */ 67288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 67298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 67318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 67328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load PC into tmp and CPSR into tmp2. */ 67338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, 0); 67348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 67358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, 0); 67368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 67378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 67388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 67398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -8; break; 67405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 4; break; 67415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -4; break; 67428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 0; break; 67438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 67448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 67468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 67478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 67488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 67508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rfe(s, tmp, tmp2); 67525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 67538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e000000) == 0x0a000000) { 67548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch link and change to thumb (blx <offset>) */ 67558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 67568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 67578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc; 67585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 67598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 67608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp); 67618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Sign-extend the 24-bit offset */ 67628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (((int32_t)insn) << 8) >> 8; 67638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset * 4 + bit24 * 2 + (thumb bit) */ 67648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 2) | ((insn >> 23) & 2) | 1; 67658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pipeline offset */ 67668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += 4; 67675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* protected by ARCH(5); above, near the start of uncond block */ 67688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, val); 67698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 67708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e000f00) == 0x0c000100) { 67718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_IWMMXT)) { 67728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* iWMMXt register transfer. */ 67738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (env->cp15.c15_cpar & (1 << 1)) 67748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!disas_iwmmxt_insn(env, s, insn)) 67758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 67768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0fe00000) == 0x0c400000) { 67788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor double register transfer. */ 67795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 67808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0f000010) == 0x0e000010) { 67818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Additional coprocessor register transfer. */ 67825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!disas_coproc_insn(env, s, insn)) { 67835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 67845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 67858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0ff10020) == 0x01000000) { 67868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t mask; 67878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val; 67888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* cps (privileged) */ 67898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 67908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 67918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask = val = 0; 67928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 19)) { 67938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) 67948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_A; 67958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 67968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_I; 67978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) 67988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_F; 67998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 18)) 68008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= mask; 68018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) { 68038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_M; 68048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= (insn & 0x1f); 68058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mask) { 68075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, mask, 0, val); 68088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 68108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond != 0xe) { 68148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if not always execute, we generate a conditional jump to 68158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next instruction */ 68168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 68178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(cond ^ 1, s->condlabel); 68188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 68198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f900000) == 0x03000000) { 68218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 21)) == 0) { 68228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 68238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 68248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = ((insn >> 4) & 0xf000) | (insn & 0xfff); 68258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 22)) == 0) { 68268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVW */ 68275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 68288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 68298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVT */ 68318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 68328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 68338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, val << 16); 68348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 68368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 12) & 0xf) != 0xf) 68388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 16) & 0xf) == 0) { 68408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, insn & 0xff); 68418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* CPSR = immediate */ 68438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xff; 68448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 8) & 0xf) * 2; 68458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 68468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (val >> shift) | (val << (32 - shift)); 68478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn & (1 << 22)) != 0); 68485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val)) 68498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0f900000) == 0x01000000 68538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && (insn & 0x00000090) != 0x00000090) { 68548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* miscellaneous instructions */ 68558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 21) & 3; 68568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 4) & 0xf; 68578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 68588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (sh) { 68598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* move program status register */ 68608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 1) { 68618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PSR = reg */ 68625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rm); 68638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((op1 & 2) != 0); 68645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp)) 68658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* reg = PSR */ 68688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 68698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 2) { 68708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 68718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 68738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 68750b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_cpsr_read(tmp, cpu_env); 68768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 68788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 68808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 68818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 68828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch/exchange thumb (bx). */ 68835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(4T); 68848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 68858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 68868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op1 == 3) { 68878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* clz */ 68885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 68898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 68908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 68918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_clz(tmp, tmp); 68928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 68938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 68978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2: 68988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 68998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(5J); /* bxj */ 69008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Trivial implementation equivalent to bx. */ 69018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 69028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 69038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 69048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 69058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 69088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 != 1) 69098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 69108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 69115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 69128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch link/exchange thumb (blx) */ 69138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 69145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 69158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc); 69168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 69178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 69188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: /* saturating add/subtract */ 69205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 69218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 69228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 692380562525ca945d9e921eb49f96d52f1b5a0e693dDavid 'Digit' Turner tmp = load_reg(s, rm); 69248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 69258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 2) 69260b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_double_saturate(tmp2, cpu_env, tmp2); 69278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 1) 69280b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2); 69298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 69300b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2); 69315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 69328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 69338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: 69355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 1) { 69365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* bkpt */ 69375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 69385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_BKPT); 69395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op1 == 3) { 69405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* smi/smc */ 69415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) { 69425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 69435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 69445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_smc(env, s); 69455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 69465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 69475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 69488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* signed multiply */ 69508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: 69518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 69528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 69535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 69548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 69558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 12) & 0xf; 69568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 69578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 69588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* (32 * 16) >> 16 */ 69598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 69608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 69618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh & 4) 69628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, 16); 69638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 69648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp2); 69655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 69665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 16); 69675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 69685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 69695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 69708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((sh & 2) == 0) { 69718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 69720b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 69735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 69748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 69768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 69778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16 * 16 */ 69788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 69798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 69808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, sh & 2, sh & 4); 69815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 69828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 2) { 69835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 69845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 69855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 69865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rn, rd); 69875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 69885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 69898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 69908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0) { 69918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 69920b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 69935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 69948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 69968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 70008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 70018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (((insn & 0x0e000000) == 0 && 70038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (insn & 0x00000090) != 0x90) || 70048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((insn & 0x0e000000) == (1 << 25))) { 70058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int set_cc, logic_cc, shiftop; 70068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 70078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 21) & 0xf; 70088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project set_cc = (insn >> 20) & 1; 70098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = table_logic_cc[op1] & set_cc; 70108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 70118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing instruction */ 70128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 25)) { 70138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate operand */ 70148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xff; 70158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 8) & 0xf) * 2; 70165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (shift) { 70178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (val >> shift) | (val << (32 - shift)); 70185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 70205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_movi_i32(tmp2, val); 70215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc && shift) { 70225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_set_CF_bit31(tmp2); 70235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 70258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* register */ 70268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 70275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp2 = load_reg(s, rm); 70288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shiftop = (insn >> 5) & 3; 70298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 4))) { 70308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 70315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_arm_shift_im(tmp2, shiftop, shift, logic_cc); 70328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 70338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 70348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 70355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc); 70368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 != 0x0f && op1 != 0x0d) { 70398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 70405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rn); 70415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 70425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGV_UNUSED(tmp); 70438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 70458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(op1) { 70468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00: 70475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 70485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 70495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 70505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01: 70545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 70555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 70565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 70575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x02: 70618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc && rd == 15) { 70628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SUBS r15, ... is used for exception return. */ 70635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) { 70648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 70655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70660b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 70675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_exception_return(s, tmp); 70688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 70695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 70700b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 70715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 70725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 70735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x03: 70785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 70790b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp); 70805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 70815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp2, tmp); 70825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x04: 70865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 70870b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); 70885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 70895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 70905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x05: 70945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 70950b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); 70965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 70975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_add_carry(tmp, tmp, tmp2); 70985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 71008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x06: 71025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 71030b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); 71045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 71055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_sub_carry(tmp, tmp, tmp2); 71065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 71088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x07: 71105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 71110b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp); 71125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 71135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_sub_carry(tmp, tmp2, tmp); 71145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 71168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: 71188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 71195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 71205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 71218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 71238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: 71258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 71265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 71275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 71288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 71308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0a: 71328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 71330b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 71348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 71368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0b: 71388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 71390b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); 71408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 71428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0c: 71445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 71455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 71465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 71475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 71498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0d: 71518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc && rd == 15) { 71528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVS r15, ... is used for exception return. */ 71535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) { 71548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 71555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_exception_return(s, tmp2); 71578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 71595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp2); 71605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp2); 71628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0e: 71655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 71665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 71675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 71685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 71708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 71728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0f: 71735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_not_i32(tmp2, tmp2); 71745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 71755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp2); 71765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp2); 71788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 != 0x0f && op1 != 0x0d) { 71815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 71825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* other instructions */ 71858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 24) & 0xf; 71868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(op1) { 71878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 71888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 71898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* multiplies, extra load/stores */ 71908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 5) & 3; 71918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh == 0) { 71928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0x0) { 71938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 71948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 12) & 0xf; 71958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 71968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 71978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 0xf; 71988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 71998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 2: case 3: case 6: 72008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 32 bit mul */ 72018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 72028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 72038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp, tmp, tmp2); 72045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 72058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 72068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Subtract (mls) */ 72078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 72088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 72098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp2, tmp); 72105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 72118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 72128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Add */ 72138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 72148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 72155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 72168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 72188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 72198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 72208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 72215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 72225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64 bit mul double accumulate (UMAAL) */ 72235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(6); 72248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 72258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 72265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 72275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_addq_lo(s, tmp64, rn); 72285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_addq_lo(s, tmp64, rd); 72295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 72305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 72315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 72325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: case 9: case 10: case 11: 72335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 12: case 13: case 14: case 15: 72345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */ 72355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rs); 72365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 72375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) { 72385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 72395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 72405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 72415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 72425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 21)) { /* mult accumulate */ 72435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rn, rd); 72448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 20)) { 72465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logicq_cc(tmp64); 72475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 72485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 72495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 72508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 72515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 72525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 72538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 72568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 72578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 72588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store exclusive */ 72595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1 = (insn >> 21) & 0x3; 72605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1) 72615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6K); 72625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 72635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6); 72645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new_i32(); 72655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 72668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 72675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (op1) { 72685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: /* ldrex */ 72695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 2); 72705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: /* ldrexd */ 72725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, rd + 1, addr, 3); 72735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: /* ldrexb */ 72755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 0); 72765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 3: /* ldrexh */ 72785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 1); 72795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 72815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner abort(); 72825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 72838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 72855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (op1) { 72865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: /* strex */ 72875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 2); 72885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: /* strexd */ 72905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, rm + 1, addr, 3); 72915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: /* strexb */ 72935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 0); 72945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 3: /* strexh */ 72965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 1); 72975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 72985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 72995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner abort(); 73005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 73018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 73038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SWP instruction */ 73058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 73068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 73078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This is not really atomic. However we know 73088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project we never have multiple CPUs running in parallel, 73098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so it is good enough. */ 73108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 73118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 73128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 73138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld8u(addr, IS_USER(s)); 73148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 73158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, IS_USER(s)); 73178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 73188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 73208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp2); 73218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int address_offset; 73258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int load; 73268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Misc load/store */ 73278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 73288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 73298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 73308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 73318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_datah_offset(s, insn, 0, addr); 73328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project address_offset = 0; 73338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 73348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 73358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(sh) { 73368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 73378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 73388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 73398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 73408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8s(addr, IS_USER(s)); 73418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 73428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 73438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 73448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16s(addr, IS_USER(s)); 73458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 73468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 1; 73488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (sh & 2) { 73495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 73508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* doubleword */ 73518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh & 1) { 73528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 73538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 73548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 73558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 73568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd + 1); 73578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 73588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 0; 73598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 73618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 73628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 73648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 73658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd++; 73668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 1; 73678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project address_offset = -4; 73698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 73718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 73728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 73738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 0; 73748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Perform base writeback before the loaded value to 73768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ensure correct behavior with overlapping index registers. 73778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ldrd with base writeback is is undefined if the 73788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project destination and index registers overlap. */ 73798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 24))) { 73808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_datah_offset(s, insn, address_offset, addr); 73818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 73828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 73838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (address_offset) 73848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, address_offset); 73858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 73868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 73888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (load) { 73908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Complete the load. */ 73918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 73958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 73968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 73978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto do_ldst; 73988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x6: 73998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 74008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 74018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 74028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Armv6 Media instructions. */ 74038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 74048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 74058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 74068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 74078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 23) & 3) { 74088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Parallel add/subtract. */ 74098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 7; 74108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 74118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 74128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 5) & 7; 74138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op1 & 3) == 0 || sh == 5 || sh == 6) 74148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 74158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_parallel_addsub(op1, sh, tmp, tmp2); 74165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 74208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x00700020) == 0) { 74218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Halfword pack. */ 74228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 74238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 74248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 74258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 74268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pkhtb */ 74278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 74288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 74298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, shift); 74308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xffff0000); 74318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp2, tmp2); 74328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pkhbt */ 74348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 74358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp2, tmp2, shift); 74368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 74378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 74388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(tmp, tmp, tmp2); 74405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00200020) == 0x00200000) { 74438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* [us]sat */ 74448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 74468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 74478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 74488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 74498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, shift); 74508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 74528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 16) & 0x1f; 74545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(sh); 74555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) 74560b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_usat(tmp, cpu_env, tmp, tmp2); 74575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 74580b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_ssat(tmp, cpu_env, tmp, tmp2); 74595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00300fe0) == 0x00200f20) { 74628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* [us]sat16 */ 74638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 16) & 0x1f; 74655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(sh); 74665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) 74670b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_usat16(tmp, cpu_env, tmp, tmp2); 74685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 74690b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); 74705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00700fe0) == 0x00000fa0) { 74738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Select bytes. */ 74748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 74758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 74765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 7477e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE)); 74788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); 74795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 74805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x000003e0) == 0x00000060) { 74838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 10) & 3; 74855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* ??? In many cases it's not necessary to do a 74868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rotate, a shift is sufficient. */ 74878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) 74885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(tmp, tmp, shift * 8); 74898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 7; 74908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 74918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxtb16(tmp); break; 74928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_sxtb(tmp); break; 74938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_sxth(tmp); break; 74948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_uxtb16(tmp); break; 74958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: gen_uxtb(tmp); break; 74968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: gen_uxth(tmp); break; 74975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: tcg_temp_free_i32(tmp); goto illegal_op; 74988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != 15) { 75008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 75018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op1 & 3) == 0) { 75028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add16(tmp, tmp2); 75038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 75055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 75098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x003f0f60) == 0x003f0f20) { 75108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rev */ 75118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 75128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 75138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 75148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_revsh(tmp); 75158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 75178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rbit(tmp, tmp); 75188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 75218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rev16(tmp); 75228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 75235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_bswap32_i32(tmp, tmp); 75248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 75268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 75288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 75308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Multiplies (Type 3). */ 75318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 75328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 75338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 75345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Signed multiply most significant [accumulate]. 75355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (SMMUL, SMMLA, SMMLS) */ 75365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 75375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 75385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (rd != 15) { 75395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 75408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 75415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_subq_msw(tmp64, tmp); 75428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_addq_msw(tmp64, tmp); 75448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 75475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u); 75485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 75495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 32); 75505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 75515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 75525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 75535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rn, tmp); 75548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 5)) 75568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 75578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 75588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 75595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This subtraction cannot overflow. */ 75608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 75618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This addition cannot overflow 32 bits; 75635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * however it may overflow considered as a signed 75645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * operation, in which case we must set the Q flag. 75655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 75660b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 75678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 75708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smlald, smlsld */ 75715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 75725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 75735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 75745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rd, rn); 75755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rd, rn, tmp64); 75765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 75778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smuad, smusd, smlad, smlsd */ 75798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) 75808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 75818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 75820b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 75835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp); 75868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 75898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 75908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7); 75918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 75928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Unsigned sum of absolute differences. */ 75938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 75948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 75958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 75968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usad8(tmp, tmp, tmp2); 75975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (rd != 15) { 75995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp2 = load_reg(s, rd); 76008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 76015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 76028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rn, tmp); 76048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x20: case 0x24: case 0x28: case 0x2c: 76068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Bitfield insert/clear. */ 76078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 76088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 76098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 16) & 0x1f; 76108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = i + 1 - shift; 76118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm == 15) { 76125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 76138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 76148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 76168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i != 32) { 76188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 76198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1); 76205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 76218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 76238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */ 76258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */ 76265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6T2); 76278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 76288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 76298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn >> 16) & 0x1f) + 1; 76308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + i > 32) 76318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 76328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i < 32) { 76338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 0x20) { 76348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_ubfx(tmp, shift, (1u << i) - 1); 76358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sbfx(tmp, shift, i); 76378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 76408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 76428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 76438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do_ldst: 76498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Check for undefined extension instructions 76508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * per the ARM Bible IE: 76518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx 76528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 76538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (0xf << 20) | (0xf << 4); 76548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0x7 && ((insn & sh) == sh)) 76558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 76568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 76578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store byte/word */ 76598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 76608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 76618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 76628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); 76638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 76648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_data_offset(s, insn, tmp2); 76658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 76668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 76678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 76688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(tmp2, i); 76698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(tmp2, i); 76718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 76748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 76758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) 76768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, tmp2, i); 76778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 76788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, tmp2, i); 76798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 24))) { 76818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_data_offset(s, insn, tmp2); 76828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp2); 76838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 76848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp2); 76858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 76878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 76898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Complete the load. */ 76905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, rd, tmp); 76918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: 76948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: 76958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 76968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int j, n, user, loaded_base; 76978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv loaded_var; 76988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple words */ 76998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: store correct base if write back */ 77008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 0; 77018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 77028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 77038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; /* only usable in supervisor mode */ 77048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 15)) == 0) 77068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 1; 77078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 77098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 77105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32(4); 77118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* compute total size */ 77138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_base = 0; 77148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(loaded_var); 77158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 0; 77168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 77178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 77188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n++; 77198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: test invalid n == 0 case ? */ 77218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 77228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 77238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre increment */ 77245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 77258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post increment */ 77278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 77308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre decrement */ 77318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -(n * 4)); 77328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post decrement */ 77348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != 1) 77358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); 77368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j = 0; 77398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 77408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 77418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 77428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 77438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 77445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (user) { 77455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(i); 77460b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_set_user_reg(cpu_env, tmp2, tmp); 77475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 77485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 77498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (i == rn) { 77508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_var = tmp; 77518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_base = 1; 77528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, i, tmp); 77548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 77578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i == 15) { 77588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* special case: r15 = PC + 8 */ 77598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (long)s->pc + 4; 77605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 77618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 77628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (user) { 77635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 77645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(i); 77650b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_get_user_reg(tmp, cpu_env, tmp2); 77665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 77678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 77698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 77718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j++; 77738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no need to add after the last transfer */ 77748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (j != n) 77755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 77768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 77798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* write back */ 77808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 77818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 77828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre increment */ 77838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post increment */ 77855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 77868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 77898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre decrement */ 77908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != 1) 77918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); 77928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post decrement */ 77948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -(n * 4)); 77958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 77988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 77995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 78008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 78028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (loaded_base) { 78038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, loaded_var); 78048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 22)) && !user) { 78068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Restore CPSR from SPSR. */ 78078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 78088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(tmp, 0xffffffff); 78095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 78108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 78118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: 78158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 78168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 78178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 78185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 78198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch (and link) */ 78208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (int32_t)s->pc; 78218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 78225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 78238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 78248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp); 78258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (((int32_t)insn << 8) >> 8); 78278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 2) + 4; 78288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 78298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 78328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: 78338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 78348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor. */ 78358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_coproc_insn(env, s, insn)) 78368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 78378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: 78398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* swi */ 78408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 78418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_SWI; 78428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 78448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project illegal_op: 78455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_UDEF); 78468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 78508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return true if this is a Thumb-2 logical op. */ 78528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 78538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectthumb2_logic_op(int op) 78548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 78558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (op < 8); 78568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 78578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero 78598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project then set condition code flags based on the result of the operation. 78608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project If SHIFTER_OUT is nonzero then set the carry flag for logical operations 78618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project to the high bit of T1. 78628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Returns zero if the opcode is valid. */ 78638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 78655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnergen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1) 78668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 78678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int logic_cc; 78688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = 0; 78708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 78718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* and */ 78725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(t0, t0, t1); 78738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 78748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* bic */ 78765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(t0, t0, t1); 78778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 78788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* orr */ 78805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t0, t0, t1); 78818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 78828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* orn */ 78845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_orc_i32(t0, t0, t1); 78858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 78868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* eor */ 78885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(t0, t0, t1); 78898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 78908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* add */ 78928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 78930b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(t0, cpu_env, t0, t1); 78948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 78955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, t1); 78968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 78978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* adc */ 78988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 78990b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_adc_cc(t0, cpu_env, t0, t1); 79008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 79015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_adc(t0, t1); 79028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 79038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* sbc */ 79048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 79050b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sbc_cc(t0, cpu_env, t0, t1); 79068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 79075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_sub_carry(t0, t0, t1); 79088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 79098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* sub */ 79108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 79110b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(t0, cpu_env, t0, t1); 79128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 79135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(t0, t0, t1); 79148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 79158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* rsb */ 79168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 79170b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(t0, cpu_env, t1, t0); 79188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 79195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(t0, t1, t0); 79208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 79218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* 5, 6, 7, 9, 12, 15. */ 79228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 79238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc) { 79255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(t0); 79268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shifter_out) 79275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_CF_bit31(t1); 79288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 79308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 79318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 79328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction 79338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project is not legal. */ 7934e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1) 79358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 79368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t insn, imm, shift, offset; 79378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd, rn, rm, rs; 79388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 79398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 79408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp3; 79418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 79425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 79438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 79448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shiftop; 79458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int conds; 79468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int logic_cc; 79478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 79488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(arm_feature(env, ARM_FEATURE_THUMB2) 79498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || arm_feature (env, ARM_FEATURE_M))) { 79508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Thumb-1 cores may need to treat bl and blx as a pair of 79518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16-bit instructions to get correct prefetch abort behavior. */ 79528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insn = insn_hw1; 79538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 12)) == 0) { 79545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 79558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Second half of blx. */ 79568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0x7ff) << 1); 79578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 79588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, offset); 79598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); 79608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 79615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 79628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc | 1); 79638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 79648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 79658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 79668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 79688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Second half of bl. */ 79698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0x7ff) << 1) | 1; 79708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 79718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, offset); 79728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 79735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 79748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc | 1); 79758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 79768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 79778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 79788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((s->pc & ~TARGET_PAGE_MASK) == 0) { 79808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Instruction spans a page boundary. Implement it as two 79818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16-bit instructions in case the second half causes an 79828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project prefetch abort. */ 79838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 21) >> 9; 79845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset); 79858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 79868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through to 32-bit decode. */ 79888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7990eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner insn = cpu_lduw_code(env, s->pc); 79915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine s->pc += 2; 79925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner insn |= (uint32_t)insn_hw1 << 16; 79935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 79948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0xf800e800) != 0xf000e800) { 79958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 79968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 79988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 79998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 12) & 0xf; 80008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0xf; 80018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 80028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 25) & 0xf) { 80038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 2: case 3: 80048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16-bit instructions. Should never happen. */ 80058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 80068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 80078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 80088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Other load/store, table branch. */ 80098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x01200000) { 80108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store doubleword. */ 80118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 80125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 80138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, s->pc & ~3); 80148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 80168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) * 4; 80188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) 80198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset; 80208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 80218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 80228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 80238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 80258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ldrd */ 80268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 80278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rs, tmp); 80288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 80298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 80308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 80318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* strd */ 80338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 80348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 80358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 80368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 80378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 80388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 80408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 80418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) 80428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 80438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset - 4); 80448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 80458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 80478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 23)) == 0) { 80498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store exclusive word. */ 80505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new(); 80515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 80525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2); 80538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 80545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rs, 15, addr, 2); 80558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rs, 15, addr, 2); 80578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 80598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 6)) == 0) { 80608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Table Branch. */ 80618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 80625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 80638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, s->pc); 80648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 80668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 80688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 80698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 80708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* tbh */ 80718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 80725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 80738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 80748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* tbb */ 80755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 80768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 80778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 80798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, 1); 80808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, s->pc); 80818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 15, tmp); 80828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store exclusive byte/halfword/doubleword. */ 80845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 80858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0x3; 80865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 2) { 80875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 80885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 80895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new(); 80905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 80918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 80925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rs, rd, addr, op); 80938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rm, rs, rd, addr, op); 80958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 80978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store multiple, RFE, SRS. */ 81008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 23) & 1) == ((insn >> 24) & 1)) { 81018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not available in user mode. */ 81028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 81038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 81048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 81058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rfe */ 81068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 81078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) 81088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -8); 81098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load PC into tmp and CPSR into tmp2. */ 81108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, 0); 81118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 81128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, 0); 81138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 81148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 81158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 81168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 81178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -4); 81198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 81218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 81238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rfe(s, tmp, tmp2); 81258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* srs */ 81278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn & 0x1f); 81285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 81295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op); 81305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_r13_banked(addr, cpu_env, tmp); 81315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 81328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) { 81338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -8); 81348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 81368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 81378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 81385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 81390b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_cpsr_read(tmp, cpu_env); 81408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 81418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 81428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) { 81438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -4); 81448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 81468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op); 81485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_r13_banked(cpu_env, tmp, addr); 81495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 81508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 81528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int i, loaded_base = 0; 81565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv loaded_var; 81578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store multiple. */ 81588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 81598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 81608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 81618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 81628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += 4; 81638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 81658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 81668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 81685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(loaded_var); 81695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(4); 81708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 81718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << i)) == 0) 81728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 81738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 81748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load. */ 81758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 81768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i == 15) { 81778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 81785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (i == rn) { 81795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_var = tmp; 81805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_base = 1; 81818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, i, tmp); 81838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Store. */ 81868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 81878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 81888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 81905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 81915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (loaded_base) { 81925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, loaded_var); 81938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 81958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 81968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base register writeback. */ 81978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 81988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 81998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fault if writeback register is in register list. */ 82018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << rn)) 82028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 82038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 82048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 82055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 82068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: 82115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 82128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 0xf; 82135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 6) { 82145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Halfword pack. */ 82155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 82165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 82175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3); 82185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 82195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* pkhtb */ 82205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift == 0) 82215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = 31; 82225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sari_i32(tmp2, tmp2, shift); 82235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xffff0000); 82245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp2, tmp2); 82255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 82265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* pkhbt */ 82275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift) 82285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, shift); 82295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp, tmp); 82305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 82315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 82325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 82335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 82355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 82365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Data processing register constant shift. */ 82375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 82385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 82395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 82405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 82415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 82425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 82435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 82445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 82455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shiftop = (insn >> 4) & 3; 82465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); 82475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner conds = (insn & (1 << 20)) != 0; 82485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner logic_cc = (conds && thumb2_logic_op(op)); 82495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_arm_shift_im(tmp2, shiftop, shift, logic_cc); 82505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2)) 82515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 82525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd != 15) { 82545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 82555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 82565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 82575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 82585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 82598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* Misc data processing. */ 82618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 22) & 6) | ((insn >> 7) & 1); 82628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 4 && (insn & 0xf000) != 0xf000) 82638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 82648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 82658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Register controlled shift. */ 82668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 82678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 82688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x70) != 0) 82698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 82708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 3; 82718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = (insn & (1 << 20)) != 0; 82728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_reg(tmp, op, tmp2, logic_cc); 82738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc) 82748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 82755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 82768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* Sign/zero extend. */ 82788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 82798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 3; 82805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* ??? In many cases it's not necessary to do a 82818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rotate, a shift is sufficient. */ 82828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) 82835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(tmp, tmp, shift * 8); 82848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 82858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 82868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxth(tmp); break; 82878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_uxth(tmp); break; 82888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_sxtb16(tmp); break; 82898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_uxtb16(tmp); break; 82908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_sxtb(tmp); break; 82918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: gen_uxtb(tmp); break; 82928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: goto illegal_op; 82938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != 15) { 82958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 82968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op >> 1) == 1) { 82978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add16(tmp, tmp2); 82988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 82998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 83005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 83048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* SIMD add/subtract. */ 83068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 83078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 7; 83088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 3) == 3 || (shift & 3) == 3) 83098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 83118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 83128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_thumb2_parallel_addsub(op, shift, tmp, tmp2); 83135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 83158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Other data processing. */ 83178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); 83188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 4) { 83198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Saturating add/subtract. */ 83208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 83218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 83228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 83230b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_double_saturate(tmp, cpu_env, tmp); 83245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op & 2) 83250b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp); 83268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 83270b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2); 83285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 83318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 83328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0a: /* rbit */ 83338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rbit(tmp, tmp); 83348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: /* rev */ 83365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_bswap32_i32(tmp, tmp); 83378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: /* rev16 */ 83398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rev16(tmp); 83408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0b: /* revsh */ 83428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_revsh(tmp); 83438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10: /* sel */ 83458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 83465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 8347e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE)); 83488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); 83495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 83505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x18: /* clz */ 83538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_clz(tmp, tmp); 83548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 83568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 83608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */ 83628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0xf; 83638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 83648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 83658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 7) { 83668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* 32 x 32 -> 32 */ 83678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp, tmp, tmp2); 83685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 83708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 83718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 83728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp2, tmp); 83738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 83748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 83755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* 16 x 16 -> 32 */ 83798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, op & 2, op & 1); 83805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 83828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 83830b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 83845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Dual multiply add. */ 83888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* Dual multiply subtract. */ 83898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 83908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 83918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 83928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 83935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This subtraction cannot overflow. */ 83948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 83958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This addition cannot overflow 32 bits; 83975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * however it may overflow considered as a signed 83985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * operation, in which case we must set the Q flag. 83995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 84000b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 84018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) 84048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 84058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 84060b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 84075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* 32 * 16 -> 32msb */ 84118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 84128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, 16); 84138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 84148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp2); 84155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 84165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 16); 84175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 84185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 84195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 84208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) 84218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 84228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 84230b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_setq(tmp, cpu_env, tmp, tmp2); 84245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */ 84285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 84298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 84305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rs); 84315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 20)) { 84325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_addq_msw(tmp64, tmp); 84338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_subq_msw(tmp64, tmp); 84358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 4)) { 84385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u); 84395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 84405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 32); 84415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 84425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 84435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 84448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* Unsigned sum of absolute differences. */ 84468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usad8(tmp, tmp, tmp2); 84475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 84498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 84508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 84515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 84568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: /* 64-bit multiply, Divide. */ 84588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70); 84598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 84608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 84618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 0x50) == 0x10) { 84628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* sdiv, udiv */ 84638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_DIV)) 84648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 84658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x20) 84668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_udiv(tmp, tmp, tmp2); 84678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 84688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sdiv(tmp, tmp, tmp2); 84695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 84718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((op & 0xe) == 0xc) { 84728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Dual multiply accumulate long. */ 84738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 84748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 84758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 84768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x10) { 84778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 84788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 84808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* BUGFIX */ 84835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 84845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 84855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 84865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rs, rd); 84875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rs, rd, tmp64); 84885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 84898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x20) { 84918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unsigned 64-bit multiply */ 84925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 84938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 8) { 84958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smlalxy */ 84968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, op & 2, op & 1); 84975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 84985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 84995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 85005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 85018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Signed 64-bit multiply */ 85035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 85048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 4) { 85078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* umaal */ 85085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq_lo(s, tmp64, rs); 85095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq_lo(s, tmp64, rd); 85108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op & 0x40) { 85118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 64-bit accumulate. */ 85125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rs, rd); 85138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rs, rd, tmp64); 85155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 85168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: case 14: case 15: 85218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor. */ 85228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 24) & 3) == 3) { 85238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Translate into the equivalent ARM encoding. */ 85245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28); 85258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_data_insn(env, s, insn)) 85268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 28)) 85298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_coproc_insn (env, s, insn)) 85318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: case 10: case 11: 85358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 15)) { 85368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Branches, misc control. */ 85378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x5000) { 85388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unconditional branch. */ 85398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* signextend(hw1[10:0]) -> offset[:12]. */ 85408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff; 85418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* hw1[10:0] -> offset[11:1]. */ 85428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & 0x7ff) << 1; 85438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22] 85448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset[24:22] already have the same value because of the 85458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sign extension above. */ 85468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset ^= ((~insn) & (1 << 13)) << 10; 85478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset ^= ((~insn) & (1 << 11)) << 11; 85488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 14)) { 85508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Branch and link. */ 85515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[14], s->pc | 1); 85528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += s->pc; 85558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 12)) { 85568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* b/bl */ 85578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, offset); 85588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* blx */ 85608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset &= ~(uint32_t)2; 85615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* thumb2 bx, no need to check */ 85628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, offset); 85638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (((insn >> 23) & 7) == 7) { 85658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Misc control */ 85668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 13)) 85678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 26)) { 85705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Secure monitor call / smc (v6Z) */ 85715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) { 85725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 85735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 85745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_smc(env, s); 85758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 85778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 85788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* msr cpsr. */ 85798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 85808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 85818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(insn & 0xff); 85828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 85835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 85845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 85858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 85868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* fall through */ 85898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* msr spsr. */ 85908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) 85918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 85935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr(s, 85948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project msr_mask(env, s, (insn >> 8) & 0xf, op == 1), 85955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op == 1, tmp)) 85968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* cps, nop-hint. */ 85998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 8) & 7) == 0) { 86008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, insn & 0xff); 86018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Implemented as NOP in user mode. */ 86038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 86048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 86068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = 0; 86078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 86088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 86098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_A; 86108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) 86118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_I; 86128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 5)) 86138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_F; 86148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) 86158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = CPSR_A | CPSR_I | CPSR_F; 86168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 86188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= 0x1f; 86198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (insn & 0x1f); 86208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 86225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, offset, 0, imm); 86238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Special control operations. */ 86265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 86278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0xf; 86288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 86298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* clrex */ 86305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_clrex(s); 86318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* dsb */ 86338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* dmb */ 86348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* isb */ 86358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* These execute as NOPs. */ 86368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 86388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 86398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* bxj */ 86428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Trivial implementation equivalent to bx. */ 86438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 86448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 86458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* Exception return. */ 86475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (IS_USER(s)) { 86485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 86495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 86505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn != 14 || rd != 15) { 86515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 86525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 86535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 86545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_subi_i32(tmp, tmp, insn & 0xff); 86555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_return(s, tmp); 86565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 86578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* mrs cpsr. */ 86585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 86598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 86608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(insn & 0xff); 86618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_mrs(tmp, cpu_env, addr); 86625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 86638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86640b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_cpsr_read(tmp, cpu_env); 86658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 86678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* mrs spsr. */ 86698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not accessible in user mode. */ 86708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) || IS_M(env)) 86718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 86728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 86738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 86748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Conditional branch. */ 86798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 22) & 0xf; 86808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Generate a conditional jump to next instruction. */ 86818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 86828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(op ^ 1, s->condlabel); 86838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 86848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 86858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[11:1] = insn[10:0] */ 86868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0x7ff) << 1; 86878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[17:12] = insn[21:16]. */ 86888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & 0x003f0000) >> 4; 86898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[31:20] = insn[26]. */ 86908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11; 86918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[18] = insn[13]. */ 86928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & (1 << 13)) << 5; 86938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[19] = insn[11]. */ 86948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & (1 << 11)) << 8; 86958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 86968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* jump to the offset */ 86978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, s->pc + offset); 86988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Data processing immediate. */ 87018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 25)) { 87028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 87038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 87048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Bitfield/Saturate. */ 87068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 7; 87078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0x1f; 87088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); 87098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 87105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 87118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 87128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 87148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 87168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Signed bitfield extract. */ 87178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm++; 87188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + imm > 32) 87198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 32) 87218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sbfx(tmp, shift, imm); 87228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* Unsigned bitfield extract. */ 87248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm++; 87258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + imm > 32) 87268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 32) 87288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_ubfx(tmp, shift, (1u << imm) - 1); 87298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Bitfield insert/clear. */ 87318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < shift) 87328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = imm + 1 - shift; 87348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm != 32) { 87358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 87368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1); 87375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 87388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 87418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Saturate. */ 87438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) { 87448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 87458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, shift); 87468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 87488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = tcg_const_i32(imm); 87508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 4) { 87518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unsigned. */ 87528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 1) && shift == 0) 87530b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_usat16(tmp, cpu_env, tmp, tmp2); 87548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87550b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_usat(tmp, cpu_env, tmp, tmp2); 87568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Signed. */ 87588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 1) && shift == 0) 87590b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); 87608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87610b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_ssat(tmp, cpu_env, tmp, tmp2); 87628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 87648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 87678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ((insn & 0x04000000) >> 15) 87698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | ((insn & 0x7000) >> 4) | (insn & 0xff); 87708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 87718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16-bit immediate. */ 87728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (insn >> 4) & 0xf000; 87738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 87748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* movt */ 87758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 87768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 87778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, imm << 16); 87788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* movw */ 87805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 87818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, imm); 87828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Add/sub 12-bit immediate. */ 87858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 87868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = s->pc & ~(uint32_t)3; 87878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 87888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset -= imm; 87898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += imm; 87915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 87928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, offset); 87938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 87958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 87968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(tmp, tmp, imm); 87978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, imm); 87998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 88028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 88048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shifter_out = 0; 88058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* modified 12-bit immediate. */ 88068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12); 88078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (insn & 0xff); 88088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shift) { 88098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* XY */ 88108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing to do. */ 88118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* 00XY00XY */ 88138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 88148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* XY00XY00 */ 88168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 88178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 8; 88188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* XYXYXYXY */ 88208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 88218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 8; 88228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Rotated constant. */ 88248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (shift << 1) | (imm >> 7); 88258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= 0x80; 88268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = imm << (32 - shift); 88278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out = 1; 88288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 88315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, imm); 88328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 88335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 88345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 88355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 88365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 88375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 88385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 0xf; 88408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0, 88415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shifter_out, tmp, tmp2)) 88428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 88435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 88448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0xf; 88458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) { 88465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 88475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 88485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 88498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* Load/store single data item. */ 88548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 88558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int postinc = 0; 88568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int writeback = 0; 88578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int user; 88588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x01100000) == 0x01000000) { 88598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_ls_insn(env, s, insn)) 88608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 88618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op = ((insn >> 21) & 3) | ((insn >> 22) & 4); 88645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rs == 15) { 88655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 20))) { 88665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 88675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op != 2) { 88695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Byte or halfword load space with dest == r15 : memory hints. 88705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Catch them early so we don't emit pointless addressing code. 88715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This space is a mix of: 88725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * PLD/PLDW/PLI, which we implement as NOPs (note that unlike 88735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP 88745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * cores) 88755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * unallocated hints, which must be treated as NOPs 88765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * UNPREDICTABLE space, which we NOP or UNDEF depending on 88775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * which is easiest for the decoding logic 88785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Some space which must UNDEF 88795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 88805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op1 = (insn >> 23) & 3; 88815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op2 = (insn >> 6) & 0x3f; 88825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op & 2) { 88835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 88845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 88865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNPREDICTABLE or unallocated hint */ 88875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 88885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 & 1) { 88905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; /* PLD* or unallocated hint */ 88915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) { 88935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; /* PLD* or unallocated hint */ 88945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF space, or an UNPREDICTABLE */ 88965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 88975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = IS_USER(s); 89008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 89015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 89028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PC relative. */ 89038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* s->pc has already been incremented by 4. */ 89048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = s->pc & 0xfffffffc; 89058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 89068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm += insn & 0xfff; 89078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 89088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm -= insn & 0xfff; 89098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, imm); 89108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 89128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 89138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Positive offset. */ 89148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0xfff; 89158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 89168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0xff; 89185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch ((insn >> 8) & 0xf) { 89195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0x0: /* Shifted Register. */ 89208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 0xf; 89215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift > 3) { 89225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 89245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 89258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 89268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 89278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 89288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 89295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 89308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xc: /* Negative offset. */ 89328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -imm); 89338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xe: /* User privilege. */ 89358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 89368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 1; 89378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0x9: /* Post-decrement. */ 89398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = -imm; 89408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 89415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xb: /* Post-increment. */ 89428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project postinc = 1; 89438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project writeback = 1; 89448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xd: /* Pre-decrement. */ 89468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = -imm; 89478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 89485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xf: /* Pre-increment. */ 89498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 89508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project writeback = 1; 89518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 89535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 89558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 89598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load. */ 89605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 89615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tmp = gen_ld8u(addr, user); break; 89625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: tmp = gen_ld8s(addr, user); break; 89635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: tmp = gen_ld16u(addr, user); break; 89645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: tmp = gen_ld16s(addr, user); break; 89655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tmp = gen_ld32(addr, user); break; 89665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 89675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 89695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 89705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rs == 15) { 89715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_bx(s, tmp); 89728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rs, tmp); 89748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Store. */ 89778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 89788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 89798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_st8(tmp, addr, user); break; 89808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_st16(tmp, addr, user); break; 89818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_st32(tmp, addr, user); break; 89825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 89835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 89858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (postinc) 89888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 89898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (writeback) { 89908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 89918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 89978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 89988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 90008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op: 90018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 90028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 90038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9004e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void disas_thumb_insn(CPUARMState *env, DisasContext *s) 90058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 90068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val, insn, op, rm, rn, rd, shift, cond; 90078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 90088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 90098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 90108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 90118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 90128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9013a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (s->condexec_mask) { 9014a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine cond = s->condexec_cond; 90155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (cond != 0x0e) { /* Skip conditional when condition is AL. */ 90165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->condlabel = gen_new_label(); 90175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_test_cc(cond ^ 1, s->condlabel); 90185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->condjmp = 1; 90195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 90208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9022eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner insn = cpu_lduw_code(env, s->pc); 90235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 9024288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_WATCH_CALLSTACK_THUMB(s); 9025288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner 90268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->pc += 2; 90278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 90288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (insn >> 12) { 90298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: 90305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 90318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 90328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 11) & 3; 90338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 3) { 90348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* add/subtract */ 90358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 90365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 90378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 90388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 90395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 90405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, (insn >> 6) & 7); 90418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* reg */ 90438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 6) & 7; 90445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 90458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) { 90478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 90485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 90498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 90500b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 90518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 90535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 90548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 90550b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); 90568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 90585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 90598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* shift immediate */ 90618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 90628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 6) & 0x1f; 90638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 90648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0); 90658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 90668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 90678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 90688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: case 3: 90718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arithmetic large immediate */ 90728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 11) & 3; 90738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0x7; 90745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 0) { /* mov */ 90755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 90765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, insn & 0xff); 90778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 90785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 90795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 90805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 90815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 90825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 90835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, insn & 0xff); 90845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 90855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: /* cmp */ 90860b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 90875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 90885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 90895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 90905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* add */ 90915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (s->condexec_mask) 90925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 90935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 90940b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); 90955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 90965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 90975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 90985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: /* sub */ 90995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (s->condexec_mask) 91005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 91015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 91020b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 91035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 91045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 91055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 91065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 91078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 91108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 91118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 91128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load pc-relative. Bit 1 of PC is ignored. */ 91138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = s->pc + 2 + ((insn & 0xff) * 4); 91148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val &= ~(uint32_t)2; 91155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 91168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, val); 91178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 91185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 91198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 91208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 91238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing extended or blx */ 91248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn & 7) | ((insn >> 4) & 8); 91258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 0xf; 91268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 3; 91278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 91288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* add */ 91295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 91305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 91315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 91325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 91335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 91348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* cmp */ 91365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 91375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 91380b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 91395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 91405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 91418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* mov/cpy */ 91435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rm); 91445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 91458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3:/* branch [and link] exchange thumb register */ 91478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 91488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 91495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 91508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc | 1; 91515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 91528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, val); 91538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 91548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* already thumb, no need to check */ 91568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 91578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing register */ 91638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 91648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 91658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 6) & 0xf; 91668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 2 || op == 3 || op == 4 || op == 7) { 91678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* the shift/rotate ops want the operands backwards */ 91688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = rm; 91698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rd; 91708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = val; 91718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 1; 91728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 91738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 0; 91748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 9) { /* neg */ 91775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 91785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 91795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op != 0xf) { /* mvn doesn't read its first operand */ 91805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 91815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 91825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp); 91835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 91848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 91868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 91878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* and */ 91885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 91898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 91918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: /* eor */ 91935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 91948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 91968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2: /* lsl */ 91988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 91995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shl(tmp2, tmp2, tmp); 92008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92010b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp); 92025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 92038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: /* lsr */ 92068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 92075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shr(tmp2, tmp2, tmp); 92088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92090b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp); 92105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 92118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: /* asr */ 92148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 92155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sar(tmp2, tmp2, tmp); 92168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92170b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp); 92185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 92198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: /* adc */ 92228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 92235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_adc(tmp, tmp2); 92248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 92250b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2); 92268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x6: /* sbc */ 92288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 92295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_sub_carry(tmp, tmp, tmp2); 92308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 92310b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2); 92328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: /* ror */ 92348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 92355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0x1f); 92365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotr_i32(tmp2, tmp2, tmp); 92378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92380b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp); 92395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 92408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* tst */ 92435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 92445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 92458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 92468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: /* neg */ 92488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 92495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_neg_i32(tmp, tmp2); 92508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 92510b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 92528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: /* cmp */ 92540b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2); 92558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 92568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: /* cmn */ 92580b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_add_cc(tmp, cpu_env, tmp, tmp2); 92598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 92608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: /* orr */ 92625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 92638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 92645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 92658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: /* mul */ 92675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mul_i32(tmp, tmp, tmp2); 92688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 92695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 92708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* bic */ 92725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 92738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 92745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 92758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: /* mvn */ 92775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp2, tmp2); 92788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 92795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 92808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 1; 92818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rd; 92828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 16) { 92855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (val) { 92865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rm, tmp2); 92875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op != 0xf) 92885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 92895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 92905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 92915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 92925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 92935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 92945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 92955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 92968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 93008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store register offset. */ 93018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 93028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 93038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 6) & 7; 93048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 9) & 7; 93058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 93068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 93078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 93085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 93098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 3) /* store */ 93118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 93128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 93148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* str */ 93158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 93168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* strh */ 93188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 93198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* strb */ 93218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 93228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* ldrsb */ 93248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8s(addr, IS_USER(s)); 93258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* ldr */ 93278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 93288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* ldrh */ 93308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 93318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* ldrb */ 93338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 93348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* ldrsh */ 93368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16s(addr, IS_USER(s)); 93378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op >= 3) /* load */ 93408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 93415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 93428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 93458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store word immediate offset */ 93468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 93478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 93488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 93498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 4) & 0x7c; 93508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 93518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 93538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 93548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 93558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 93568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 93578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 93588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 93598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 93608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 93628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 93658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store byte immediate offset */ 93668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 93678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 93688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 93698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 6) & 0x1f; 93708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 93718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 93738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 93748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 93758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 93768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 93778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 93788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 93798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 93808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 93828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: 93858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store halfword immediate offset */ 93868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 93878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 93888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 93898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 5) & 0x3e; 93908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 93918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 93938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 93948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 93958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 93968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 93978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 93988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 93998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 94008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 94028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: 94058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store from stack */ 94068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 94078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, 13); 94088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xff) * 4; 94098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 94108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 94128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 94138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 94148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 94158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 94178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 94188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 94198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 94218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 94248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* add to high reg */ 94258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 94268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 94278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SP */ 94288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 13); 94298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PC. bit 1 is ignored. */ 94315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 94328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2); 94338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xff) * 4; 94358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, val); 94368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 94378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 94408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* misc */ 94418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 94428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 94438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 94448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* adjust stack pointer */ 94458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 13); 94468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0x7f) * 4; 94478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 94488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -(int32_t)val; 94498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, val); 94508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 13, tmp); 94518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* sign/zero extend. */ 94548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 94558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 94568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 94578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 94588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 94598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxth(tmp); break; 94608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_sxtb(tmp); break; 94618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_uxth(tmp); break; 94628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_uxtb(tmp); break; 94638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 94658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: case 0xc: case 0xd: 94678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push/pop */ 94688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, 13); 94698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) 94708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 94718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 94728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 94738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 94748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 94758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += 4; 94768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 11)) == 0) { 94788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 94798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(4); 94818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 94828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 94838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 94848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pop */ 94858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 94868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, i, tmp); 94878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push */ 94898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 94908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 94918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* advance to the next address. */ 94935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 94948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp); 94978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 94988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 94998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pop pc */ 95008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 95018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* don't set the pc until the rest of the instruction 95028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project has completed */ 95038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 95048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push lr */ 95058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 95068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 95078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 95098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 95118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 11)) == 0) { 95128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 95138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* write back the new stack pointer */ 95158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 13, addr); 95168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* set the new PC value */ 95175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0900) == 0x0900) { 95185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, 15, tmp); 95195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 95208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: case 3: case 9: case 11: /* czb */ 95238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 7; 95248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 95258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 95268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 95278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) 95288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel); 95298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 95308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel); 95315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 95328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3; 95338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc + 2; 95348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += offset; 95358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 95368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* IT, nop-hint. */ 95398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0xf) == 0) { 95408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, (insn >> 4) & 0xf); 95418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If Then. */ 9544a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine s->condexec_cond = (insn >> 4) & 0xe; 9545a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine s->condexec_mask = insn & 0x1f; 95468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* No actual code generated for this insn, just setup state. */ 95478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* bkpt */ 95505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 95515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 2, EXCP_BKPT); 95528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: /* rev */ 95558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 95568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 0x7; 95578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 0x7; 95588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 95598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 95605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 95618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_rev16(tmp); break; 95628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_revsh(tmp); break; 95638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: goto illegal_op; 95648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 95668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* cps */ 95698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 95708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 95718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 95738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tcg_const_i32((insn & (1 << 4)) != 0); 95748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PRIMASK */ 95758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 1) { 95768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(16); 95778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 95785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 95798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FAULTMASK */ 95818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 2) { 95828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(17); 95838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 95845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 95858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 95878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 95888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 95898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) 95908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = CPSR_A | CPSR_I | CPSR_F; 95918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 95928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 0; 95935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, ((insn & 7) << 6), 0, shift); 95948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 95988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef; 95998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: 96035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { 96048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple */ 96055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv loaded_var; 96065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(loaded_var); 96078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 8) & 0x7; 96088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 96098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 96108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 96118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 96128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 96138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 96145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (i == rn) { 96155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_var = tmp; 96165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 96175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, i, tmp); 96185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 96198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 96208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 96218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 96228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 96238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* advance to the next address */ 96258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 96268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << rn)) == 0) { 96295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* base reg not in list: base register writeback */ 96308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 96318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 96325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* base reg in list: if load, complete it now */ 96335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 11)) { 96345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, loaded_var); 96355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 96365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 96378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 96408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: 96418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* conditional branch or swi */ 96428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cond = (insn >> 8) & 0xf; 96438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xe) 96448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef; 96458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xf) { 96478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* swi */ 96488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 96498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_SWI; 96508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* generate a conditional jump to next instruction */ 96538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 96548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(cond ^ 1, s->condlabel); 96558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 96568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* jump to the offset */ 96588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc + 2; 96598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 24) >> 24; 96608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += offset << 1; 96618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 96628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: 96658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 96668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_thumb2_insn(env, s, insn)) 96678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef32; 96688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* unconditional branch */ 96718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc; 96728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 21) >> 21; 96738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 1) + 2; 96748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 96758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 96788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_thumb2_insn(env, s, insn)) 96798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef32; 96808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 96838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef32: 96845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_UDEF); 96858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 96868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op: 96878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef: 96885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 2, EXCP_UDEF); 96898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 96908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generate intermediate code in gen_opc_buf and gen_opparam_buf for 96928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project basic block 'tb'. If search_pc is TRUE, also generate PC 96938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project information for each intermediate instruction. */ 9694e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void gen_intermediate_code_internal(CPUARMState *env, 96958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TranslationBlock *tb, 96968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int search_pc) 96978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 96988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DisasContext dc1, *dc = &dc1; 96995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CPUBreakpoint *bp; 97008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t *gen_opc_end; 97018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int j, lj; 97028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong pc_start; 97038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t next_page_start; 97048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int num_insns; 97058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int max_insns; 97068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* generate intermediate code */ 97088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pc_start = tb->pc; 97098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->tb = tb; 97118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9712975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; 97138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_NEXT; 97158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc = pc_start; 9716fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner dc->singlestep_enabled = ENV_GET_CPU(env)->singlestep_enabled; 97178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 97185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->thumb = ARM_TBFLAG_THUMB(tb->flags); 97195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; 97205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; 97218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY) 97225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); 97238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 9724288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_START_CODEGEN(search_pc); 97255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); 97265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); 97275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); 97285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F0s = tcg_temp_new_i32(); 97295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F1s = tcg_temp_new_i32(); 97305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F0d = tcg_temp_new_i64(); 97315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F1d = tcg_temp_new_i64(); 97328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_V0 = cpu_F0d; 97338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_V1 = cpu_F1d; 97348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: cpu_M0 can probably be the same as cpu_V0. */ 97355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_M0 = tcg_temp_new_i64(); 97368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; 97378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj = -1; 97388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns = 0; 97398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project max_insns = tb->cflags & CF_COUNT_MASK; 97408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (max_insns == 0) 97418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project max_insns = CF_COUNT_MASK; 97428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_icount_start(); 97448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_clear_temp_count(); 97465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 97475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* A note on handling of the condexec (IT) bits: 97485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 97495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * We want to avoid the overhead of having to write the updated condexec 9750e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner * bits back to the CPUARMState for every instruction in an IT block. So: 97515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (1) if the condexec bits are not already zero then we write 9752e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner * zero back into the CPUARMState now. This avoids complications trying 97535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to do it at the end of the block. (For example if we don't do this 97545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * it's hard to identify whether we can safely skip writing condexec 97555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * at the end of the TB, which we definitely want to do for the case 97565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * where a TB doesn't do anything with the IT state at all.) 97575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (2) if we are going to leave the TB then we call gen_set_condexec() 9758e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner * which will write the correct value into CPUARMState if zero is wrong. 97595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This is done both for leaving the TB at the end, and for leaving 97605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * it because of an exception we know will happen, which is done in 97615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * gen_exception_insn(). The latter is necessary because we need to 97625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * leave the TB with the PC/IT state just prior to execution of the 97635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * instruction which caused the exception. 97645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (3) if we leave the TB unexpectedly (eg a data abort on a load) 9765e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner * then the CPUARMState will be wrong and we need to reset it. 97665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This is handled in the same way as restoration of the 97675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * PC in these situations: we will be called again with search_pc=1 97685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * and generate a mapping of the condexec bits for each PC in 97695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * gen_opc_condexec_bits[]. restore_state_to_opc() then uses 97705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * this to restore the condexec bits. 97715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 97725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Note that there are no instructions which can read the condexec 97735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bits, and none which can write non-static values to them, so 9774e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner * we don't need to care about whether CPUARMState is correct in the 97755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * middle of a TB. 97765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 97775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 97785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Reset the conditional execution bits immediately. This avoids 97795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner complications trying to do it at the end of the block. */ 97805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dc->condexec_mask || dc->condexec_cond) 97815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { 97825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 97835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 97845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, condexec_bits); 97855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 97868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 97878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 97888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Intercept jump to the magic kernel page. */ 97898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->pc >= 0xffff0000) { 97908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We always get here via a jump, so know we are not in a 97918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional execution block. */ 97928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_KERNEL_TRAP); 97938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_UPDATE; 97948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 97978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->pc >= 0xfffffff0 && IS_M(env)) { 97988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We always get here via a jump, so know we are not in a 97998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional execution block. */ 98008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_EXCEPTION_EXIT); 98018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_UPDATE; 98028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 98038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 98058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9806a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { 9807a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QTAILQ_FOREACH(bp, &env->breakpoints, entry) { 98085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bp->pc == dc->pc) { 98095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(dc, 0, EXCP_DEBUG); 98108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Advance PC so that clearing the breakpoint will 98118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project invalidate this TB. */ 98128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc += 2; 98138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto done_generating; 98148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 98158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 9819288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner if (ANDROID_CHECK_CODEGEN_PC(search_pc)) { 9820975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; 98218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (lj < j) { 98228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj++; 98238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (lj < j) 9824975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_instr_start[lj++] = 0; 98258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9826975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_pc[lj] = dc->pc; 9827975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); 9828975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_instr_start[lj] = 1; 9829975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_icount[lj] = num_insns; 98308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) 98338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_io_start(); 98348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { 98365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_debug_insn_start(dc->pc); 98375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 98385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 98395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dc->thumb) { 98408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project disas_thumb_insn(env, dc); 98418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condexec_mask) { 9842a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_cond = (dc->condexec_cond & 0xe) 9843a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine | ((dc->condexec_mask >> 4) & 1); 9844a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f; 9845a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (dc->condexec_mask == 0) { 9846a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_cond = 0; 98478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 98508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project disas_arm_insn(env, dc); 98518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp && !dc->is_jmp) { 98548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 98558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 98568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 98585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (tcg_check_temp_count()) { 98595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc); 98605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 98615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 98625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Translation stops when a conditional branch is encountered. 98638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise the subsequent code could get translated several times. 98648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Also stop translation when a page boundary is reached. This 98658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ensures prefetch aborts occur at the right place. */ 98668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns ++; 9867975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end && 9868fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner !ENV_GET_CPU(env)->singlestep_enabled && 98695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner !singlestep && 98708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc < next_page_start && 98718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns < max_insns); 98728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tb->cflags & CF_LAST_IO) { 98748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 98758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: This can theoretically happen with self-modifying 98768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code. */ 98778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(env, "IO on conditional branch instruction"); 98788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_io_end(); 98808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* At this stage dc->condjmp will only be set when the skipped 98838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction was a conditional branch or trap, and the PC has 98848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project already been written. */ 9885fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner if (unlikely(ENV_GET_CPU(env)->singlestep_enabled)) { 98868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Make sure the pc is updated, and raise a debug exception. */ 98878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 98888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 98898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->is_jmp == DISAS_SWI) { 98908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 98915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (dc->is_jmp == DISAS_SMC) { 98925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 98938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 98948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_DEBUG); 98958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 98978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp || !dc->is_jmp) { 98998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dc->pc); 99008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 99018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 99038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->is_jmp == DISAS_SWI && !dc->condjmp) { 99048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 99055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) { 99065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 99078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 99088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: Single stepping a WFI insn will not halt 99098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the CPU. */ 99108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_DEBUG); 99118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 99138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* While branches must always occur at the end of an IT block, 99148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project there are a few other things that can cause us to terminate 99158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the TB in the middel of an IT block: 99168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Exception generating instructions (bkpt, swi, undefined). 99178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Page boundaries. 99188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Hardware watchpoints. 99198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Hardware breakpoints have already been handled and skip this code. 99208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 99218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 99228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(dc->is_jmp) { 99238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_NEXT: 99248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(dc, 1, dc->pc); 99258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 99268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 99278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_JUMP: 99288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_UPDATE: 99298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* indicate that the hash table must be used to find the next TB */ 99308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_exit_tb(0); 99318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 99328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_TB_JUMP: 99338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* nothing more to generate */ 99348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 99358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_WFI: 99360b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner gen_helper_wfi(cpu_env); 99378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 99388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_SWI: 99398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 99408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 99415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case DISAS_SMC: 99425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 99435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 99448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 99468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 99478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 99488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(dc, 1, dc->pc); 99498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 99508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 99538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdone_generating: 99548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_icount_end(tb, num_insns); 9955975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner *tcg_ctx.gen_opc_ptr = INDEX_op_end; 99568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 99578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS 99585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { 99595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("----------------\n"); 99605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("IN: %s\n", lookup_symbol(pc_start)); 99610dc43a9a7d4ed798d2c53792fe30a907f81d7615David 'Digit' Turner log_target_disas(env, pc_start, dc->pc - pc_start, dc->thumb); 99625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("\n"); 99638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 99658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (search_pc) { 9966975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; 99678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj++; 99688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (lj <= j) 9969975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner tcg_ctx.gen_opc_instr_start[lj++] = 0; 99708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 9971288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_END_CODEGEN(); 99728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb->size = dc->pc - pc_start; 99738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb->icount = num_insns; 99748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 99758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 99768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9977e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) 99788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 99798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_intermediate_code_internal(env, tb, 0); 99808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 99818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9982e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb) 99838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 99848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_intermediate_code_internal(env, tb, 1); 99858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 99868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 99878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char *cpu_mode_names[16] = { 99888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "usr", "fiq", "irq", "svc", "???", "???", "???", "abt", 99898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "???", "???", "???", "und", "???", "???", "???", "sys" 99908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 99918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9992e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf, 99938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int flags) 99948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 99958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 99968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 99978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 99988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t i; 99998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float s; 100008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } s0, s1; 100018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project CPU_DoubleU d; 100028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This assumes float64 and double have the same layout. 100038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Oh well, it's only debug dumps. */ 100048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 100058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float64 f64; 100068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project double d; 100078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } d0; 100088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 100098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t psr; 100108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 100118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 100128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]); 100138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((i % 4) == 3) 100148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "\n"); 100158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 100168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, " "); 100178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 100188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr = cpsr_read(env); 100198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n", 100208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr, 100218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 31) ? 'N' : '-', 100228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 30) ? 'Z' : '-', 100238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 29) ? 'C' : '-', 100248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 28) ? 'V' : '-', 100258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & CPSR_T ? 'T' : 'A', 100268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); 100278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 100288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 100298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 100308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d.d = env->vfp.regs[i]; 100318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s0.i = d.l.lower; 100328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s1.i = d.l.upper; 100338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d0.f64 = d.d; 100348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n", 100358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i * 2, (int)s0.i, s0.s, 100368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i * 2 + 1, (int)s1.i, s1.s, 100378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower, 100388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d0.d); 100398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 100408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); 100418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 100428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 100438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10044e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos) 100458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10046975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos]; 10047975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner env->condexec_bits = tcg_ctx.gen_opc_condexec_bits[pc_pos]; 100488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10049